Linux kernel 如何为PCI条内存实现mmap?

Linux kernel 如何为PCI条内存实现mmap?,linux-kernel,linux-device-driver,kernel-module,pci,pci-e,Linux Kernel,Linux Device Driver,Kernel Module,Pci,Pci E,我有一个SRAM内存,可在PCI总线1上寻址。我想知道如何在驱动程序中正确写入mmap函数,以便我的用户进程能够mmap sram内存并读/写到其中 我在driver中编写了以下probe和mmap函数来执行相同的操作: 探头功能: static int probe(struct pci_dev * pcidev, const struct pci_device_id * id) { int r,i; unsigned long start,end; int sram;

我有一个SRAM内存,可在PCI总线1上寻址。我想知道如何在驱动程序中正确写入mmap函数,以便我的用户进程能够mmap sram内存并读/写到其中

我在driver中编写了以下probe和mmap函数来执行相同的操作:

探头功能:

static int probe(struct pci_dev * pcidev, const struct pci_device_id * id)
{
    int r,i;
    unsigned long start,end;
    int sram;

    r = pci_enable_device(pcidev);
    if(r < 0)
    {
        printk(KERN_ALERT DEVICE_NAME ": Enable of my_pci device fails %d\n",r); 
        return -1;
    }
    pci_set_master(pcidev);

    start = pci_resource_start(pcidev, 1);
    end = pci_resource_end(pcidev, 1);
    size = end - start + 1;

    sram_raw_base_address = start;
    sram_base_address = (unsigned long)ioremap_nocache(start,size);
    sram_size = size;
}
static int probe(struct pci_dev*pcidev,const struct pci_device\u id*id)
{
int r,i;
无符号长起始、结束;
int sram;
r=pci_启用_设备(pcidev);
if(r<0)
{
printk(内核警报设备名称):启用我的pci设备失败%d\n“,r);
返回-1;
}
pci设置主机(pcidev);
启动=pci_资源_启动(pcidev,1);
end=pci_资源_end(pcidev,1);
大小=结束-开始+1;
sram_原始_基本_地址=开始;
sram_base_address=(无符号长)ioremap_nocache(开始,大小);
sram_大小=大小;
}
mmap功能是:

