I'm trying to read and write to and PCI-device from a loadable kernel module.
Therefore I follow this post:
pci_enable_device(dev);
pci_request_regions(dev, "expdev");
bar1 = pci_iomap(dev, 1, 0);
// void iowrite32(u32 val, void __iomem *addr)
iowrite32( 0xaaaaaaaa, bar1 + 0x060000); /* offset from device spec */
But at the end the device doesn't do his work as expected. Then I look to the address behind bar1
and found a very big value ffffbaaaaa004500
.
At this point I don't really understand what was happen there and what was right. Can I interpret bar1
as an address inside my kernel address space which points directly to the base address which is 0x60000
offset to the PCI Chip Select Address?
And how can it be that the value I write to bar1 + offset
copied to the device? How does the mechanism work in behind of iowrite32
and pci_iomap
?
Thanks and regards
Alex
PS: I tested a read back from the same address successfully.
Register description of the PCI device:
PCIBAR0
PCI Base Address 0; used for Memory-Mapped Configuration RegistersPCIBAR1
PCI Base Address 1; used for I/O-Mapped Configuration RegistersPCIBAR2
PCI Base Address 2; used for Local Address Space 0PCIBAR3
PCI Base Address 3; used for Local Address Space 1PCIBAR4
Unused Base AddressPCIBAR5
Unused Base AddressHello again.
In the last time I tried several approaches to communicate with the BAR2 register but without success. Here my actual code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
#define DEV_PCI_VENDORID 0x10B5
#define DEV_PCI_DEVICEID 0x1860
static struct pci_device_id pci_drvIdTable[] =
{
{
.vendor = DEV_PCI_VENDORID, // vendor ID
.device = DEV_PCI_DEVICEID, // device ID
.subvendor = PCI_ANY_ID, // no subsystem available
.subdevice = PCI_ANY_ID, // no subsystem available
.class = PCI_CLASS_NOT_DEFINED, // no device class
.class_mask = 0, // no device class
.driver_data = 0 // no private data to the driver
},
{ 0, } // end of table
};
struct pci_data
{
/// the IO mapping for the PCI config space
uint32_t *pciConfigAddr;
uint32_t *pciB2Addr;
// void __iomem *pciConfigAddr;
wait_queue_head_t waitq;
uint8_t flag;
} *data;
static irqreturn_t
_expdev_irq (int irq, void *pdata)
{
struct pci_data *data = pdata;
printk(KERN_INFO "Interrupt talks...\n");
data->flag = 1;
wake_up_interruptible( &data->waitq );
return IRQ_HANDLED;
}
static int
_pci_probe ( struct pci_dev *pdev,
const struct pci_device_id *ent )
{
int ret = 0;
int i;
u16 reg_16;
unsigned long bas2addr;
data = kzalloc( sizeof(*data) , GFP_KERNEL );
if( !data )
{
printk(KERN_ERR "Failed to allocate memory.\n");
return -ENOMEM;
}
pci_set_drvdata(pdev, data);
// enabling the device
ret = pci_enable_device(pdev);
if( ret )
{
printk(KERN_ERR "Failed to enable PCI device.\n");
goto no_enable;
}
pci_read_config_word(pdev,0,®_16);
printk(KERN_INFO "VendorID. %x\n",reg_16);
// checking if PCI-device reachable by checking that BAR0 is defined and
// memory mapped
if( !(pci_resource_flags(pdev,0) & IORESOURCE_MEM) )
{
printk(KERN_ERR "Incorrect BAR configuration.\n");
ret = -ENODEV;
goto bad_bar;
}
// taking ownership of a memory region
ret = pcim_iomap_regions(pdev, 0b0100, "expdev");
// ret = pci_request_regions(pdev,"expdev");
if( ret )
{
printk(KERN_ERR "Failed to request regions.\n");
goto failed_request_regions;
}
bas2addr = pci_resource_start(pdev, 2);
reg_16 = 0xAA;
i = 0x060000;
iowrite16( reg_16 , (unsigned long *)(bas2addr+i) );
printk( KERN_INFO "BAR2 Register[0x%x] = 0x%x\n",
i, ioread32( (unsigned long *)(bas2addr+i) ) );
printk(KERN_INFO "Module successfully initialised.\n");
return 0;
// Error handling - backward disabling the device
failed_request_regions:
bad_bar:
pci_disable_device(pdev);
no_enable:
pci_set_drvdata(pdev, data);
return ret;
}
static void
_pci_remove( struct pci_dev *pdev )
{
free_irq(pdev->irq, data);
pci_disable_msi(pdev);
pci_clear_master(pdev);
pci_iounmap(pdev,data->pciConfigAddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
printk(KERN_INFO "PCI-device removed.\n");
}
static struct pci_driver pci_drv =
{
.name = "expdev",
.id_table = pci_drvIdTable,
.probe = _pci_probe,
.remove = _pci_remove,
};
// module related functions ///////////////////////////////////////////////////
static int __init _module_init(void){
printk(KERN_INFO "Hello!\n");
pci_register_driver(&pci_drv);
return 0;
}
static void __exit _module_exit(void){
pci_unregister_driver(&pci_drv);
printk(KERN_INFO "Goodbye!\n");
}
module_init(_module_init);
module_exit(_module_exit);
This is the responding output with tail -f /var/log/kern.log
kernel: [ 493.719999] Hello!
kernel: [ 493.720071] expdev 0000:05:02.0: enabling device (0000 -> 0003)
kernel: [ 493.720845] VendorID. 10b5
kernel: [ 493.722375] BUG: unable to handle kernel paging request at 00000000eb060000
kernel: [ 493.722381] IP: [<ffffffff8137aca8>] iowrite16+0x38/0x40
kernel: [ 493.722388] PGD 0
kernel: [ 493.722390] Oops: 0002 [#1] SMP
kernel: [ 493.722394] Modules linked in: expdev(OX+) rfcomm bnep bluetooth nvidia(POX) snd_hda_codec_hdmi joydev snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm coretemp snd_page_alloc snd_seq_midi snd_seq_midi_event snd_rawmidi gpio_ich kvm snd_seq snd_seq_device drm dcdbas snd_timer lpc_ich snd soundcore shpchp serio_raw ppdev i82975x_edac lp parport_pc edac_core parport mac_hid hid_generic usbhid hid psmouse ahci tg3 libahci ptp pps_core pata_acpi
kernel: [ 493.722429] CPU: 0 PID: 3542 Comm: insmod Tainted: P OX 3.13.0-79-generic #123-Ubuntu
kernel: [ 493.722431] Hardware name: Dell Inc. Precision WorkStation 390 /0DN075, BIOS 2.3.0 05/01/2007
kernel: [ 493.722434] task: ffff8800549c3000 ti: ffff8800555e6000 task.ti: ffff8800555e6000
kernel: [ 493.722436] RIP: 0010:[<ffffffff8137aca8>] [<ffffffff8137aca8>] iowrite16+0x38/0x40
kernel: [ 493.722440] RSP: 0018:ffff8800555e7b88 EFLAGS: 00010212
kernel: [ 493.722442] RAX: 00000000eb000000 RBX: ffff88007c2b4000 RCX: 0000000000000000
kernel: [ 493.722444] RDX: 00000000eb060000 RSI: 00000000eb060000 RDI: 00000000000000aa
kernel: [ 493.722446] RBP: ffff8800555e7bb0 R08: 00000000ebffffff R09: 00000000ffffffec
kernel: [ 493.722448] R10: 0000000000003692 R11: 0000000000000000 R12: 00000000eb060000
kernel: [ 493.722450] R13: ffff88007c2b4098 R14: ffff88007c2b4098 R15: ffffffffa022b140
kernel: [ 493.722452] FS: 00007fa8053ef740(0000) GS:ffff88007f800000(0000) knlGS:0000000000000000
kernel: [ 493.722454] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
kernel: [ 493.722456] CR2: 00000000eb060000 CR3: 000000005a74b000 CR4: 00000000000007f0
kernel: [ 493.722458] Stack:
kernel: [ 493.722460] ffffffffa02291c4 00aa88007c2b4000 ffff88007c2b4000 0000000000000000
kernel: [ 493.722464] ffffffffa022b000 ffff8800555e7be8 ffffffff813ac8a5 ffffffff813adb45
kernel: [ 493.722467] ffff88007c2b4098 ffffffffffffffff ffff88007c2b4000 0000000000000017
kernel: [ 493.722471] Call Trace:
kernel: [ 493.722477] [<ffffffffa02291c4>] ? _pci_probe+0x114/0x215 [expdev]
kernel: [ 493.722481] [<ffffffff813ac8a5>] local_pci_probe+0x45/0xa0
kernel: [ 493.722484] [<ffffffff813adb45>] ? pci_match_device+0xc5/0xd0
kernel: [ 493.722487] [<ffffffff813adc69>] pci_device_probe+0xd9/0x130
kernel: [ 493.722492] [<ffffffff8149a4bd>] driver_probe_device+0x12d/0x3e0
kernel: [ 493.722495] [<ffffffff8149a843>] __driver_attach+0x93/0xa0
kernel: [ 493.722498] [<ffffffff8149a7b0>] ? __device_attach+0x40/0x40
kernel: [ 493.722501] [<ffffffff81498403>] bus_for_each_dev+0x63/0xa0
kernel: [ 493.722504] [<ffffffff81499e6e>] driver_attach+0x1e/0x20
kernel: [ 493.722507] [<ffffffff81499a50>] bus_add_driver+0x180/0x250
kernel: [ 493.722510] [<ffffffffa0005000>] ? 0xffffffffa0004fff
kernel: [ 493.722514] [<ffffffff8149aec4>] driver_register+0x64/0xf0
kernel: [ 493.722517] [<ffffffffa0005000>] ? 0xffffffffa0004fff
kernel: [ 493.722520] [<ffffffff813ac23c>] __pci_register_driver+0x4c/0x50
kernel: [ 493.722523] [<ffffffffa000502c>] _module_init+0x2c/0x1000 [expdev]
kernel: [ 493.722528] [<ffffffff8100214a>] do_one_initcall+0xfa/0x1b0
kernel: [ 493.722532] [<ffffffff810598f3>] ? set_memory_nx+0x43/0x50
kernel: [ 493.722536] [<ffffffff810e2b7d>] load_module+0x12ed/0x1b50
kernel: [ 493.722540] [<ffffffff810de5f0>] ? store_uevent+0x40/0x40
kernel: [ 493.722544] [<ffffffff810e3556>] SyS_finit_module+0x86/0xb0
kernel: [ 493.722548] [<ffffffff817363dd>] system_call_fastpath+0x1a/0x1f
kernel: [ 493.722550] Code: 81 fe 00 00 01 00 76 0b 0f b7 d6 89 f8 66 ef c3 0f 1f 00 55 48 c7 c6 b0 10 a9 81 48 89 d7 48 89 e5 e8 5d fe ff ff 5d c3 0f 1f 00 <66> 89 3e c3 0f 1f 40 00 48 81 fe ff ff 03 00 48 89 f2 77 2c 48
kernel: [ 493.722583] RIP [<ffffffff8137aca8>] iowrite16+0x38/0x40
kernel: [ 493.722586] RSP <ffff8800555e7b88>
kernel: [ 493.722588] CR2: 00000000eb060000
kernel: [ 493.722591] ---[ end trace 2d3dfa92998d58a7 ]---
According to Ian Abbott now I tried this approach successfully. I don't really understand the mechanism behind but it works for now. So BAR2 is an Memory Register type. This approach uses ioremap
and not memory-mapping. How to get access to BAR2 via memory-mapping?
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
#define DEV_PCI_VENDORID 0x10B5
#define DEV_PCI_DEVICEID 0x1860
static struct pci_device_id pci_drvIdTable[] =
{
{
.vendor = DEV_PCI_VENDORID, // vendor ID
.device = DEV_PCI_DEVICEID, // device ID
.subvendor = PCI_ANY_ID, // no subsystem available
.subdevice = PCI_ANY_ID, // no subsystem available
.class = PCI_CLASS_NOT_DEFINED, // no device class
.class_mask = 0, // no device class
.driver_data = 0 // no private data to the driver
},
{ 0, } // end of table
};
struct pci_data
{
// struct pci_dev *pci_dev;
/// the IO mapping for the PCI config space
uint32_t *pciConfigAddr;
uint32_t *pciB2Addr;
wait_queue_head_t waitq;
uint8_t flag;
} *data;
static int
_pci_probe ( struct pci_dev *pdev,
const struct pci_device_id *ent )
{
int ret = 0;
int i;
u16 reg_16;
unsigned long *pbas2addr;
data = kzalloc( sizeof(*data) , GFP_KERNEL );
if( !data )
{
printk(KERN_ERR "Failed to allocate memory.\n");
return -ENOMEM;
}
pci_set_drvdata(pdev, data);
// enabling the device
ret = pci_enable_device(pdev);
if( ret )
{
printk(KERN_ERR "Failed to enable PCI device.\n");
goto no_enable;
}
pci_read_config_word(pdev,0,®_16);
printk(KERN_INFO "VendorID. %x\n",reg_16);
// checking if PCI-device reachable by checking that BAR0 is defined and
// memory mapped
if( !(pci_resource_flags(pdev,0) & IORESOURCE_MEM) )
{
printk(KERN_ERR "Incorrect BAR configuration.\n");
ret = -ENODEV;
goto bad_bar;
}
// taking ownership of a memory region
pbas2addr = pci_ioremap_bar(pdev, 2);
// void iowrite8(u8 val, void __iomem *addr)
for ( i = 0x060000; i<0x070000; i++ )
{
iowrite8( 0x11 , pbas2addr+i );
}
// further read/write function in the kernel:
// inp, readl, readw, readb, ioread8, ioread16, ioread32
// outp, writel, writew, writeb, iowrite8, iowrite16, iowrite32
bad_bar:
pci_disable_device(pdev);
no_enable:
pci_set_drvdata(pdev, data);
return ret;
}
static void
_pci_remove( struct pci_dev *pdev )
{
pci_disable_device(pdev);
printk(KERN_INFO "PCI-device removed.\n");
}
static struct pci_driver pci_drv =
{
.name = "expdev",
.id_table = pci_drvIdTable,
.probe = _pci_probe,
.remove = _pci_remove,
};
// module related functions ///////////////////////////////////////////////////
static int __init _module_init(void){
printk(KERN_INFO "Hello!\n");
pci_register_driver(&pci_drv);
return 0;
}
static void __exit _module_exit(void){
pci_unregister_driver(&pci_drv);
printk(KERN_INFO "Goodbye!\n");
}
module_init(_module_init);
module_exit(_module_exit);
I'm really at the end. I think I have fully follow the docs but it doesn't work as expected.
Here the code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/delay.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
#define DEV_PCI_VENDORID 0x10B5
#define DEV_PCI_DEVICEID 0x1860
static struct pci_device_id pci_drvIdTable[] =
{
{
.vendor = DEV_PCI_VENDORID, // vendor ID
.device = DEV_PCI_DEVICEID, // device ID
.subvendor = PCI_ANY_ID, // no subsystem available
.subdevice = PCI_ANY_ID, // no subsystem available
.class = PCI_CLASS_NOT_DEFINED, // no device class
.class_mask = 0, // no device class
.driver_data = 0 // no private data to the driver
},
{ 0, }
};
static int
_pci_probe ( struct pci_dev *pdev,
const struct pci_device_id *ent )
{
int ret = 0;
int i;
unsigned long *pbas2addr;
// enabling the device
ret = pci_enable_device(pdev);
if( ret )
{
printk(KERN_ERR "Failed to enable PCI device.\n");
goto no_enable;
}
pci_request_regions(pdev, "expdev");
// checking if PCI-device reachable by checking that BAR0 is defined and
// memory mapped
if( !(pci_resource_flags(pdev,0) & IORESOURCE_MEM) )
{
printk(KERN_ERR "Incorrect BAR configuration.\n");
ret = -ENODEV;
goto bad_bar;
}
// taking ownership of a memory region
pbas2addr = pci_ioremap_bar(pdev, 2);
printk(KERN_INFO "BAR2: %p\n",pbas2addr);
for ( i = 0x060000; i<0x070000; i++ )
{
iowrite8( 0x00 , pbas2addr+i );
}
// the next write operations cause crashing the the module
// load control word to set ICD in set-up-mode
iowrite32(0b01111000000101, pbas2addr+0x200014);
// load the bit-stuffed set up word
iowrite32(0b10110001001001101110000, pbas2addr+0x200018); // 39.5 MHz
// load control word to set ICD in set-up-mode
iowrite32(0b01111000000100, pbas2addr+0x200014);
msleep(10);
// load control word to set ICD in set-up-mode
iowrite32(0b01111000000000, pbas2addr+0x200014);
return 0;
bad_bar:
pci_disable_device(pdev);
return ret;
}
static void
_pci_remove( struct pci_dev *pdev )
{
pci_release_regions(pdev);
pci_disable_device(pdev);
printk(KERN_INFO "PCI-device removed.\n");
}
static struct pci_driver pci_drv =
{
.name = "expdev",
.id_table = pci_drvIdTable,
.probe = _pci_probe,
.remove = _pci_remove,
};
// module related functions
static int __init _module_init(void){
printk(KERN_INFO "Hello!\n");
pci_register_driver(&pci_drv);
return 0;
}
static void __exit _module_exit(void){
pci_unregister_driver(&pci_drv);
printk(KERN_INFO "Goodbye!\n");
}
module_init(_module_init);
module_exit(_module_exit);
With only the for-loop:
kernel: [ 467.545079] Hello!
kernel: [ 467.545136] expdev 0000:05:02.0: enabling device (0000 -> 0003)
kernel: [ 467.546807] BAR2: ffffc90006c00000
kernel: [ 467.562146] PCI-device removed.
kernel: [ 467.562489] Goodbye!
and I can see some outputs on the device GPIO.
If I write to the higher addresses as needed regarding to the device manual the LKM crashes:
kernel: [ 1324.591578] Hello!
kernel: [ 1324.593300] BAR2: ffffc90007c80000
kernel: [ 1324.605162] BUG: unable to handle kernel paging request at ffffc90008c800a0
kernel: [ 1324.605168] IP: [<ffffffff8137ace8>] iowrite32+0x38/0x40
kernel: [ 1324.605175] PGD 7d00d067 PUD 7d00e067 PMD 611e7067 PTE 0
kernel: [ 1324.605179] Oops: 0002 [#1] SMP
kernel: [ 1324.605183] Modules linked in: expdev(OX+) rfcomm bnep bluetooth nvidia(POX) snd_hda_codec_hdmi joydev snd_hda_codec_idt snd_hda_intel snd_hda_codec gpio_ich coretemp drm snd_seq_midi kvm snd_seq_midi_event dcdbas snd_rawmidi snd_hwdep lpc_ich snd_seq snd_pcm snd_seq_device snd_page_alloc shpchp ppdev serio_raw snd_timer lp snd soundcore mac_hid i82975x_edac edac_core parport_pc parport hid_generic usbhid hid psmouse ahci libahci pata_acpi tg3 ptp pps_core [last unloaded: expdev]
kernel: [ 1324.605219] CPU: 0 PID: 3155 Comm: insmod Tainted: P OX 3.13.0-79-generic #123-Ubuntu
kernel: [ 1324.605221] Hardware name: Dell Inc. Precision WorkStation 390 /0DN075, BIOS 2.3.0 05/01/2007
kernel: [ 1324.605224] task: ffff88007c048000 ti: ffff880061122000 task.ti: ffff880061122000
kernel: [ 1324.605226] RIP: 0010:[<ffffffff8137ace8>] [<ffffffff8137ace8>] iowrite32+0x38/0x40
kernel: [ 1324.605229] RSP: 0018:ffff880061123b90 EFLAGS: 00010292
kernel: [ 1324.605231] RAX: 0000000000000016 RBX: ffffc90008c800a0 RCX: 0000000000000000
kernel: [ 1324.605233] RDX: ffffc90008c800a0 RSI: ffffc90008c800a0 RDI: 0000000000001e05
kernel: [ 1324.605235] RBP: ffff880061123bb0 R08: 0000000000000096 R09: 0000000000000306
kernel: [ 1324.605237] R10: 0000000000000000 R11: ffff8800611238c6 R12: ffffc90007f80000
kernel: [ 1324.605239] R13: ffffc90007c80000 R14: ffff88007c2b4098 R15: ffffffffa01fc140
kernel: [ 1324.605242] FS: 00007fc6802cb740(0000) GS:ffff88007f800000(0000) knlGS:0000000000000000
kernel: [ 1324.605244] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: [ 1324.605246] CR2: ffffc90008c800a0 CR3: 0000000062f96000 CR4: 00000000000007f0
kernel: [ 1324.605248] Stack:
kernel: [ 1324.605249] ffffffffa01fa0ec ffff88007c2b4000 0000000000000000 ffffffffa01fc000
kernel: [ 1324.605253] ffff880061123be8 ffffffff813ac8a5 ffffffff813adb45 ffff88007c2b4098
kernel: [ 1324.605257] ffffffffffffffff ffff88007c2b4000 0000000000000018 ffff880061123c30
kernel: [ 1324.605260] Call Trace:
kernel: [ 1324.605267] [<ffffffffa01fa0ec>] ? _pci_probe+0xbc/0x110 [expdev]
kernel: [ 1324.605271] [<ffffffff813ac8a5>] local_pci_probe+0x45/0xa0
kernel: [ 1324.605274] [<ffffffff813adb45>] ? pci_match_device+0xc5/0xd0
kernel: [ 1324.605277] [<ffffffff813adc69>] pci_device_probe+0xd9/0x130
kernel: [ 1324.605281] [<ffffffff8149a4bd>] driver_probe_device+0x12d/0x3e0
kernel: [ 1324.605285] [<ffffffff8149a843>] __driver_attach+0x93/0xa0
kernel: [ 1324.605288] [<ffffffff8149a7b0>] ? __device_attach+0x40/0x40
kernel: [ 1324.605290] [<ffffffff81498403>] bus_for_each_dev+0x63/0xa0
kernel: [ 1324.605293] [<ffffffff81499e6e>] driver_attach+0x1e/0x20
kernel: [ 1324.605296] [<ffffffff81499a50>] bus_add_driver+0x180/0x250
kernel: [ 1324.605300] [<ffffffffa0006000>] ? 0xffffffffa0005fff
kernel: [ 1324.605303] [<ffffffff8149aec4>] driver_register+0x64/0xf0
kernel: [ 1324.605306] [<ffffffffa0006000>] ? 0xffffffffa0005fff
kernel: [ 1324.605309] [<ffffffff813ac23c>] __pci_register_driver+0x4c/0x50
kernel: [ 1324.605313] [<ffffffffa000602c>] _module_init+0x2c/0x1000 [expdev]
kernel: [ 1324.605317] [<ffffffff8100214a>] do_one_initcall+0xfa/0x1b0
kernel: [ 1324.605321] [<ffffffff810598f3>] ? set_memory_nx+0x43/0x50
kernel: [ 1324.605326] [<ffffffff810e2b7d>] load_module+0x12ed/0x1b50
kernel: [ 1324.605330] [<ffffffff810de5f0>] ? store_uevent+0x40/0x40
kernel: [ 1324.605334] [<ffffffff810e3556>] SyS_finit_module+0x86/0xb0
kernel: [ 1324.605338] [<ffffffff817363dd>] system_call_fastpath+0x1a/0x1f
kernel: [ 1324.605340] Code: 81 fe 00 00 01 00 76 0b 0f b7 d6 89 f8 ef c3 0f 1f 40 00 55 48 c7 c6 bf 10 a9 81 48 89 d7 48 89 e5 e8 1d fe ff ff 5d c3 0f 1f 00 <89> 3e c3 0f 1f 44 00 00 48 81 ff ff ff 03 00 77 37 48 81 ff 00
kernel: [ 1324.605373] RIP [<ffffffff8137ace8>] iowrite32+0x38/0x40
kernel: [ 1324.605376] RSP <ffff880061123b90>
kernel: [ 1324.605378] CR2: ffffc90008c800a0
kernel: [ 1324.605381] ---[ end trace 9b1029fd3f919791 ]---
RIP - but why. The offset is within the limits of 16 MB.
I think your code is corrent but you are supposed to check your resource files for the PCI host driver. When you call the funtion "pci_ioremap_bar(pdev, 2)", the function needs some resource data to remap the memory space.
For example,
[2] = {
.name = "ep_mem2",
.start = PCIE_BASE + 0x1000,
.end = PCIE_BASE + 0x2000 - 1,
.flags = IORESOURCE_MEM,
}