title: Address mapping of PCI-memory in Kernel space
body: <p>I'm trying to read and write to and PCI-device from a loadable kernel module.</p>
  
  <p>Therefore I follow this <a href="https://stackoverflow.com/questions/23414288/do-i-need-to-enable-a-pcie-memory-region-in-a-linux-3-12-driver">post</a>:</p>
  
  <pre><code>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 */
  </code></pre>
  
  <p>But at the end the device doesn't do his work as expected. Then I look to the address behind <code>bar1</code> and found a very big value <code>ffffbaaaaa004500</code>.</p>
  
  <p>At this point I don't really understand what was happen there and what was right. Can I interpret <code>bar1</code> as an address inside my kernel address space which points directly to the base address which is <code>0x60000</code> offset to the PCI Chip Select Address?</p>
  
  <p>And how can it be that the value I write to <code>bar1 + offset</code> copied to the device? How does the mechanism work in behind of <code>iowrite32</code> and <code>pci_iomap</code>?</p>
  
  <p>Thanks and regards</p>
  
  <p>Alex</p>
  
  <p>PS: I tested a read back from the same address successfully.</p>
  
  <hr>
  
  <p>Register description of the PCI device:</p>
  
  <ul>
  <li><code>PCIBAR0</code> PCI Base Address 0; used for Memory-Mapped Configuration Registers</li>
  <li><code>PCIBAR1</code> PCI Base Address 1; used for I/O-Mapped Configuration Registers</li>
  <li><code>PCIBAR2</code> PCI Base Address 2; used for Local Address Space 0</li>
  <li><code>PCIBAR3</code> PCI Base Address 3; used for Local Address Space 1</li>
  <li><code>PCIBAR4</code> Unused Base Address</li>
  <li><code>PCIBAR5</code> Unused Base Address</li>
  </ul>
  
  <hr>
  
  <p>Hello again.</p>
  
  <p>In the last time I tried several approaches to communicate with the BAR2 register but without success. Here my actual code:</p>
  
  <pre><code>#include &lt;linux/init.h&gt;
  #include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/pci.h&gt;
  #include &lt;linux/interrupt.h&gt;
  #include &lt;linux/sched.h&gt;
  
  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-&gt;flag = 1;
    wake_up_interruptible( &amp;data-&gt;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,&amp;reg_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) &amp; 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-&gt;irq, data);
    pci_disable_msi(pdev);
    pci_clear_master(pdev);
    pci_iounmap(pdev,data-&gt;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(&amp;pci_drv);
  
     return 0;
  }
  
  static void __exit _module_exit(void){
  
     pci_unregister_driver(&amp;pci_drv);
  
     printk(KERN_INFO "Goodbye!\n");
  }
  
  module_init(_module_init);
  module_exit(_module_exit);
  </code></pre>
  
  <p>This is the responding output with <code>tail -f /var/log/kern.log</code></p>
  
  <pre><code>kernel: [  493.719999] Hello!
  kernel: [  493.720071] expdev 0000:05:02.0: enabling device (0000 -&gt; 0003)
  kernel: [  493.720845] VendorID. 10b5
  kernel: [  493.722375] BUG: unable to handle kernel paging request at 00000000eb060000
  kernel: [  493.722381] IP: [&lt;ffffffff8137aca8&gt;] 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:[&lt;ffffffff8137aca8&gt;]  [&lt;ffffffff8137aca8&gt;] 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]  [&lt;ffffffffa02291c4&gt;] ? _pci_probe+0x114/0x215 [expdev]
  kernel: [  493.722481]  [&lt;ffffffff813ac8a5&gt;] local_pci_probe+0x45/0xa0
  kernel: [  493.722484]  [&lt;ffffffff813adb45&gt;] ? pci_match_device+0xc5/0xd0
  kernel: [  493.722487]  [&lt;ffffffff813adc69&gt;] pci_device_probe+0xd9/0x130
  kernel: [  493.722492]  [&lt;ffffffff8149a4bd&gt;] driver_probe_device+0x12d/0x3e0
  kernel: [  493.722495]  [&lt;ffffffff8149a843&gt;] __driver_attach+0x93/0xa0
  kernel: [  493.722498]  [&lt;ffffffff8149a7b0&gt;] ? __device_attach+0x40/0x40
  kernel: [  493.722501]  [&lt;ffffffff81498403&gt;] bus_for_each_dev+0x63/0xa0
  kernel: [  493.722504]  [&lt;ffffffff81499e6e&gt;] driver_attach+0x1e/0x20
  kernel: [  493.722507]  [&lt;ffffffff81499a50&gt;] bus_add_driver+0x180/0x250
  kernel: [  493.722510]  [&lt;ffffffffa0005000&gt;] ? 0xffffffffa0004fff
  kernel: [  493.722514]  [&lt;ffffffff8149aec4&gt;] driver_register+0x64/0xf0
  kernel: [  493.722517]  [&lt;ffffffffa0005000&gt;] ? 0xffffffffa0004fff
  kernel: [  493.722520]  [&lt;ffffffff813ac23c&gt;] __pci_register_driver+0x4c/0x50
  kernel: [  493.722523]  [&lt;ffffffffa000502c&gt;] _module_init+0x2c/0x1000 [expdev]
  kernel: [  493.722528]  [&lt;ffffffff8100214a&gt;] do_one_initcall+0xfa/0x1b0
  kernel: [  493.722532]  [&lt;ffffffff810598f3&gt;] ? set_memory_nx+0x43/0x50
  kernel: [  493.722536]  [&lt;ffffffff810e2b7d&gt;] load_module+0x12ed/0x1b50
  kernel: [  493.722540]  [&lt;ffffffff810de5f0&gt;] ? store_uevent+0x40/0x40
  kernel: [  493.722544]  [&lt;ffffffff810e3556&gt;] SyS_finit_module+0x86/0xb0
  kernel: [  493.722548]  [&lt;ffffffff817363dd&gt;] 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 &lt;66&gt; 89 3e c3 0f 1f 40 00 48 81 fe ff ff 03 00 48 89 f2 77 2c 48 
  kernel: [  493.722583] RIP  [&lt;ffffffff8137aca8&gt;] iowrite16+0x38/0x40
  kernel: [  493.722586]  RSP &lt;ffff8800555e7b88&gt;
  kernel: [  493.722588] CR2: 00000000eb060000
  kernel: [  493.722591] ---[ end trace 2d3dfa92998d58a7 ]---
  </code></pre>
  
  <hr>
  
  <p>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 <code>ioremap</code> and not memory-mapping. How to get access to BAR2 via memory-mapping?</p>
  
  <pre><code>#include &lt;linux/init.h&gt;
  #include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/pci.h&gt;
  
  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,&amp;reg_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) &amp; 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&lt;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(&amp;pci_drv);
     return 0;
  }
  
  static void __exit _module_exit(void){
     pci_unregister_driver(&amp;pci_drv);
     printk(KERN_INFO "Goodbye!\n");
  }
  
  module_init(_module_init);
  module_exit(_module_exit);
  </code></pre>
  
  <hr>
  
  <p>I'm really at the end. I think I have fully follow the docs but it doesn't work as expected.</p>
  
  <p>Here the code:</p>
  
  <pre><code>#include &lt;linux/init.h&gt;
  #include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/pci.h&gt;
  #include &lt;linux/interrupt.h&gt;
  #include &lt;linux/sched.h&gt;
  
  #include &lt;linux/delay.h&gt;
  
  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) &amp; 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&lt;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(&amp;pci_drv);
     return 0;
  }
  
  static void __exit _module_exit(void){
     pci_unregister_driver(&amp;pci_drv);
     printk(KERN_INFO "Goodbye!\n");
  }
  
  module_init(_module_init);
  module_exit(_module_exit);
  </code></pre>
  
  <p>With only the for-loop:</p>
  
  <pre><code>kernel: [  467.545079] Hello!
  kernel: [  467.545136] expdev 0000:05:02.0: enabling device (0000 -&gt; 0003)
  kernel: [  467.546807] BAR2: ffffc90006c00000
  kernel: [  467.562146] PCI-device removed.
  kernel: [  467.562489] Goodbye!
  </code></pre>
  
  <p>and I can see some outputs on the device GPIO.</p>
  
  <p>If I write to the higher addresses as needed regarding to the device manual the LKM crashes:</p>
  
  <pre><code>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: [&lt;ffffffff8137ace8&gt;] 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:[&lt;ffffffff8137ace8&gt;]  [&lt;ffffffff8137ace8&gt;] 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]  [&lt;ffffffffa01fa0ec&gt;] ? _pci_probe+0xbc/0x110 [expdev]
  kernel: [ 1324.605271]  [&lt;ffffffff813ac8a5&gt;] local_pci_probe+0x45/0xa0
  kernel: [ 1324.605274]  [&lt;ffffffff813adb45&gt;] ? pci_match_device+0xc5/0xd0
  kernel: [ 1324.605277]  [&lt;ffffffff813adc69&gt;] pci_device_probe+0xd9/0x130
  kernel: [ 1324.605281]  [&lt;ffffffff8149a4bd&gt;] driver_probe_device+0x12d/0x3e0
  kernel: [ 1324.605285]  [&lt;ffffffff8149a843&gt;] __driver_attach+0x93/0xa0
  kernel: [ 1324.605288]  [&lt;ffffffff8149a7b0&gt;] ? __device_attach+0x40/0x40
  kernel: [ 1324.605290]  [&lt;ffffffff81498403&gt;] bus_for_each_dev+0x63/0xa0
  kernel: [ 1324.605293]  [&lt;ffffffff81499e6e&gt;] driver_attach+0x1e/0x20
  kernel: [ 1324.605296]  [&lt;ffffffff81499a50&gt;] bus_add_driver+0x180/0x250
  kernel: [ 1324.605300]  [&lt;ffffffffa0006000&gt;] ? 0xffffffffa0005fff
  kernel: [ 1324.605303]  [&lt;ffffffff8149aec4&gt;] driver_register+0x64/0xf0
  kernel: [ 1324.605306]  [&lt;ffffffffa0006000&gt;] ? 0xffffffffa0005fff
  kernel: [ 1324.605309]  [&lt;ffffffff813ac23c&gt;] __pci_register_driver+0x4c/0x50
  kernel: [ 1324.605313]  [&lt;ffffffffa000602c&gt;] _module_init+0x2c/0x1000 [expdev]
  kernel: [ 1324.605317]  [&lt;ffffffff8100214a&gt;] do_one_initcall+0xfa/0x1b0
  kernel: [ 1324.605321]  [&lt;ffffffff810598f3&gt;] ? set_memory_nx+0x43/0x50
  kernel: [ 1324.605326]  [&lt;ffffffff810e2b7d&gt;] load_module+0x12ed/0x1b50
  kernel: [ 1324.605330]  [&lt;ffffffff810de5f0&gt;] ? store_uevent+0x40/0x40
  kernel: [ 1324.605334]  [&lt;ffffffff810e3556&gt;] SyS_finit_module+0x86/0xb0
  kernel: [ 1324.605338]  [&lt;ffffffff817363dd&gt;] 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 &lt;89&gt; 3e c3 0f 1f 44 00 00 48 81 ff ff ff 03 00 77 37 48 81 ff 00 
  kernel: [ 1324.605373] RIP  [&lt;ffffffff8137ace8&gt;] iowrite32+0x38/0x40
  kernel: [ 1324.605376]  RSP &lt;ffff880061123b90&gt;
  kernel: [ 1324.605378] CR2: ffffc90008c800a0
  kernel: [ 1324.605381] ---[ end trace 9b1029fd3f919791 ]---
  </code></pre>
  
  <p>RIP - but why. The offset is within the limits of 16 MB.</p>