3

I have a user space program that simulates a PCI device. I have downloaded the nvme linux device driver that interacts with the PCI device using the NVMe standard. I have to verify that my userspace program is compatible with the standard.

The nvme.c(the linux device driver) contains the nvme_probe() function that would be called when the device is plugged in. Since I do not have the device so I think I will incorporate the probe functionality in nvme_init() function.

Now I have studied quite a lot on the internet to understand how to emulate a PCI device, posts such as Installing PCI driver without connection to device, emulating a PCI device on linux I do not get the idea how to return the populated struct pci_dev to the function call in the nvme_probe() ofpci_set_drvdata(pdev, dev);

And if you could suggest a tutorial, on how to manually populate the pci_dev struct with dummy device configuration and memory address of the userspace program function pointers to emulate interaction with the nvme driver.

Community
  • 1
  • 1
hasanijaz
  • 33
  • 1
  • 6

1 Answers1

1

I don't think it is possible to fake such thing with standard linux kernel.

Because in module_init() you are telling the kernel's PCI SUBSYSTEM to load the operation handlers (a.k.a - callbacks through function pointers) when a certain device is present in the system (via id_table).

so whenever you insmod your module, kernel's PCI SUBSYTEM then knows to load your driver whenever a device of matching vid/pid is plugged into the PCIe slot. The operation is like below -

  • Tell kernel to load {my_driver.ko} when this {vid/pid} pci device is found in module_init or _init
  • After kernel knew, whenever a matching {vid/pid} device is connected to the system, it will call the .probe function callback of {my_driver.ko}
  • You may init the device (for real-device) or just return true to tell kernel that has correctly initialized the device. You can also register new driver type from this probe function (for read/write).

I am not sure about any magic VID/PID number which causes the PCI SUBSYTEM to always load the driver.

But you can actually load the PCI driver by using an actual PCI device.

Just remove appropriate driver for a real-PCI device. and use it's VID & PID as your driver's VID PID. Then the PCI SUBSYTEM will load your driver & you can also test your driver to simulate PCI device afterwards.

Hope this helps,

regards.

fadedreamz
  • 1,156
  • 1
  • 10
  • 19
  • Thanks for explaining... It does clear a lot of things. Now I am thinking that I will remove all calls to the PCI subsystem. The nvme driver uses queues to communicate with the PCI device. I am thinking about copying the queue data to user space from where it will trigger the simulation code. Please comment.. And do send me a tutorial on communication of kernel modules with user space programs. – hasanijaz Dec 10 '12 at 04:22
  • You can do that to test your program, (if you want to interact with driver only). I don't have any experience on nvme driver, but generally all driver will follow the pattern below - [nvme-driver]<---loads--[pci-driver]<--loads--[pci-bus-driver]<----notify-system---[device]. Arrow denotes the loading order. So, If you are enabling a fs driver, I think you have to short-circuit (kind of loopback) the read/write function used in nvme-driver. If you want to just grab data from the driver, you can use netlink. I am not sure which path you want to use. hope this helps – fadedreamz Dec 12 '12 at 16:28
  • Does this answer still stand? Any changes on this with newer kernels? Are there any options to emulate a PCIe device without HW? – Vinu Chandran May 26 '21 at 06:32