static int my_mmap(struct file *file, struct vm_area_struct *vma)
{   
    size_t size = vma->vm_end - vma->vm_start;
    unsigned long ioaddress, iosize;

    if(vma->vm_end < vma->vm_start)
    {
        return -EAGAIN;
    }

    /* mapping sram. */
    ioaddress = sram_base_address;
    iosize = sram_size;

    /* simple check to prevent mapping past io area. */
    if( (size > iosize) ||
        ((vma->vm_pgoff << PAGE_SHIFT) > iosize) ||
        ( ((vma->vm_pgoff << PAGE_SHIFT)+size) > iosize) )
    {
        return -EINVAL;
    }

    if (remap_pfn_range(vma,vma->vm_start,vmalloc_to_pfn(ioaddress+(vma->vm_pgoff << PAGE_SHIFT)),
            size,vma->vm_page_prot)) {
    return -EAGAIN;
    }

    vma->vm_ops = &vmops;
    vmops_open(vma);

    return 0;
}
static int my_mmap(结构文件*file,结构vm\u区域*vma)
{   
size\u t size=vma->vm\u end-vma->vm\u start;
未签名的长ioaddress,iosize;
如果(vma->vm_结束vm_开始)
{
返回-伊根;
}
/*映射sram*/
ioaddress=sram\u基地址;
iosize=sram_大小;
/*简单检查以防止映射超过io区域*/
如果((大小>大小)||
((vma->vm_pgoff iosize)||
((vma->vm_pgoff iosize))
{
返回-艾因瓦尔;
}
if(重新映射到pfn范围(vma,vma->vm\U开始,vmalloc\U到pfn(ioaddress+(vma->vm\U pgoff vm\U页面保护)){
返回-伊根;
}
vma->vm_ops=&vmops;
vmops_open(vma);
返回0;
}
每当我尝试在我的应用程序中mmap SRAM内存时,我在/var/log/syslog中都会遇到以下错误:

Jul 26 13:21:12 manik kernel: [86635.262485] my_pci my_mmap - called
Jul 26 13:21:12 manik kernel: [86635.262524] BUG: unable to handle kernel  paging request at 02530000
Jul 26 13:21:12 manik kernel: [86635.262549] IP: [<c11ab31d>] vmalloc_to_pfn+0xd/0x30
Jul 26 13:21:12 manik kernel: [86635.262569] *pdpt = 00000000050f8001 *pde = 0000000000000000
Jul 26 13:21:12 manik kernel: [86635.262584] Oops: 0000 [#1] SMP
Jul 26 13:21:12 manik kernel: [86635.262595] Modules linked in: qcomdl(POE) gdapdl(POE) gammadl(POE) aspdl(POE) ccce(POE) scard(POE) kmikohn(OE) fmon(OE) khcd(OE) kcid(OE) kspi(POE) kpwrfail(OE) mk7i_pci(OE) snd_usb_audio input_leds hid_multitouch joydev snd_usbmidi_lib intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm i2c_ocores snd_soc_rt5640 snd_hda_codec_hdmi irqbypass crc32_pclmul snd_soc_rl6231 snd_hda_intel snd_hda_codec lpc_ich ie31200_edac edac_core snd_hda_core shpchp snd_hwdep snd_soc_core snd_compress ac97_bus snd_pcm_dmaengine 8250_fintek snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device snd_timer snd snd_soc_sst_acpi soundcore 8250_dw dw_dmac soc_button_array dw_dmac_core elan_i2c spi_pxa2xx_platform i2c_designware_platform i2c_designware_core mac_hid parport_pc ppdev lp parport autofs4 nouveau mxm_wmi i915 wmi i2c_algo_bit ttm ahci libahci drm_kms_helper syscopyarea e1000e sysfillrect sysimgblt fb_sys_fops ptp drm pps_core sdhci_acpi video i2c_hid sdhci fjes hid_generic usbhid hid [last unloaded: mk7i_pci]
Jul 26 13:21:12 manik kernel: [86635.262938] CPU: 0 PID: 14025 Comm: test_sram Tainted: P        W IOE   4.4.0-31-generic #50
Jul 26 13:21:12 manik kernel: [86635.262950] Hardware name: ADLINK Technology Inc. Express-HL./SHARKBAY, BIOS 1.14 01/01/2013
Jul 26 13:21:12 manik kernel: [86635.262962] task: d0c05a00 ti: ca928000 task.ti: ca928000
Jul 26 13:21:12 manik kernel: [86635.262972] EIP: 0060:[<c11ab31d>] EFLAGS: 00010246 CPU: 0
Jul 26 13:21:12 manik kernel: [86635.262983] EIP is at vmalloc_to_pfn+0xd/0x30
Jul 26 13:21:12 manik kernel: [86635.262991] EAX: 02530000 EBX: c5617138 ECX: ee9d9000 EDX: fff1b000
Jul 26 13:21:12 manik kernel: [86635.263001] ESI: 02000000 EDI: f3200000 EBP: ca929e70 ESP: ca929e70
Jul 26 13:21:12 manik kernel: [86635.263010]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
Jul 26 13:21:12 manik kernel: [86635.263019] CR0: 80050033 CR2: 02530000 CR3: 2dc02500 CR4: 001406f0
Jul 26 13:21:12 manik kernel: [86635.263028] Stack:
Jul 26 13:21:12 manik kernel: [86635.263034]  ca929e90 f0c566af f0c58260 024080c0 c5617138 c56171b4 b5321000 c56171b0
Jul 26 13:21:12 manik kernel: [86635.263063]  ca929ee4 c11a64f8 b7321000 000000fb 00000000 c6eac0c0 00000000 00000000
Jul 26 13:21:12 manik kernel: [86635.263091]  00000000 00000008 00000000 00000000 c56171b4 00002000 c6eac0c0 c5617138
Jul 26 13:21:12 manik kernel: [86635.263120] Call Trace:
Jul 26 13:21:12 manik kernel: [86635.263132]  [<f0c566af>] my_mmap+0x6f/0xf0 [mk7i_pci]
Jul 26 13:21:12 manik kernel: [86635.263145]  [<c11a64f8>] mmap_region+0x388/0x590
Jul 26 13:21:12 manik kernel: [86635.263155]  [<c11a6956>] do_mmap+0x256/0x360
Jul 26 13:21:12 manik kernel: [86635.263167]  [<c118d19a>] vm_mmap_pgoff+0x9a/0xc0
Jul 26 13:21:12 manik kernel: [86635.263177]  [<c11a4c54>] SyS_mmap_pgoff+0x194/0x230
Jul 26 13:21:12 manik kernel: [86635.263190]  [<c100393d>] do_fast_syscall_32+0x8d/0x150
Jul 26 13:21:12 manik kernel: [86635.263202]  [<c17b229c>] sysenter_past_esp+0x3d/0x61
Jul 26 13:21:12 manik kernel: [86635.263210] Code: 8b 80 c0 20 d2 c1 83 e0 fc 8d 1c d0 eb bb 31 db 89 d8 5b 5e 5f 5d c3 8d b4 26 00 00 00 00 55 89 e5 3e 8d 74 26 00 e8 d3 fe ff ff <8b> 10 5d c1 ea 19 c1 e2 04 8b 92 c0 20 d2 c1 83 e2 fc 29 d0 c1
Jul 26 13:21:12 manik kernel: [86635.263388] EIP: [<c11ab31d>] vmalloc_to_pfn+0xd/0x30 SS:ESP 0068:ca929e70
Jul 26 13:21:12 manik kernel: [86635.263406] CR2: 0000000002530000
Jul 26 13:21:12 manik kernel: [86635.269070] ---[ end trace f85e2d73d203ae00 ]---
Jul 26 13:21:12 manik内核:[86635.262485]我的pci我的mmap-调用
Jul 26 13:21:12 manik内核:[86635.262524]错误:无法处理0253000处的内核分页请求
Jul 26 13:21:12 manik内核:[86635.262549]IP:[]vmalloc_to_pfn+0xd/0x30
Jul 26 13:21:12 manik内核:[86635.262569]*pdpt=000000000 50F8001*pde=0000000000000000000000
Jul 26 13:21:12 manik内核:[86635.262584]Oops:0000[#1]SMP
7月26日13:21:12 manik内核:[86635.262595]链接模块:qcomdl(POE)gdapdl(POE)gammadl(POE)aspdl(POE)ccce(POE)scard(POE)kmikohn(OE)fmon(OE)khcd(OE)kcid(OE)kspi(POE)kpwrfail(OE)mk7i_pci(OE)研究结果发现了一种新的研究方法(U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U Udmaengine 8250 fintek snd pcm snd序列midi snd序列midi事件snd序列rawmidi snd序列snd序列设备snd定时器snd序列soc sst acpi soundcore 8250 dw dw dmac soc按钮阵列dw dmac核心elan i2c spi总线pxa2xx平台i2c设计软件i2c平台i2c硬件ARM核心mac端口MX新算法libahci drm_kms_helper syscopyrea e1000e sysfillrect sysimgblt fb_sys_fops ptp drm pps_core sdhci_acpi video i2c_hid sdhci fjes hid_generic usbhid[上次卸载:mk7i_pci]
7月26日13:21:12 manik内核:[86635.262938]CPU:0 PID:14025通信:测试受sram污染:PWIOE 4.4.0-31-generic#50
7月26日13:21:12 manik内核:[86635.262950]硬件名称:ADLINK Technology Inc.Express HL./SHARKBAY,BIOS 1.14 01/01/2013
Jul 26 13:21:12 manik内核:[86635.262962]任务:d0c05a00 ti:ca928000任务。ti:ca928000
Jul 26 13:21:12 manik内核:[86635.262972]EIP:0060:[]EFLAGS:00010246 CPU:0
7月26日13:21:12 manik内核:[86635.262983]EIP位于vmalloc_to_pfn+0xd/0x30
7月26日13:21:12 manik内核:[86635.262991]EAX:0253000 EBX:c5617138 ECX:ee9d9000 EDX:fff1b000
7月26日13:21:12 manik内核:[86635.263001]ESI:02000000 EDI:f3200000 EBP:ca929e70 ESP:ca929e70
7月26日13:21:12 manik内核:[86635.263010]DS:007b ES:007b FS:00d8 GS:00e0 SS:0068
7月26日13:21:12 manik内核:[86635.263019]CR0:80050033 CR2:0253000 CR3:2DC02500CR4:001406f0
Jul 26 13:21:12 manik内核:[86635.263028]堆栈:
7月26日13:21:12 manik内核:[86635.263034]ca929e90 f0c566af f0c58260 024080c0 c5617138 c56171b4 b5321000 c56171b0
7月26日13:21:12 manik内核:[86635.263063]ca929ee4 c11a64f8 B73210000 000000 FB 00000000 C6EAC0C000000000 00000000
7月26日13:21:12 manik内核:[86635.263091]0000000000000000000800000000000000C56171B40002000C6EAC0C5617138
Jul 26 13:21:12 manik内核:[86635.263120]调用跟踪:
Jul 26 13:21:12 manik内核:[86635.263132][]我的mmap+0x6f/0xf0[mk7i_pci]
Jul 26 13:21:12 manik内核:[86635.263145][]mmap_区域+0x388/0x590
Jul 26 13:21:12 manik内核:[86635.263155][]do_mmap+0x256/0x360
7月26日13:21:12 manik内核:[86635.263167][]vm_mmap_pgoff+0x9a/0xc0
Jul 26 13:21:12 manik内核:[86635.263177][]系统mmap pgoff+0x194/0x230
Jul 26 13:21:12 manik内核:[86635.263190][]执行快速系统调用\u 32+0x8d/0x150
7月26日13:21:12 manik内核:[86635.263202][]syscenter\u pass\u esp+0x3d/0x61
7月26日13:21:12马尼克内核:[86635.263210]代码:8b 80 c0 20 d2 c1 83 e0 fc 8d 1c d0 eb bb 31 db 89 d8 5b 5e 5f 5d c3 8d b4 26 00 00 00 55 89 e5 3e 8d 74 26 00 e8 d3 fe ff 10 5d c1 ea 19 c1 e2 04 8b 92 c0 20 d2 c1 83 e2 fc 29 d0 c1
7月26日13:21:12 manik内核:[86635.263388]EIP:[]vmalloc_to_pfn+0xd/0x30 SS:ESP 0068:ca929e70
Jul 26 13:21:12 manik内核:[86635.263406]CR2:000000000 2530000
7月26日13:21:12 manik内核:[86635.269070]--[end trace f85e2d73d203ae00]---
显然,驱动程序的mmap功能在
vmalloc_to_pfn
调用中失败。 我不明白为什么

我正在使用探测函数中的
ioremap\u nocache
创建不可缓存的虚拟地址,因为我希望PCI条内存区域中发生的写/读操作是在内存硬件而不是cpu缓存中读/写的。我希望我是