Can write to but not read from PCI address

93 Views Asked by At

I have taken over some software that was originally written to use VxWorks controlling some custom PCI hardware. We are transitioning away from VxWorks to Linux for a variety of reasons. I have managed to use some frame works found on line to put together a driver that kind of works. I can write to a couple of ports to set the I/O direction and data. However, when I read from the port I get a page fault. The ports are actually memory mapped locations not actual "I/O ports" The code looks like:


    typedef struct
    {
        DWORD dwLocalBase;
        DWORD dwMask;
        DWORD dwBytes;
        void * dwAddr;
        void * dwAddrDirect;
        BOOL  fIsMemory;
    } P9054_ADDR_DESC;

    typedef struct P9054_STRUCT
    {
        P9054_ADDR_DESC addrDesc[AD_PCI_BARS];
        P9054_INTERRUPT Int;
    } P9054_STRUCT;


    static int plx9054_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
    {
    int bar, err, n;
    unsigned long mmio_start,mmio_len;
    struct P9054_STRUCT *drv_priv;
    void __iomem *pci_bar = 0;

    if (read_device_config(pdev) < 0) { // find out how many of these things there are
       return -EIO;
    }

    bar = pci_select_bars(pdev, IORESOURCE_MEM);

    LOG_INFO("Device available MEM BAR are 0x%x\n", bar);

    err = pci_enable_device_mem(pdev);

    if (err) {
        LOG_ERROR("Failed to enable plx device memory, err: %i\n", err);
        return err;
    }

    err = pci_request_region(pdev, bar, DRIVER_NAME);

    if (err) {
        LOG_ERROR("Failed to pci_request_region, err: %i\n", err);
        pci_disable_device(pdev);
        return err;
    }

    // resource 0 - 4

    drv_priv = kzalloc(sizeof(struct P9054_STRUCT), GFP_KERNEL);

    if (!drv_priv) {
        release_device(pdev);
        return -ENOMEM;
    }

    for (n=0; n<4;n++)
    {
        mmio_start = pci_resource_start(pdev, n);
        mmio_len   = pci_resource_len(pdev, n);
        printk("res %d, start 0x%ld, len=0x%lx\n",n, mmio_start, mmio_len);
        drv_priv->addrDesc[n].dwLocalBase = mmio_start;
        drv_priv->addrDesc[n].dwBytes = mmio_len;
        drv_priv->addrDesc[n].dwAddr = ioremap(mmio_start, mmio_len);
        pci_bar = pci_ioremap_bar(pdev, n);
        if (pci_bar)
        {
            drv_priv->addrDesc[n].dwAddr = pci_bar;
            printk("pciBar %d = %p\n",n, pci_bar);
        }
        drv_priv->addrDesc[n].dwAddrDirect = pci_iomap(pdev,n,0);

        if (!drv_priv->addrDesc[n].dwAddr) {
            release_device(pdev);
            return -EIO;
        }
    }
    create_char_devs(drv_priv);
    pci_set_drvdata(pdev, drv_priv);
    return 0;
    }

    // ioctl calls 

    void set_port_400_mode(struct P9054_STRUCT* drv, long arg)
    {
    char *y = (char *)drv->addrDesc[2].dwAddr;
    y += 0x410;
    printk("set_port_400_mode: addrs %p, y=%p, offset %d\n", drv->addrDesc[2].dwAddr,y,0x410);
    writel(arg, y);
    }

    void set_port_400_data(struct P9054_STRUCT* drv, long arg)
    {
    printk("set_port_400_data: addrs: %p, with offset of 0x400 %p, data: 0X%lX\n",
        (void *)drv->addrDesc[2].dwAddr, (void *)(drv->addrDesc[2].dwAddr+ 0x400),arg);
    writel(arg, (drv->addrDesc[2].dwAddr+ 0x400)); // 0x400
    }

    void get_port_330_data(struct P9054_STRUCT* drv, char * arg)
    {
    char b;
    printk("get_port_330_data: addrs: %p, %p data: 0X%p\n",
        (void *)drv->addrDesc[2].dwAddr, (void *)(drv->addrDesc[2].dwAddr+ 0x400),arg);
    b = readb((char *)drv->addrDesc[2].dwAddr+ 0x330); // 0x400
    *arg = b;
    }

