LCOV - code coverage report
Current view: top level - spdk/test/env/pci - pci_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 106 112 94.6 %
Date: 2024-07-12 17:53:22 Functions: 11 11 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 17 28 60.7 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "CUnit/Basic.h"
       9                 :            : #include "spdk_internal/mock.h"
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : 
      12                 :            : #include "env_dpdk/pci.c"
      13                 :            : 
      14                 :            : static void
      15                 :         20 : pci_claim_test(struct spdk_pci_device *dev)
      16                 :            : {
      17                 :         20 :         int rc = 0;
      18                 :            :         pid_t childPid;
      19                 :          9 :         int status, ret;
      20                 :            : 
      21                 :         20 :         rc = spdk_pci_device_claim(dev);
      22                 :         20 :         CU_ASSERT(rc >= 0);
      23                 :            : 
      24                 :         20 :         childPid = fork();
      25                 :         40 :         CU_ASSERT(childPid >= 0);
      26         [ +  + ]:         40 :         if (childPid == 0) {
      27                 :         20 :                 ret = spdk_pci_device_claim(dev);
      28                 :         20 :                 CU_ASSERT(ret == -1);
      29                 :         20 :                 exit(0);
      30                 :            :         } else {
      31                 :         20 :                 waitpid(childPid, &status, 0);
      32                 :            :         }
      33                 :         20 : }
      34                 :            : 
      35                 :            : static struct spdk_pci_driver ut_pci_driver;
      36                 :            : 
      37                 :            : struct ut_pci_dev {
      38                 :            :         struct spdk_pci_device pci;
      39                 :            :         char config[16];
      40                 :            :         char bar[16];
      41                 :            :         bool attached;
      42                 :            : };
      43                 :            : 
      44                 :            : static int
      45                 :         40 : ut_map_bar(struct spdk_pci_device *dev, uint32_t bar,
      46                 :            :            void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
      47                 :            : {
      48                 :         40 :         struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
      49                 :            : 
      50                 :            :         /* just one bar */
      51         [ +  + ]:         40 :         if (bar > 0) {
      52                 :         20 :                 return -1;
      53                 :            :         }
      54                 :            : 
      55                 :         20 :         *mapped_addr = ut_dev->bar;
      56                 :         20 :         *phys_addr = 0;
      57                 :         20 :         *size = sizeof(ut_dev->bar);
      58                 :         20 :         return 0;
      59                 :            : }
      60                 :            : 
      61                 :            : static int
      62                 :         20 : ut_unmap_bar(struct spdk_pci_device *device, uint32_t bar, void *addr)
      63                 :            : {
      64                 :         20 :         return 0;
      65                 :            : }
      66                 :            : 
      67                 :            : static int
      68                 :         60 : ut_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
      69                 :            : {
      70                 :         60 :         struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
      71                 :            : 
      72         [ +  + ]:         60 :         if (len + offset >= sizeof(ut_dev->config)) {
      73                 :         20 :                 return -1;
      74                 :            :         }
      75                 :            : 
      76   [ -  +  -  + ]:         40 :         memcpy(value, (void *)((uintptr_t)ut_dev->config + offset), len);
      77                 :         40 :         return 0;
      78                 :            : }
      79                 :            : 
      80                 :            : static int
      81                 :         40 : ut_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
      82                 :            : {
      83                 :         40 :         struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
      84                 :            : 
      85         [ -  + ]:         40 :         if (len + offset >= sizeof(ut_dev->config)) {
      86                 :          0 :                 return -1;
      87                 :            :         }
      88                 :            : 
      89   [ -  +  -  + ]:         40 :         memcpy((void *)((uintptr_t)ut_dev->config + offset), value, len);
      90                 :         40 :         return 0;
      91                 :            : }
      92                 :            : 
      93                 :            : 
      94                 :            : static int
      95                 :         20 : ut_enum_cb(void *ctx, struct spdk_pci_device *dev)
      96                 :            : {
      97                 :         20 :         struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
      98                 :            : 
      99                 :         20 :         ut_dev->attached = true;
     100                 :         20 :         return 0;
     101                 :            : }
     102                 :            : 
     103                 :            : static int
     104                 :         20 : ut_attach_cb(const struct spdk_pci_addr *addr)
     105                 :            : {
     106                 :         20 :         return -ENODEV;
     107                 :            : }
     108                 :            : 
     109                 :            : static void
     110                 :         20 : ut_detach_cb(struct spdk_pci_device *dev)
     111                 :            : {
     112                 :         20 : }
     113                 :            : 
     114                 :            : static struct spdk_pci_device_provider g_ut_provider = {
     115                 :            :         .name = "custom",
     116                 :            :         .attach_cb = ut_attach_cb,
     117                 :            :         .detach_cb = ut_detach_cb,
     118                 :            : };
     119                 :            : 
     120                 :         20 : SPDK_PCI_REGISTER_DEVICE_PROVIDER(ut, &g_ut_provider);
     121                 :            : 
     122                 :            : static void
     123                 :         20 : pci_hook_test(void)
     124                 :            : {
     125                 :         20 :         struct ut_pci_dev ut_dev = {};
     126                 :          9 :         uint32_t value_32;
     127                 :          9 :         void *bar0_vaddr;
     128                 :          9 :         uint64_t bar0_paddr, bar0_size;
     129                 :            :         int rc;
     130                 :            : 
     131                 :         20 :         ut_dev.pci.type = "custom";
     132                 :         20 :         ut_dev.pci.id.vendor_id = 0x4;
     133                 :         20 :         ut_dev.pci.id.device_id = 0x8;
     134                 :            : 
     135                 :            :         /* Use add parse for initialization */
     136                 :         20 :         spdk_pci_addr_parse(&ut_dev.pci.addr, "10000:00:01.0");
     137                 :         20 :         CU_ASSERT(ut_dev.pci.addr.domain == 0x10000);
     138                 :         20 :         CU_ASSERT(ut_dev.pci.addr.bus == 0x0);
     139                 :         20 :         CU_ASSERT(ut_dev.pci.addr.dev == 0x1);
     140                 :         20 :         CU_ASSERT(ut_dev.pci.addr.func == 0x0);
     141                 :            : 
     142                 :         20 :         ut_dev.pci.map_bar = ut_map_bar;
     143                 :         20 :         ut_dev.pci.unmap_bar = ut_unmap_bar;
     144                 :         20 :         ut_dev.pci.cfg_read = ut_cfg_read;
     145                 :         20 :         ut_dev.pci.cfg_write = ut_cfg_write;
     146                 :            : 
     147                 :            :         /* hook the device into the PCI layer */
     148                 :         20 :         rc = spdk_pci_hook_device(&ut_pci_driver, &ut_dev.pci);
     149                 :         20 :         CU_ASSERT_EQUAL(rc, 0);
     150                 :            : 
     151                 :            :         /* try to attach a device with the matching driver and bdf */
     152                 :         20 :         rc = spdk_pci_device_attach(&ut_pci_driver, ut_enum_cb, NULL, &ut_dev.pci.addr);
     153                 :         20 :         CU_ASSERT(rc == 0);
     154         [ -  + ]:         20 :         CU_ASSERT(ut_dev.pci.internal.attached);
     155         [ -  + ]:         20 :         CU_ASSERT(ut_dev.attached);
     156                 :            : 
     157                 :            :         /* check PCI config writes and reads */
     158                 :         20 :         value_32 = 0xDEADBEEF;
     159                 :         20 :         rc = spdk_pci_device_cfg_write32(&ut_dev.pci, value_32, 0);
     160                 :         20 :         CU_ASSERT(rc == 0);
     161                 :            : 
     162                 :         20 :         value_32 = 0x0BADF00D;
     163                 :         20 :         rc = spdk_pci_device_cfg_write32(&ut_dev.pci, value_32, 4);
     164                 :         20 :         CU_ASSERT(rc == 0);
     165                 :            : 
     166                 :         20 :         rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, 0);
     167                 :         20 :         CU_ASSERT(rc == 0);
     168                 :         20 :         CU_ASSERT(value_32 == 0xDEADBEEF);
     169                 :         20 :         CU_ASSERT(memcmp(&value_32, &ut_dev.config[0], 4) == 0);
     170                 :            : 
     171                 :         20 :         rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, 4);
     172                 :         20 :         CU_ASSERT(rc == 0);
     173                 :         20 :         CU_ASSERT(value_32 == 0x0BADF00D);
     174                 :         20 :         CU_ASSERT(memcmp(&value_32, &ut_dev.config[4], 4) == 0);
     175                 :            : 
     176                 :            :         /* out-of-bounds write */
     177                 :         20 :         rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, sizeof(ut_dev.config));
     178                 :         20 :         CU_ASSERT(rc != 0);
     179                 :            : 
     180                 :            :         /* map a bar */
     181                 :         20 :         rc = spdk_pci_device_map_bar(&ut_dev.pci, 0, &bar0_vaddr, &bar0_paddr, &bar0_size);
     182                 :         20 :         CU_ASSERT(rc == 0);
     183                 :         20 :         CU_ASSERT(bar0_vaddr == ut_dev.bar);
     184                 :         20 :         CU_ASSERT(bar0_size == sizeof(ut_dev.bar));
     185                 :         20 :         spdk_pci_device_unmap_bar(&ut_dev.pci, 0, bar0_vaddr);
     186                 :            : 
     187                 :            :         /* map an inaccessible bar */
     188                 :         20 :         rc = spdk_pci_device_map_bar(&ut_dev.pci, 1, &bar0_vaddr, &bar0_paddr, &bar0_size);
     189                 :         20 :         CU_ASSERT(rc != 0);
     190                 :            : 
     191                 :            :         /* test spdk_pci_device_claim() */
     192                 :         20 :         pci_claim_test(&ut_dev.pci);
     193                 :            : 
     194                 :         20 :         spdk_pci_device_detach(&ut_dev.pci);
     195         [ -  + ]:         20 :         CU_ASSERT(!ut_dev.pci.internal.attached);
     196                 :            : 
     197                 :            :         /* unhook the device */
     198                 :         20 :         spdk_pci_unhook_device(&ut_dev.pci);
     199                 :            : 
     200                 :            :         /* try to attach the same device again */
     201                 :         20 :         rc = spdk_pci_device_attach(&ut_pci_driver, ut_enum_cb, NULL, &ut_dev.pci.addr);
     202                 :         20 :         CU_ASSERT(rc != 0);
     203                 :         20 : }
     204                 :            : 
     205                 :            : int
     206                 :         20 : main(int argc, char **argv)
     207                 :            : {
     208                 :         20 :         CU_pSuite       suite = NULL;
     209                 :            :         unsigned int    num_failures;
     210                 :            : 
     211         [ -  + ]:         20 :         if (CU_initialize_registry() != CUE_SUCCESS) {
     212                 :          0 :                 return CU_get_error();
     213                 :            :         }
     214                 :            : 
     215                 :         20 :         suite = CU_add_suite("pci", NULL, NULL);
     216         [ -  + ]:         20 :         if (suite == NULL) {
     217                 :          0 :                 CU_cleanup_registry();
     218                 :          0 :                 return CU_get_error();
     219                 :            :         }
     220                 :            : 
     221         [ -  + ]:         20 :         if (
     222                 :         20 :                 CU_add_test(suite, "pci_hook", pci_hook_test) == NULL
     223                 :            :         ) {
     224                 :          0 :                 CU_cleanup_registry();
     225                 :          0 :                 return CU_get_error();
     226                 :            :         }
     227                 :            : 
     228                 :         20 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     229                 :         20 :         CU_cleanup_registry();
     230                 :         20 :         return num_failures;
     231                 :            : }

Generated by: LCOV version 1.14