LCOV - code coverage report
Current view: top level - drivers/drifuzz - drifuzz-pci.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 88 180 48.9 %
Date: 2022-04-01 13:59:58 Functions: 11 18 61.1 %
Branches: 25 91 27.5 %

           Branch data     Line data    Source code
       1                 :            : #include <linux/init.h>
       2                 :            : #include <linux/module.h>
       3                 :            : #include <linux/kernel.h>
       4                 :            : #include <linux/fs.h>
       5                 :            : #include <linux/ioport.h>       
       6                 :            : #include <linux/pci.h>
       7                 :            : #include <linux/delay.h>
       8                 :            : 
       9                 :            : MODULE_LICENSE("GPL");
      10                 :            : MODULE_AUTHOR("Zekun Shen");
      11                 :            : MODULE_DESCRIPTION("A command channel between linux guest and qemu host");
      12                 :            : MODULE_VERSION("0.01");
      13                 :            : 
      14                 :            : #define qemu_driver_name "Qemu driver"
      15                 :            : 
      16                 :            : static int device_open_count = 0;
      17                 :            : static int major_num;
      18                 :            : #define CMD_ADDR 0x8
      19                 :            : #define CMD_ARG1 0x10
      20                 :            : #define CMD_ARG2 0x18
      21                 :            : #define CMD_ARG3 0x20
      22                 :            : #define ACT 0x1
      23                 :            : #define READY_ADDR 0x30
      24                 :            : 
      25                 :            : #define INFO_START 0x40
      26                 :            : 
      27                 :            : /* shared */
      28                 :            : enum ACTIONS {
      29                 :            :         CONST_DMA_INIT = 1,
      30                 :            :         CONST_DMA_EXIT,
      31                 :            :         STREAM_DMA_INIT,
      32                 :            :         STREAM_DMA_EXIT,
      33                 :            :     EXEC_INIT,
      34                 :            :     EXEC_EXIT,
      35                 :            :     SUBMIT_STAGE,
      36                 :            :         SUBMIT_KCOV_TRACE,
      37                 :            :         KASAN,
      38                 :            :         REQ_RESET,
      39                 :            :         EXEC_TIMEOUT,
      40                 :            :         PROBE_FAIL,
      41                 :            : };
      42                 :            : 
      43                 :            : struct qemu_adapter {
      44                 :            :         void* hw_addr;
      45                 :            :         struct pci_dev *pdev;
      46                 :            : };
      47                 :            : 
      48                 :            : static struct qemu_adapter *adapter = NULL;
      49                 :            : 
      50                 :            : /* Handler */
      51                 :        222 : void handle_const_dma_init(uint64_t dma_addr, uint64_t addr, uint64_t size) {
      52         [ +  + ]:        222 :         if (adapter) {
      53                 :            :                 //printk(KERN_INFO "Get dma_init\n");
      54                 :         66 :                 writeq(CONST_DMA_INIT, adapter->hw_addr + CMD_ADDR);
      55                 :         66 :                 writeq(dma_addr, adapter->hw_addr + CMD_ARG1);
      56                 :         66 :                 writeq(addr, adapter->hw_addr + CMD_ARG2);
      57                 :         66 :                 writeq(size, adapter->hw_addr + CMD_ARG3);
      58                 :         66 :                 writeq(ACT, adapter->hw_addr);
      59                 :            :         }
      60                 :            :         else {
      61                 :            :                 //printk(KERN_INFO "Get dma_init: adapter not ready\n");
      62                 :        222 :         }
      63                 :        222 : }
      64                 :            : EXPORT_SYMBOL(handle_const_dma_init);
      65                 :            : 
      66                 :          0 : void handle_const_dma_exit(uint64_t dma_addr) {
      67         [ #  # ]:          0 :         if (adapter) {
      68                 :            :                 // printk(KERN_INFO "Get dma_exit\n");
      69                 :          0 :                 writeq(CONST_DMA_EXIT, adapter->hw_addr + CMD_ADDR);
      70                 :          0 :                 writeq(dma_addr, adapter->hw_addr + CMD_ARG1);
      71                 :          0 :                 writeq(ACT, adapter->hw_addr);
      72                 :            :         }
      73                 :          0 : }
      74                 :            : EXPORT_SYMBOL(handle_const_dma_exit);
      75                 :          0 : void handle_stream_dma_init(uint64_t dma_addr, uint64_t addr, uint64_t size) {
      76         [ #  # ]:          0 :         if (adapter) {
      77                 :            :                 //printk(KERN_INFO "Get dma_init\n");
      78                 :          0 :                 writeq(STREAM_DMA_INIT, adapter->hw_addr + CMD_ADDR);
      79                 :          0 :                 writeq(dma_addr, adapter->hw_addr + CMD_ARG1);
      80                 :          0 :                 writeq(addr, adapter->hw_addr + CMD_ARG2);
      81                 :          0 :                 writeq(size, adapter->hw_addr + CMD_ARG3);
      82                 :          0 :                 writeq(ACT, adapter->hw_addr);
      83                 :            :         }
      84                 :            :         else {
      85                 :            :                 //printk(KERN_INFO "Get dma_init: adapter not ready\n");
      86                 :          0 :         }
      87                 :          0 : }
      88                 :            : EXPORT_SYMBOL(handle_stream_dma_init);
      89                 :            : 
      90                 :          0 : void handle_stream_dma_exit(uint64_t dma_addr) {
      91         [ #  # ]:          0 :         if (adapter) {
      92                 :            :                 // printk(KERN_INFO "Get dma_exit\n");
      93                 :          0 :                 writeq(STREAM_DMA_EXIT, adapter->hw_addr + CMD_ADDR);
      94                 :          0 :                 writeq(dma_addr, adapter->hw_addr + CMD_ARG1);
      95                 :          0 :                 writeq(ACT, adapter->hw_addr);
      96                 :            :         }
      97                 :          0 : }
      98                 :            : EXPORT_SYMBOL(handle_stream_dma_exit);
      99                 :            : 
     100                 :         78 : static void handle_exec_init(void) {
     101                 :         78 :         printk(KERN_INFO "[GUEST_KERNEL] handle_exec_init\n");
     102         [ +  - ]:         78 :     if (adapter) {
     103                 :         78 :         writeq(EXEC_INIT, adapter->hw_addr + CMD_ADDR);
     104                 :         78 :                 writeq(ACT, adapter->hw_addr);
     105                 :         78 :                 writeq(ACT, adapter->hw_addr + READY_ADDR);
     106                 :            :     }
     107                 :         78 : }
     108                 :          0 : static void handle_exec_exit(void) {
     109                 :          0 :     if (adapter) {
     110                 :          0 :         writeq(EXEC_EXIT, adapter->hw_addr + CMD_ADDR);
     111                 :          0 :                 writeq(ACT, adapter->hw_addr);
     112                 :            :     }
     113                 :            : }
     114                 :          0 : static void handle_exec_timeout(void) {
     115                 :          0 :     if (adapter) {
     116                 :          0 :         writeq(EXEC_TIMEOUT, adapter->hw_addr + CMD_ADDR);
     117                 :          0 :                 writeq(ACT, adapter->hw_addr);
     118                 :            :     }
     119                 :            : }
     120                 :          0 : static void handle_submit_stage(uint64_t stage) {
     121                 :          0 :     if (adapter) {
     122                 :          0 :         writeq(SUBMIT_STAGE, adapter->hw_addr + CMD_ADDR);
     123                 :          0 :         writeq(stage, adapter->hw_addr + CMD_ARG1);
     124                 :          0 :                 writeq(ACT, adapter->hw_addr);
     125                 :            :     }
     126                 :            : }
     127                 :       1248 : void handle_submit_kcov_trace(uint64_t address, uint64_t size) {
     128         [ +  - ]:       1248 :     if (adapter) {
     129                 :       1248 :         writeq(SUBMIT_KCOV_TRACE, adapter->hw_addr + CMD_ADDR);
     130         [ +  - ]:       1248 :         writeq(virt_to_phys(address), adapter->hw_addr + CMD_ARG1);
     131                 :       1248 :                 writeq(size, adapter->hw_addr + CMD_ARG2);
     132                 :       1248 :                 writeq(ACT, adapter->hw_addr);
     133                 :            :     }
     134                 :       1248 : }
     135                 :            : EXPORT_SYMBOL(handle_submit_kcov_trace);
     136                 :            : 
     137                 :          0 : void handle_kasan(void) {
     138                 :          0 :         printk(KERN_INFO "handle_kasan\n");
     139         [ #  # ]:          0 :         if (adapter) {
     140                 :          0 :         writeq(KASAN, adapter->hw_addr + CMD_ADDR);
     141                 :          0 :                 writeq(ACT, adapter->hw_addr);
     142                 :            :         }
     143                 :          0 : }
     144                 :            : EXPORT_SYMBOL(handle_kasan);
     145                 :            : 
     146                 :          0 : void handle_req_reset(void) {
     147                 :          0 :         printk(KERN_INFO "handle_reset\n");
     148         [ #  # ]:          0 :         if (adapter) {
     149                 :          0 :         writeq(REQ_RESET, adapter->hw_addr + CMD_ADDR);
     150                 :          0 :                 writeq(ACT, adapter->hw_addr);
     151                 :            :         }
     152                 :          0 : }
     153                 :            : 
     154                 :        201 : void probe_fail(void) {
     155                 :        201 :         printk(KERN_INFO "probe_fail\n");
     156         [ +  + ]:        201 :         if (adapter) {
     157                 :         45 :         writeq(PROBE_FAIL, adapter->hw_addr + CMD_ADDR);
     158                 :         45 :                 writeq(ACT, adapter->hw_addr);
     159                 :            :         }
     160                 :        201 : }
     161                 :            : EXPORT_SYMBOL(probe_fail);
     162                 :            : 
     163                 :         78 : static int handle_command(void* buffer, size_t len) {
     164                 :         78 :         uint64_t *pbuffer;
     165                 :         78 :         uint64_t cmd;
     166                 :         78 :         uint64_t *argv;
     167                 :         78 :         int argc;
     168                 :         78 :         size_t nread = 0;
     169                 :         78 :         pbuffer = (uint64_t *)buffer;
     170   [ +  -  +  - ]:         78 :         if (len == 0 || len % 8) {
     171                 :            :                 return -EINVAL;
     172                 :            :         }
     173                 :            :         
     174                 :         78 :         cmd = *pbuffer;
     175                 :         78 :         nread += 8;
     176                 :         78 :         argv = pbuffer + 1;
     177                 :         78 :         argc = (len - 8) / 8;
     178   [ -  -  -  -  :         78 :         switch (cmd)
          +  -  -  -  -  
                   -  - ]
     179                 :            :         {
     180                 :          0 :         case CONST_DMA_INIT:
     181         [ #  # ]:          0 :                 WARN_ON(len != 0x20);
     182                 :          0 :                 handle_const_dma_init(argv[0], argv[1], argv[2]);
     183                 :          0 :                 return 0x20;
     184                 :          0 :         case CONST_DMA_EXIT:
     185         [ #  # ]:          0 :                 WARN_ON(len != 0x10);
     186         [ #  # ]:          0 :                 handle_const_dma_exit(argv[0]);
     187                 :            :                 return 0x10;
     188                 :          0 :         case STREAM_DMA_INIT:
     189         [ #  # ]:          0 :                 WARN_ON(len != 0x20);
     190                 :          0 :                 handle_stream_dma_init(argv[0], argv[1], argv[2]);
     191                 :          0 :                 return 0x20;
     192                 :          0 :         case STREAM_DMA_EXIT:
     193         [ #  # ]:          0 :                 WARN_ON(len != 0x10);
     194         [ #  # ]:          0 :                 handle_stream_dma_exit(argv[0]);
     195                 :            :                 return 0x10;
     196                 :         78 :     case EXEC_INIT:
     197         [ -  + ]:         78 :         WARN_ON(len!= 0x8);
     198                 :         78 :         handle_exec_init();
     199                 :         78 :         return 0x8;
     200                 :          0 :     case EXEC_EXIT:
     201         [ #  # ]:          0 :         WARN_ON(len!= 0x8);
     202         [ #  # ]:          0 :         handle_exec_exit();
     203                 :            :         return 0x8;
     204                 :          0 :     case SUBMIT_STAGE:
     205         [ #  # ]:          0 :         WARN_ON(len!= 0x10);
     206         [ #  # ]:          0 :         handle_submit_stage(argv[0]);
     207                 :            :         return 0x10;
     208                 :          0 :         case SUBMIT_KCOV_TRACE:
     209         [ #  # ]:          0 :                 WARN_ON(len!= 0x18);
     210                 :          0 :                 handle_submit_kcov_trace(argv[0], argv[1]);
     211                 :          0 :                 return 0x18;
     212                 :          0 :         case REQ_RESET:
     213         [ #  # ]:          0 :                 WARN_ON(len != 0x8);
     214                 :          0 :                 handle_req_reset();
     215                 :          0 :                 return 0x8;
     216                 :          0 :         case EXEC_TIMEOUT:
     217         [ #  # ]:          0 :                 WARN_ON(len != 0x8);
     218         [ #  # ]:          0 :                 handle_exec_timeout();
     219                 :            :                 return 0x8;
     220                 :          0 :         default:
     221                 :          0 :                 printk(KERN_INFO "Unknow action\n");
     222                 :          0 :                 return 0x4;
     223                 :            :         }
     224                 :            :         return 0;
     225                 :            : }
     226                 :            : 
     227                 :            : /* File ops */
     228                 :         78 : static ssize_t device_write(struct file *flip, const char *buffer, size_t len,
     229                 :            :                 loff_t *offset) {
     230                 :            :         //uint64_t *p = (uint64_t*) buffer;
     231                 :         78 :         *offset = 0;
     232                 :         78 :         int num = 0;
     233         [ -  + ]:         78 :         void *kbuf = kmalloc(len, GFP_KERNEL);
     234   [ -  +  +  - ]:        156 :         if (copy_from_user(kbuf, buffer, len)) {
     235                 :            :                 return -EIO;
     236                 :            :         }
     237         [ +  - ]:         78 :         if ((num = handle_command(kbuf, len)) == 0) {
     238                 :            :                 return -EINVAL;
     239                 :            :         }
     240                 :         78 :         return num;
     241                 :            :         
     242                 :            : }
     243                 :            : 
     244                 :        312 : static ssize_t device_read(struct file *flip, char *buffer, size_t len, 
     245                 :            :                 loff_t *offset) {
     246                 :        312 :         size_t off;
     247         [ -  + ]:        312 :         void *kbuf = kmalloc(len, GFP_KERNEL);
     248         [ +  - ]:        312 :         if (!adapter)
     249                 :            :                 return -EINVAL;
     250         [ +  + ]:       2496 :         for (off = 0; off < len; off++) {
     251                 :       2184 :                 *(char*)(kbuf + off) = readb(adapter->hw_addr + INFO_START + *offset + off);
     252                 :            :         }
     253   [ -  +  +  - ]:        624 :         if (copy_to_user(buffer, kbuf, len)) {
     254                 :            :                 return -EIO;
     255                 :            :         }
     256                 :        312 :         *offset += len;
     257                 :        312 :         return len;
     258                 :            : }
     259                 :            : 
     260                 :        156 : static int device_open(struct inode *inode, struct file *file) {
     261         [ +  - ]:        156 :         if (device_open_count) {
     262                 :            :                 return -EBUSY;
     263                 :            :         }
     264                 :        156 :         device_open_count++;
     265                 :        156 :         try_module_get(THIS_MODULE);
     266                 :        156 :         return 0;
     267                 :            : }
     268                 :            : 
     269                 :        156 : static int device_release(struct inode *inode, struct file *file) {
     270                 :        156 :         device_open_count--;
     271                 :        156 :         module_put(THIS_MODULE);
     272                 :        156 :         return 0;
     273                 :            : }
     274                 :            : 
     275                 :            : static struct file_operations file_ops = {
     276                 :            :         .read = device_read,
     277                 :            :         .write = device_write,
     278                 :            :         .open = device_open,
     279                 :            :         .release = device_release
     280                 :            : };
     281                 :            : 
     282                 :            : /* File ops end */
     283                 :            : 
     284                 :            : /* PCI */
     285                 :         78 : static int qemu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) {
     286                 :         78 :         printk(KERN_INFO "Qemu probe\n Hello!\n");
     287                 :         78 :         int err;
     288                 :            :         // int bars;
     289                 :            :         //bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
     290         [ +  - ]:         78 :         if ((err = pci_enable_device(pdev)))
     291                 :            :                 return err;
     292                 :            : 
     293                 :            :         // if ((err = pci_request_selected_regions(pdev, bars, qemu_driver_name)))
     294                 :            :         //      goto somewhere1;
     295                 :            :         
     296                 :            :         // pci_set_master(pdev);
     297                 :            :         // if ((err = pci_save_state(pdev))) {
     298                 :            :         //      goto somewhere2;
     299                 :            :         // }
     300                 :         78 :         adapter = kmalloc(sizeof(struct qemu_adapter), GFP_KERNEL);
     301                 :         78 :         adapter->pdev = pdev;
     302                 :         78 :         adapter->hw_addr = pci_ioremap_bar(pdev, 0);
     303                 :         78 :         pci_set_drvdata(pdev, adapter);
     304                 :            : 
     305                 :            :         // Test code for dma
     306                 :            :         /*
     307                 :            :         dma_addr_t dma_handle;
     308                 :            :         void *const_dma_region;
     309                 :            :         void *stream_dma_region;
     310                 :            :         const_dma_region =
     311                 :            :                         dma_alloc_coherent(&pdev->dev, 0x1000, &dma_handle, GFP_KERNEL);
     312                 :            : 
     313                 :            :         *(char*)const_dma_region = 'A';
     314                 :            :         *((char*)const_dma_region + 0x111) = 'A';
     315                 :            :         dma_free_coherent(&pdev->dev, 0x1000, const_dma_region, dma_handle);
     316                 :            : 
     317                 :            : 
     318                 :            :         stream_dma_region = kmalloc(0x101, GFP_KERNEL);
     319                 :            :         *((char*)stream_dma_region + 0x100) = '\x00';
     320                 :            :         dma_handle = dma_map_single(&pdev->dev, stream_dma_region, 0x100, DMA_FROM_DEVICE);
     321                 :            : 
     322                 :            :         if (dma_mapping_error(&pdev->dev, dma_handle)) {
     323                 :            :                 pr_info("dma_map_single() failed\n");
     324                 :            :         } else {
     325                 :            :                 pr_info("dma_map_single() succeeded");
     326                 :            :         }
     327                 :            :         dma_unmap_single(&pdev->dev, dma_handle, 0x100, DMA_FROM_DEVICE);
     328                 :            :         // udelay(100);
     329                 :            :         printk(KERN_INFO "stream dma data: %s\n", (char*)stream_dma_region);
     330                 :            :         kfree(stream_dma_region);
     331                 :            :         */
     332                 :         78 :         return 0;
     333                 :            : }
     334                 :            : 
     335                 :          0 : static void qemu_remove(struct pci_dev *pdev) {
     336                 :            :         //pci_release_selected_regions(pdev, bars);
     337                 :          0 :         kfree(pci_get_drvdata(pdev));
     338                 :          0 :         pci_disable_device(pdev);
     339                 :          0 : }
     340                 :            : 
     341                 :            : static const struct pci_device_id qemu_pci_tbl[] = {
     342                 :            :         {PCI_DEVICE(0x7777, 0x7777)},
     343                 :            :         {}
     344                 :            : };
     345                 :            : static struct pci_driver qemu_driver = {
     346                 :            :         .name           = qemu_driver_name,
     347                 :            :         .id_table       = qemu_pci_tbl,
     348                 :            :         .probe          = qemu_probe,
     349                 :            :         .remove         = qemu_remove,
     350                 :            : };
     351                 :            : 
     352                 :            : /* PCI ends */
     353                 :            : 
     354                 :            : /* Module */
     355                 :         78 : int __init qemu_init_module(void) {
     356                 :         78 :         int ret;
     357                 :         78 :         printk(KERN_INFO "Qemu init\n Hello!\n");
     358         [ -  + ]:         78 :         if ((ret = pci_register_driver(&qemu_driver)) != 0) {
     359                 :          0 :                 printk(KERN_ALERT "Could not register pci: %d\b", ret);
     360                 :          0 :                 return ret;
     361                 :            :         }
     362                 :         78 :         major_num = register_chrdev(0, qemu_driver_name, &file_ops);
     363         [ -  + ]:         78 :         if (major_num < 0) {
     364                 :          0 :                 printk(KERN_ALERT "Could not register device: %d\n", major_num);
     365                 :          0 :                 return major_num;
     366                 :            :         } else {
     367                 :         78 :                 printk(KERN_INFO "Qemu module loaded with major %d\n", major_num);
     368                 :         78 :                 return 0;
     369                 :            :         }
     370                 :            : }
     371                 :            : module_init(qemu_init_module);
     372                 :            : 
     373                 :          0 : void __exit qemu_exit_module(void) {
     374                 :          0 :         unregister_chrdev(major_num, qemu_driver_name);
     375                 :          0 :         printk(KERN_INFO "Qemu exit\n Goodbye!\n");
     376                 :          0 : }
     377                 :            : 
     378                 :            : module_exit(qemu_exit_module);
     379                 :            : /* Module ends */

Generated by: LCOV version 1.14