IOMMU 虚拟IO地址和物理地址相关联

RC ---------- 808 ------------- NVIDIA

NT                             Up

Link Side                   Virtual Side

服务器通过非透明桥片与NVIDIA Xavier模组相连。

NVIDIA端申请IOVA地址。

#if  1
                int ret;
                int page_num=4;
                struct device *cdev=&(pdev->dev.parent);

                //printk("2222 cdev=0x%x\n",cdev);
                struct iommu_domain *domain = iommu_get_domain_for_dev(cdev);
                struct iova_domain *iovad=(struct iova_domain *)domain->iova_cookie;
                struct iova *iova = NULL;
                unsigned long shift, iova_len;
                shift = iova_shift(iovad);
                printk("shift=%d\n",shift);

                iova = alloc_iova(iovad, page_num, cdev->coherent_dma_mask >> shift, 1);

                (iova =iommu_dma_alloc_iova(cdev, BAR0_SIZE, cdev->coherent_dma_mask);可以用iommu_dma_alloc_iova申请iova,但是这个函数在内核中没有EXPORT——SYMBOL,所以在内核ko中使用不了,分析iommu_dma_alloc_iova函数,发现可以使用alloc_iova代替。如果不是编译内核ko,而是直接编译到内核,则可以使用iommu_dma_alloc_iova
                if (iova)
                        printk("GET IOVA 0x%llx\n" ,(dma_addr_t) iova->pfn_lo << shift);
                else
                        printk("alloc iova failed!\n");
                VIRTUAL_SIDE_MEM_PHYSICAL_ADDRESS_1=(dma_addr_t) iova->pfn_lo <<shift;


                struct page *bar2_ram_page = alloc_pages(GFP_KERNEL, 1);
                //VIRTUAL_SIDE_MEM_PHYSICAL_ADDRESS_1 = page_to_phys(bar2_ram_page);
                printk("alloc RAM phys: 0x%llx\n",page_to_phys(bar2_ram_page));
                ret = iommu_map(domain,(dma_addr_t) iova->pfn_lo <<shift,page_to_phys(bar2_ram_page),PAGE_SIZE,IOMMU_READ | IOMMU_WRITE);
                if (ret) {
                        printk("iommu_map(RAM) failed: %d\n",ret);
                }
                // struct page *bar4_ram_page = alloc_pages(GFP_KERNEL, 1);
                  //               VIRTUAL_SIDE_MEM_PHYSICAL_ADDRESS_2 = page_to_phys(bar4_ram_page);
                // printk("alloc RAM2 phys: 0x%llx\n",VIRTUAL_SIDE_MEM_PHYSICAL_ADDRESS_2);
#else
        struct device *cdev=&(pdev->dev);
        dma_addr_t bar0_iova;
        void *bar2_ram_map;
        dma_addr_t bar2_iova;
        bar2_ram_map = dma_alloc_coherent(cdev, 1024*4,&bar2_iova,GFP_KERNEL);
        if(!bar2_ram_map)
                printk("dma_alloc_coherent failed!\n");
        else
                printk("@@@bar2_ram_map=0x%llx bar2_iova=0x%llx,PHY:0x%llx\n",bar2_ram_map,bar2_iova,__pa(bar2_ram_map));
        VIRTUAL_SIDE_MEM_PHYSICAL_ADDRESS_1=bar2_iova;
#endif

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#lspci -v

0005:01:00.0 Bridge: Pericom Semiconductor Device 8608
        Subsystem: Pericom Semiconductor Device 8608
        Flags: bus master, fast devsel, latency 0
        Memory at 1f40200000 (32-bit, non-prefetchable) [size=128K]
        Memory at 1f40000000 (32-bit, non-prefetchable) [size=1M]                            (修改桥片bar空间大小只能烧EEPROM,X86是在BIOS中对PCI设备进行扫描)
        Memory at 1f40100000 (32-bit, non-prefetchable) [size=1M]
        Capabilities: [40] Power Management version 3
        Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [68] Express Endpoint, MSI 00
        Capabilities: [a4] Subsystem: Pericom Semiconductor Device 8608
        Capabilities: [c8] Vendor Specific Information: Len=38 <?>
        Capabilities: [100] Device Serial Number 00-00-00-00-00-00-00-00
        Capabilities: [fb4] Advanced Error Reporting
        Capabilities: [138] Power Budgeting <?>
        Capabilities: [148] Virtual Channel

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

验证流程(两个NVIDIA Xavier模组通过非透明桥片互联,且都设置为RC)
1.首先在link side和virtual side使用lspci命令查看是否查看到达尔的桥片。
link side如下:
root@dsp:~# lspci
0001:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad2 (rev a1)
0001:01:00.0 SATA controller: Marvell Technology Group Ltd. Device 9171 (rev 13)
0005:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad0 (rev a1)
0005:01:00.0 Bridge: Pericom Semiconductor Device 8608
virtual side如下:
root@dsp:/home/dsp/1223/driver/virtual# lspci
0005:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad0 (rev a1)
0005:01:00.0 PCI bridge: Pericom Semiconductor Device 8608
0005:02:01.0 PCI bridge: Pericom Semiconductor Device 8608
0005:03:00.0 Bridge: Pericom Semiconductor Device 8608

2.link side首先insmod pscgrande.ko
3.virtual side再insmod pscgrande.ko
4.link side 使用lspci -v查看bar2地址为1f40000000。

0005:01:00.0 Bridge: Pericom Semiconductor Device 8608
        Subsystem: Pericom Semiconductor Device 8608
        Flags: bus master, fast devsel, latency 0, IRQ 39
        Memory at 1f40200000 (32-bit, non-prefetchable) [size=128K]
        Memory at 1f40000000 (32-bit, non-prefetchable) [size=1M]
        Memory at 1f40100000 (32-bit, non-prefetchable) [size=1M]
        Capabilities: [40] Power Management version 3
        Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [68] Express Endpoint, MSI 00
        Capabilities: [a4] Subsystem: Pericom Semiconductor Device 8608
        Capabilities: [c8] Vendor Specific Information: Len=38 <?>
        Capabilities: [100] Device Serial Number 00-00-00-00-00-00-00-00
        Capabilities: [fb4] Advanced Error Reporting
        Capabilities: [138] Power Budgeting <?>
        Capabilities: [148] Virtual Channel
        Kernel driver in use: psc8608

  使用busybox devmem (0x1f40000000加上偏移0xf8000) 32 0x12345678---->0xf8000是virtual side申请的iova的低20位(iova地址为0xffff8000),高12位配置到桥片的TBR寄存器
5.virtual side 
root@dsp:/home/dsp/1223/driver/virtual# busybox devmem 0x84c134000---->0x84c134000是virtual side申请的物理地址,读出来与link side写入的数据相同
0x12345678

-----------------------------------------------------------------------------------------------------桥片主要配置了TBR和BDF表-------------------------------------------------------------------------------------------------------------

link side dmesg:

[ 6097.518402] pscgrande: loading out-of-tree module taints kernel.
[ 6097.520561] pscgrande: Initialization started
[ 6097.521321] pscgrande_probe(424): pDriver 0xffffffc7b4af9000
[ 6097.521513] pscgrande_probe(436): ID = 860812D8
[ 6097.521788] pscgrande_probe(463): got pci resource: bar 0 physical address(0x1f40200000)
[ 6097.522566] pscgrande_probe(470): bar 0 physical remap to virt: 0xffffff8024940000
[ 6097.522713] pscgrande_probe(471): bar 0 length: 131072
[ 6097.522830] pscgrande_probe(479): CDEP found
[ 6097.522916] pscgrande_probe(490): got pci resource: bar 2 physical address(0x1f40000000)
[ 6097.524422] pscgrande_probe(497): bar 2 physical remap to virt: 0xffffff8024a00000
[ 6097.524921] pscgrande_probe(498): bar 2 length: 1048576
[ 6097.525214] ProbeReqID(296): ReqID(W) = 0000 [b:00 s:00 f:0]
[ 6097.525363] NtLutAdd(381): Added Req ID (0000) to LUT #0
[ 6097.525618] ProbeReqID(296): ReqID(R) = 0000 [b:00 s:00 f:0]
[ 6097.525737] NtLutAdd(381): Added Req ID (0000) to LUT #1
[ 6097.525878] pscgrande_probe(532): request_irq succeeded. irq = 39
[ 6097.526015] pscgrande_probe(541): read scatchpad  0 = 00000000
[ 6097.528817] pscgrande_probe(546): write scatchpad  0 = 860612D8
[ 6097.534019] pscgrande_probe(541): read scatchpad  1 = 00000000
[ 6097.540055] pscgrande_probe(546): write scatchpad  1 = 860612D8
[ 6097.546100] pscgrande_probe(541): read scatchpad  2 = 00000000
[ 6097.552184] pscgrande_probe(546): write scatchpad  2 = 860612D8
[ 6097.557928] pscgrande_probe(541): read scatchpad  3 = 00000000
[ 6097.564367] pscgrande_probe(546): write scatchpad  3 = 860612D8
[ 6097.570151] pscgrande_probe(541): read scatchpad  4 = 00000000
[ 6097.575982] pscgrande_probe(546): write scatchpad  4 = 860612D8
[ 6097.581674] pscgrande_probe(541): read scatchpad  5 = 00000000
[ 6097.587801] pscgrande_probe(546): write scatchpad  5 = 860612D8
[ 6097.593385] pscgrande_probe(541): read scatchpad  6 = 00000000
[ 6097.599567] pscgrande_probe(546): write scatchpad  6 = 860612D8
[ 6097.605237] pscgrande_probe(541): read scatchpad  7 = 00000000
[ 6097.611133] pscgrande_probe(546): write scatchpad  7 = 860612D8
[ 6097.617493] pscgrande_probe(579): 0xC64  = 00007FFF
[ 6097.622376] pscgrande: Class created
[ 6097.625310] pscgrande: alloc ffffffc7b4af9000
[ 6173.258553] t19x-arm-smmu 12000000.iommu: Unhandled context fault: smmu0, iova=0x00000000, fsynr=0x3c0001, cb=3, sid=91(0x5b - PCIE5), pgd=0, pud=0, pmd=0, pte=0
[ 6173.259508] mc-err: (255) csr_pcie5r: EMEM address decode error
[ 6173.259746] mc-err:   status = 0x200640e2; addr = 0xffffffff00; hi_adr_reg=ff08
[ 6173.259897] mc-err:   secure: yes, access-type: read
[ 6173.260018] mc-err: mcerr: unknown intr source intstatus = 0x00000000, intstatus_1 = 0x00000000
[ 6173.270876] pscgrande_cdep_interrupt(115): irq = 39   pdx 0xffffffc7b4af9000
[ 6173.271047] pscgrande_cdep_interrupt(116): isLink  = 1
[ 6173.271188] pscgrande_cdep_interrupt(119): 0x11C5C  = 00008000
[ 6173.271338] @@@@ TBR2 nValue=0xffff8000
[ 6173.271349] @@@@ TBR3 nValue=0x0

virtual side dmesg:

[ 6170.378112] pscgrande: loading out-of-tree module taints kernel.
[ 6170.379468] pscgrande: Initialization started
[ 6170.380008] shift=12
[ 6170.380018] GET IOVA 0xffff8000
[ 6170.380026] alloc RAM phys: 0x84c134000
[ 6170.380039] pscgrande_probe(410): pDriver 0xffffffc7d675b000
[ 6170.380179] pscgrande_probe(423): ID = 860812D8
[ 6170.380438] pscgrande_probe(450): got pci resource: bar 0 physical address(0x1f40200000)
[ 6170.380791] pscgrande_probe(457): bar 0 physical remap to virt: 0xffffff80127c0000
[ 6170.380924] pscgrande_probe(458): bar 0 length: 131072
[ 6170.381012] pscgrande_probe(466): CDEP found
[ 6170.381098] pscgrande_probe(477): got pci resource: bar 2 physical address(0x1f40000000)
[ 6170.381265] pscgrande_probe(484): bar 2 physical remap to virt: 0xffffff801c400000
[ 6170.381403] pscgrande_probe(485): bar 2 length: 1048576
[ 6170.381687] ProbeReqID(239): ReqID(W) = 0000 [b:00 s:00 f:0]
[ 6170.381801] NtLutAdd(324): Added Req ID (0000) to LUT #0
[ 6170.382029] ProbeReqID(239): ReqID(R) = 0000 [b:00 s:00 f:0]
[ 6170.382139] NtLutAdd(324): Added Req ID (0000) to LUT #1
[ 6170.382254] pscgrande_probe(521): request_irq succeeded. irq = 39
[ 6170.382392] pscgrande_probe(530): read scatchpad  0 = 860612D8
[ 6170.387682] pscgrande_probe(543): index = 0, peer was loaded already
[ 6170.395025] pscgrande: Class created
[ 6170.397814] pscgrande: alloc ffffffc7d675b000
[ 6170.409558] tegra-asoc: sound: ASoC: CODEC DAI rt5659-aif1 not registered
[ 6170.412653] tegra-asoc: sound: snd_soc_register_card failed (-517)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

driver.tar (20201223)是达尔提供的桥片驱动代码。
readme.txt是达尔提供的对驱动代码的说明。
driver_final文件夹是我在达尔驱动的基础上做的修改,加载driver_final驱动后,可以实现link端对virtal端的读写(devmem)。

验证流程(两个NVIDIA Xavier模组通过非透明桥片互联,且都设置为RC)
1.首先在link side和virtual side使用lspci命令查看是否查看到达尔的桥片。
link side如下:
root@dsp:~# lspci
0001:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad2 (rev a1)
0001:01:00.0 SATA controller: Marvell Technology Group Ltd. Device 9171 (rev 13)
0005:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad0 (rev a1)
0005:01:00.0 Bridge: Pericom Semiconductor Device 8608
virtual side如下:
root@dsp:/home/dsp/1223/driver/virtual# lspci
0005:00:00.0 PCI bridge: NVIDIA Corporation Device 1ad0 (rev a1)
0005:01:00.0 PCI bridge: Pericom Semiconductor Device 8608
0005:02:01.0 PCI bridge: Pericom Semiconductor Device 8608
0005:03:00.0 Bridge: Pericom Semiconductor Device 8608

2.link side首先insmod pscgrande.ko,在insmod时对端会出现如下报错信息,这是正常的,是为了获取BDF信息主动触发的。

加载ko后Link side dmesg信息如下,

3.virtual side再insmod pscgrande.ko
加载ko时会触发Link side中断,从而从scratchpad中读取virtual side申请的iova地址。Link side打印如下,

Virtual side打印如下,

4.link side 使用lspci -v查看bar2地址为1f40000000。

  使用busybox devmem (0x1f40000000加上偏移0xf8000) 32 0x12345678---->0xf8000是virtual side申请的iova的低20位(iova地址为0xffff8000),高12位配置到桥片的TBR寄存器

5.virtual side 
root@dsp:/home/dsp/1223/driver/virtual# busybox devmem 0x84c134000---->0x84c134000是virtual side申请的物理地址,读出来与link side写入的数据相同
0x12345678
 

猜你喜欢

转载自blog.csdn.net/u014426028/article/details/112272430
今日推荐