When this code is tied together and the module installed from dmesg I get:


[20671.690992] Loading plx driver for ADI and 2 channel 4 gate boards - version 0.1
[20671.691053] Device vid: 0x10B5  pid: 0x5406
[20671.691057] Device status reg: 0x290
[20671.691061] Device supports memory access
[20671.691063] Device available MEM BAR are 0xd
[20671.691156] res 0, start 0x2713735168, len=0x100
[20671.691175] pciBar 0 = 00000000d38709cf
[20671.691180] Memory; ioremap resource0  0x00000000d38709cf, size = 256
[20671.691182] Memory; pci_iomap resource0 to 0x000000007d614d94
[20671.691183] res 1, start 0x32768, len=0x100
[20671.691237] plx9054 0000:04:0f.0: can't ioremap BAR 1: [io  0x8000-0x80ff]
[20671.691240] IO; ioremap resource1  0x0000000042011847, size = 256
[20671.691242] IO; pci_iomap resource1 to 0x00000000d2340133
[20671.691243] res 2, start 0x2713731072, len=0x1000
[20671.691250] pciBar 2 = 00000000160e2359
[20671.691253] Memory; ioremap resource2  0x00000000160e2359, size = 4096
[20671.691255] Memory; pci_iomap resource2 to 0x00000000b63d8bca
[20671.691270] res 3, start 0x2713714688, len=0x4000
[20671.691276] pciBar 3 = 000000005ea05322
[20671.691280] Memory; ioremap resource3  0x000000005ea05322, size = 16384
[20671.691281] Memory; pci_iomap resource3 to 0x0000000072bf29b6
[20671.691283] entered create_char_devs, MAX_DEV =4
[20671.691299] initialized cdev, plx_fops ioctl = 0x000000004113b042
[20671.691392] initialized cdev, plx_fops ioctl = 0x000000004113b042
[20671.691424] initialized cdev, plx_fops ioctl = 0x000000004113b042
[20671.691455] initialized cdev, plx_fops ioctl = 0x000000004113b042
[20671.691478] create_char_devs done


Then I call a test routine that writes to the driver at memory address in BAR 2 at offset 0x400 and 0x410 and read from offset 0x330. I have tried readb, readw and readl with the same result

