linuxlinux-kernelpcispinlock

where is implemented pci_user_write_config_word?


As indicated by the perf report analysis, my user application interacts with the kernel when reading from a PCI device, specifically through a function called pci_user_write_config_dword.

I'm interested in exploring this function to comprehend why it invokes _raw_spin_lock_irq.

I've been unable to locate the actual implementation of this function. I've only found its definition in the kernel source code at the following location: https://elixir.bootlin.com/linux/v5.18.19/source/include/linux/pci.h#L1235

Where can I find the implementation of pci_user_write_config_dword in the Linux kernel source code?

user_ application         [kernel.kallsyms]                        [k] do_syscall_64
            |          
            |--90.82%--do_syscall_64
            |          |          
            |          |--61.22%--__x64_sys_pwrite64
            |          |          |          
            |          |           --61.21%--ksys_pwrite64
            |          |                     |          
            |          |                      --61.05%--vfs_write
            |          |                                |          
            |          |                                 --60.87%--__vfs_write
            |          |                                           |          
            |          |                                            --60.79%--kernfs_fop_write
            |          |                                                      |          
            |          |                                                       --60.19%--sysfs_kf_bin_write
            |          |                                                                 |          
            |          |                                                                  --60.18%--pci_write_config
            |          |                                                                            |          
            |          |                                                                            |--57.62%--pci_user_write_config_dword
            |          |                                                                            |          |          
            |          |                                                                            |          |--35.92%--_raw_spin_lock_irq
            |          |                                                                            |          |          |          
            |          |                                                                            |          |           --35.88%--native_queued_spin_lock_slowpath

Solution

  • You can find it in drivers/pci/access.c:

        /* Returns 0 on success, negative values indicate error. */
    #define PCI_USER_WRITE_CONFIG(size, type)                               \
    int pci_user_write_config_##size                                        \
            (struct pci_dev *dev, int pos, type val)                        \
    {                                                                       \
            int ret = PCIBIOS_SUCCESSFUL;                                   \
            if (PCI_##size##_BAD)                                           \
                    return -EINVAL;                                         \
            raw_spin_lock_irq(&pci_lock);                           \
            if (unlikely(dev->block_cfg_access))                            \
                    pci_wait_cfg(dev);                                      \
            ret = dev->bus->ops->write(dev->bus, dev->devfn,                \
                                            pos, sizeof(type), val);        \
            raw_spin_unlock_irq(&pci_lock);                         \
            return pcibios_err_to_errno(ret);                               \
    }                                                                       \
    EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
    

    You may have found it more difficult than usual to search for because an entire class of functions (operating on byte, word, dword) is defined in one go by using the C preprocessor's token concatenation feature plus a convenient helper macro. This is economical codewise but can defeat code browsers such as cscope. If you're not familiar, you can read about C token concatenation here and start making your own kernel code more compact with it.