title: Cause PCIe error callbacks using AER injection
body: <p>I am trying to cause a callback in the Linux nvme driver by using AER injection. I've modified the AER source code to directly inject errors through module loading rather than from userland program. </p>
  
  <p>I've verified that I got the correct bus, dev, and fn and that the error injection went successfully, yet the error handling functions for the nvme driver did not pick up anything.</p>
  
  <p>Here is the modification for the aer_injection.c file</p>
  
  <p>This fills out the error structure</p>
  
  <pre><code> 554    static int __init aer_inject_init(void)
   555    {
   556    
   557        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   558        int ret = misc_register(&amp;aer_inject_device);
   559        struct aer_error_inj ae = {
   560           .bus             = 0x84,
   561           .dev             = 0x00,
   562        .fn              = 0x00, 
   563           .uncor_status    = 0x00040000,    //poisoned TLP
   564           .cor_status      = 0x0,
   565           .header_log0     = 0x0,
   566           .header_log1     = 0x1,
   567           .header_log2     = 0x2,
   568           .header_log3     = 0x3,
   569           .domain          = 0x00
   570        }; 
   571        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   572        aer_inject(&amp;ae); 
   573        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   574        return ret;
   575    }
  </code></pre>
  
  <p>This is the aer_inject() function:</p>
  
  <pre><code> 320    static int aer_inject(struct aer_error_inj *einj)
   321    {
   322        struct aer_error *err, *rperr;
   323        struct aer_error *err_alloc = NULL, *rperr_alloc = NULL;
   324        struct pci_dev *dev, *rpdev;
   325        struct pcie_device *edev;
   326        unsigned long flags;
   327        unsigned int devfn = PCI_DEVFN(einj-&gt;dev, einj-&gt;fn);
   328        int pos_cap_err, rp_pos_cap_err;
   329        u32 sever, cor_mask, uncor_mask, cor_mask_orig = 0, uncor_mask_orig = 0;
   330        int ret = 0;
   331        
   332        //einj-&gt;domain = 0x0000;
   333        //einj-&gt;bus = 0x84;
   334        //devfn = 0x0;  
   335    
   336        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   337        dev = pci_get_domain_bus_and_slot((int)einj-&gt;domain, einj-&gt;bus, devfn);
   338        printk(KERN_INFO "dev-&gt;vendor %#x\n", dev-&gt;vendor);
   339        printk(KERN_INFO "dev-&gt;device %#x\n", dev-&gt;device);
   340        if (!dev) {
   341            printk(KERN_INFO "ENODEV %s %d\n", __func__, __LINE__);
   342            return -ENODEV;
   343        }
   344        rpdev = pcie_find_root_port(dev);
   345        if (!rpdev) {
   346            ret = -ENODEV;
   347            goto out_put;
   348        }
   349    
   350        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   351        pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
   352        if (!pos_cap_err) {
   353            ret = -EPERM;
   354            goto out_put;
   355        }
   356        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &amp;sever);
   357        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &amp;cor_mask);
   358        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
   359                      &amp;uncor_mask);
   360    
   361        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   362        rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
   363        if (!rp_pos_cap_err) {
   364            ret = -EPERM;
   365            goto out_put;
   366        }
   367    
   368        err_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
   369        if (!err_alloc) {
   370            ret = -ENOMEM;
   371            goto out_put;
   372        }
   373        rperr_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
   374        if (!rperr_alloc) {
   375            ret = -ENOMEM;
   376            goto out_put;
   377        }
   378    
   379        if (aer_mask_override) {
   380            cor_mask_orig = cor_mask;
   381            cor_mask &amp;= !(einj-&gt;cor_status);
   382            pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
   383                           cor_mask);
   384    
   385            uncor_mask_orig = uncor_mask;
   386            uncor_mask &amp;= !(einj-&gt;uncor_status);
   387            pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
   388                           uncor_mask);
   389        }
   390    
   391        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   392        spin_lock_irqsave(&amp;inject_lock, flags);
   393    
   394        err = __find_aer_error_by_dev(dev);
   395        if (!err) {
   396            err = err_alloc;
   397            err_alloc = NULL;
   398            aer_error_init(err, einj-&gt;domain, einj-&gt;bus, devfn,
   399                       pos_cap_err);
   400            list_add(&amp;err-&gt;list, &amp;einjected);
   401        }
   402        err-&gt;uncor_status |= einj-&gt;uncor_status;
   403        printk(KERN_INFO "err-&gt;uncor_status %#x\n", err-&gt;uncor_status);
   404        err-&gt;cor_status |= einj-&gt;cor_status;
   405        err-&gt;header_log0 = einj-&gt;header_log0;
   406        err-&gt;header_log1 = einj-&gt;header_log1;
   407        err-&gt;header_log2 = einj-&gt;header_log2;
   408        err-&gt;header_log3 = einj-&gt;header_log3;
   409    
   410        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   411        if (!aer_mask_override &amp;&amp; einj-&gt;cor_status &amp;&amp;
   412            !(einj-&gt;cor_status &amp; ~cor_mask)) {
   413            ret = -EINVAL;
   414            printk(KERN_WARNING "The correctable error(s) is masked "
   415                    "by device\n");
   416            spin_unlock_irqrestore(&amp;inject_lock, flags);
   417            goto out_put;
   418        }
   419        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   420        if (!aer_mask_override &amp;&amp; einj-&gt;uncor_status &amp;&amp;
   421            !(einj-&gt;uncor_status &amp; ~uncor_mask)) {
   422            ret = -EINVAL;
   423            printk(KERN_WARNING "The uncorrectable error(s) is masked "
   424                    "by device\n");
   425            spin_unlock_irqrestore(&amp;inject_lock, flags);
   426            goto out_put;
   427        }
   428    
   429        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   430        rperr = __find_aer_error_by_dev(rpdev);
   431        if (!rperr) {
   432                printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   433            rperr = rperr_alloc;
   434            rperr_alloc = NULL;
   435            aer_error_init(rperr, pci_domain_nr(rpdev-&gt;bus),
   436                       rpdev-&gt;bus-&gt;number, rpdev-&gt;devfn,
   437                       rp_pos_cap_err);
   438            list_add(&amp;rperr-&gt;list, &amp;einjected);
   439        }
   440        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   441        if (einj-&gt;cor_status) {
   442            if (rperr-&gt;root_status &amp; PCI_ERR_ROOT_COR_RCV)
   443                rperr-&gt;root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
   444            else
   445                rperr-&gt;root_status |= PCI_ERR_ROOT_COR_RCV;
   446            rperr-&gt;source_id &amp;= 0xffff0000;
   447            rperr-&gt;source_id |= (einj-&gt;bus &lt;&lt; 8) | devfn;
   448        }
   449        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   450        if (einj-&gt;uncor_status) {
   451                printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   452            if (rperr-&gt;root_status &amp; PCI_ERR_ROOT_UNCOR_RCV)
   453            {
   454                printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   455                rperr-&gt;root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
   456            if (sever &amp; einj-&gt;uncor_status) {
   457                rperr-&gt;root_status |= PCI_ERR_ROOT_FATAL_RCV;
   458                if (!(rperr-&gt;root_status &amp; PCI_ERR_ROOT_UNCOR_RCV))
   459                    rperr-&gt;root_status |= PCI_ERR_ROOT_FIRST_FATAL;
   460            } else
   461                rperr-&gt;root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
   462            rperr-&gt;root_status |= PCI_ERR_ROOT_UNCOR_RCV;
   463            rperr-&gt;source_id &amp;= 0x0000ffff;
   464            rperr-&gt;source_id |= ((einj-&gt;bus &lt;&lt; 8) | devfn) &lt;&lt; 16;
   465        }
   466        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   467        spin_unlock_irqrestore(&amp;inject_lock, flags);
   468    
   469        if (aer_mask_override) {
   470            pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
   471                           cor_mask_orig);
   472            pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
   473                           uncor_mask_orig);
   474        }
   475    
   476        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   477        ret = pci_bus_set_aer_ops(dev-&gt;bus);
   478        if (ret)  
   479            goto out_put;
   480        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   481        ret = pci_bus_set_aer_ops(rpdev-&gt;bus);
   482        if (ret)
   483            goto out_put;
   484    
   485        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   486        if (find_aer_device(rpdev, &amp;edev)) {
   487            if (!get_service_data(edev)) {
   488                printk(KERN_WARNING "AER service is not initialized\n");
   489                ret = -EINVAL;
   490        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   491                goto out_put;
   492            }
   493            aer_irq(-1, edev);
   494        }
   495        else
   496            ret = -EINVAL;
   497        printk(KERN_INFO "%s %d\n", __func__, __LINE__);
   498    out_put:
   499        kfree(err_alloc);
   500        kfree(rperr_alloc);
   501        pci_dev_put(dev);
   502        return ret;
   503    }
  </code></pre>
  
  <p>This is the function I am attempting to hit in the nvme driver:</p>
  
  <pre><code>2563 static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev,
  2564                 enum pci_channel_state state)
  2565 {
  2566 
  2567                 printk(KERN_INFO "nvme_error_detected called\n");
  2568                 dev_printk(KERN_ERR, &amp;pdev-&gt;dev, "%s\n", __func__);
  2569 }
  </code></pre>
  
  <p>Verification from kernel:</p>
  
  <pre><code>aer_inject_init 555
  aer_inject_init 569
  aer_inject 336
  dev-&gt;vendor 0x1c58
  dev-&gt;device 0x3
  aer_inject 350
  aer_inject 361
  aer_inject 391
  err-&gt;uncor_status 0x40000
  aer_inject 410
  aer_inject 419
  aer_inject 429
  aer_inject 432
  aer_inject 440
  aer_inject 449
  aer_inject 451
  aer_inject 464
  aer_inject 474
  aer_inject 478
  aer_inject 483
  aer_inject 495
  aer_inject_init 571
  </code></pre>
  
  <p>As we can see, the kernel messages did not print from the driver but executed fully throughout the AER injection method. What could be the cause of this? Thank you for apologies for the messy code formatting.</p>