[45821.381693] In ioctl
[45821.381709] set_port_400_mode: addrs 000000007d614d94, y=00000000e2871985, offset 0x400
[45821.381737] In ioctl
[45821.381743] set_port_400_data: addrs: 000000007d614d94, with offset of 0x400 000000005ebc3edd, data: 0X0
[45821.381775] In ioctl
[45821.381779] get_port_330_data: addrs: 000000007d614d94, 000000005ebc3edd data: 0X0000000014741bb8
[45821.381795] BUG: unable to handle page fault for address: **00000000fffa6054**
[45821.381801] #PF: supervisor write access in kernel mode
[45821.381808] #PF: error_code(0x0003) - permissions violation
[45821.381814] PGD 800000011ab8c067 P4D 800000011ab8c067 PUD 16fa27067 PMD 11b57b067 PTE 80000001887e0867
[45821.381835] Oops: 0003 [#6] PREEMPT SMP PTI
[45821.381845] CPU: 7 PID: 9398 Comm: test_client Tainted: G      D W  OE      6.2.0-32-generic #32~22.04.1-Ubuntu
[45821.381857] Hardware name: To be filled by O.E.M. To be filled by O.E.M./To be filled by O.E.M., BIOS 0.14.10 03/04/2022
[45821.381863] RIP: 0010:get_port_330_data+0x3d/0x60 [plx9054]
[45821.381891] Code: 8b b7 08 0a 00 00 48 c7 c7 e8 f7 b7 c0 48 89 d9 48 8d 96 00 04 00 00 e8 e1 d0 80 f4 49 8b 84 24 08 0a 00 00 8a 80 30 03 00 00 <88> 03 5b 41 5c 5d 31 c0 31 d2 31 c9 31 f6 31 ff c3 cc cc cc cc 66
[45821.381900] RSP: 0018:ffffbbdcc69dfe08 EFLAGS: 00010246
[45821.381910] RAX: ffffbbdcc0103000 RBX: 00000000fffa6054 RCX: 0000000000000000
[45821.381917] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[45821.381923] RBP: ffffbbdcc69dfe18 R08: 0000000000000000 R09: 0000000000000000
[45821.381928] R10: 0000000000000000 R11: 0000000000000000 R12: ffff93560ce67000
[45821.381934] R13: ffff93561ae3f6c0 R14: 00000000fffa6054 R15: ffff93560bbafa00
[45821.381941] FS:  0000000000000000(0000) GS:ffff935763bc0000(0063) knlGS:00000000f7f6d500
[45821.381950] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
[45821.381957] CR2: 00000000fffa6054 CR3: 000000011b3b2002 CR4: 00000000003706e0
[45821.381965] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[45821.381971] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[45821.381977] Call Trace:
[45821.381982]  <TASK>
[45821.381990]  ? show_regs+0x72/0x90
[45821.382004]  ? __die+0x25/0x80
[45821.382015]  ? page_fault_oops+0x79/0x190
[45821.382024]  ? _prb_read_valid+0x62/0xd0
[45821.382037]  ? do_user_addr_fault+0x30c/0x640
[45821.382045]  ? prb_read_valid+0x1c/0x30
[45821.382054]  ? console_unlock+0x85/0xf0
[45821.382068]  ? exc_page_fault+0x81/0x1b0
[45821.382082]  ? asm_exc_page_fault+0x27/0x30
[45821.382100]  ? get_port_330_data+0x3d/0x60 [plx9054]
[45821.382121]  ? get_port_330_data+0x2f/0x60 [plx9054]
[45821.382140]  plxdev_ioctl+0x12b/0x160 [plx9054]
[45821.382160]  __do_compat_sys_ioctl+0x18d/0x1c0
[45821.382175]  __ia32_compat_sys_ioctl+0x17/0x30
[45821.382187]  __do_fast_syscall_32+0x89/0x100
[45821.382200]  ? exit_to_user_mode_prepare+0x3b/0xd0
[45821.382210]  ? syscall_exit_to_user_mode+0x2a/0x50
[45821.382222]  ? __do_fast_syscall_32+0x99/0x100
[45821.382232]  ? __do_fast_syscall_32+0x99/0x100
[45821.382243]  ? __do_fast_syscall_32+0x99/0x100
[45821.382254]  ? irqentry_exit_to_user_mode+0x9/0x20
[45821.382266]  do_fast_syscall_32+0x34/0x80
[45821.382278]  do_SYSENTER_32+0x1f/0x30
[45821.382289]  entry_SYSENTER_compat_after_hwframe+0x7f/0x91
[45821.382301] RIP: 0023:0xf7f72549
[45821.382309] Code: 03 74 c0 01 10 05 03 74 b8 01 10 06 03 74 b4 01 10 07 03 74 b0 01 10 08 03 74 d8 01 00 00 00 00 00 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 cc 90 90 90 8d b4 26 00 00 00 00 8d b4 26 00 00 00 00
[45821.382317] RSP: 002b:00000000fffa6014 EFLAGS: 00000282 ORIG_RAX: 0000000000000036
[45821.382327] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000000331
[45821.382333] RDX: 00000000fffa6054 RSI: 00000000f7e2a000 RDI: 00000000f7faab80
[45821.382339] RBP: 00000000fffa6098 R08: 0000000000000000 R09: 0000000000000000
[45821.382345] R10: 0000000000000000 R11: 0000000000000282 R12: 0000000000000000
[45821.382351] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[45821.382365]  </TASK>
[45821.382369] Modules linked in: plx9054(OE) cmac nls_utf8 cifs cifs_arc4 cifs_md4 fscache netfs snd_hda_codec_hdmi snd_sof_pci_intel_cnl snd_sof_intel_hda_common soundwire_intel soundwire_generic_allocation soundwire_cadence snd_sof_intel_hda snd_sof_pci snd_sof_xtensa_dsp snd_sof snd_sof_utils snd_soc_hdac_hda snd_hda_ext_core intel_rapl_msr snd_soc_acpi_intel_match intel_rapl_common snd_soc_acpi intel_tcc_cooling soundwire_bus x86_pkg_temp_thermal intel_powerclamp snd_soc_core coretemp snd_compress ac97_bus binfmt_misc snd_pcm_dmaengine snd_hda_intel snd_intel_dspcfg kvm_intel snd_intel_sdw_acpi snd_hda_codec snd_hda_core ipmi_ssif nls_iso8859_1 kvm snd_hwdep mei_hdcp snd_pcm mei_pxp irqbypass i915 crct10dif_pclmul polyval_clmulni snd_seq_midi polyval_generic ghash_clmulni_intel snd_seq_midi_event sha512_ssse3 aesni_intel joydev snd_rawmidi crypto_simd drm_buddy input_leds cryptd ttm snd_seq rapl drm_display_helper snd_seq_device cmdlinepart intel_cstate snd_timer spi_nor cec snd mtd
[45821.382566]  wmi_bmof rc_core soundcore drm_kms_helper mei_me acpi_ipmi syscopyarea mei sysfillrect sysimgblt ipmi_si intel_pch_thermal ipmi_devintf ipmi_msghandler mac_hid acpi_pad acpi_tad sch_fq_codel msr parport_pc ppdev lp parport drm pstore_blk ramoops pstore_zone reed_solomon efi_pstore ip_tables x_tables autofs4 hid_logitech_hidpp hid_logitech_dj hid_generic usbhid uas hid usb_storage spi_intel_pci i2c_i801 crc32_pclmul igb spi_intel i2c_smbus isp1760 ahci intel_lpss_pci i2c_algo_bit udc_core dca intel_lpss libahci xhci_pci idma64 xhci_pci_renesas video wmi pinctrl_cannonlake [last unloaded: plx9054(OE)]
[45821.382728] CR2: 00000000fffa6054
[45821.382735] ---[ end trace 0000000000000000 ]---
[45821.518944] RIP: 0010:get_port_330_datay+0x61/0x90 [plx9054]
[45821.518952] Code: 49 8b b4 24 08 0a 00 00 48 c7 c7 58 f8 b7 c0 48 89 d1 e8 52 d0 80 f4 48 c7 c7 2f f3 b7 c0 e8 46 d0 80 f4 66 8b 83 30 03 00 00 <41> 88 45 00 48 c7 c7 3c f3 b7 c0 e8 2f d0 80 f4 5b 41 5c 41 5d 5d
[45821.518954] RSP: 0018:ffffbbdcc0bc7db0 EFLAGS: 00010246
[45821.518957] RAX: 000000000000bc00 RBX: ffffbbdcc00bb000 RCX: 0000000000000000
[45821.518959] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[45821.518961] RBP: ffffbbdcc0bc7dc8 R08: 0000000000000000 R09: 0000000000000000
[45821.518962] R10: 0000000000000000 R11: 0000000000000000 R12: ffff93560def5000
[45821.518964] R13: 00000000ffd55614 R14: 00000000ffd55614 R15: ffff93561ae90500
[45821.518966] FS:  0000000000000000(0000) GS:ffff935763bc0000(0063) knlGS:00000000f7f6d500
[45821.518968] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
[45821.518970] CR2: 00000000fffa6054 CR3: 000000011b3b2002 CR4: 00000000003706e0
[45821.518972] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[45821.518973] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[45821.518975] note: test_client[9398] exited with irqs disabled


where did this **00000000fffa6054** come from? does it cause the page fault? What am I doing wrong?

0

There are 0 best solutions below