How do PCIe devices advertise multiple virtual functions to Linux? - linux-kernel

SR-IOV lets PCIe devices expose a single physical function and multiple virtual functions. How does the kernel detect that a device supports virtual functions? Is it a part of the PCIe configuration registers? Where in the kernel are devices tested for how many functions they export?
EDIT: I'm looking for a line of code (or a file) in the kernel source that inspects a PCIe device in order to determine how many virtual functions it exports. I'd also settle for a link to the appropriate standard that lays out what information a device needs to send to the host in order to report that it supports multiple virtual functions.

An SR-IOV capable device defines the SR-IOV Capability (extended capability ID 10h).
This is specified in chapter 9 of the PCI Express Base specification revision 4.0. I'm not sure whether you can find a free copy online; you may need to be a PCI-SIG member.
In the Linux kernel, look for PCI_EXT_CAP_ID_SRIOV and PCI_SRIOV_TOTAL_VF in drivers/pci/iov.c.

Related

Difference between Character Device, Platform Driver and Kernel Module

I am a newbie to Linux Kernel device driver codes.
One question up on the other: which is the difference between:
Character Device
Platform Driver
Kernel Module
I am writing this question because, within the same code I am examining, there are three section: one for each.
Platform Device Driver:
A platform device driver is generally written for on-chip components/devices and on-chip/off-chip unspeakable/un-discoverable devices.
If there is a device on-chip/off-chip, which doesn't have a self-identifying capability, like say i2x devices, GPIO line based, or in-circuit (on-chip) timers, etc. Then such devices need to be identified by the drivers because the devices don't have self-ID, or capability to identify themselves. This generally happens with bus lines and on-chip components.
Here is detailed explanation.
Example platform Devices: i2c devices, kernel/Documentation/i2c/instantiating-devices states:
Basically, all device drivers can be categorized into character, or block; based on the data transaction size.
Though there are many sub-classifications like network devices drivers and X device drivers, they too can be brought into devices, which carry data transactions (operations) in terms of few bytes that undergo tr
Typically, a platform device driver can fit into character device driver section, as they generally involve on-chip operations, for initialization and to transfer a few bytes, whenever needed, but not in terms of blocks (KB, MB, GB) of data.
Kernel Module?
Now, a driver can be either compiled (to be integrated) into kernel image (zImage/bzImage/...) OR can be compiled (off-the kernel) to be optionally invokable modular driver, which is not part of kernel image, but is part of filesystem as a .ko (kernel object) file (find /lib/modules/`uname -r`/ -name "*.ko"), that stays off the kernel image, but can be inserted (using modprobe/insmod) or removed (using rmmod/modprobe -r) as necessary.
On the other hand, a built-in driver can't be removed dynamically, even if we don't need it momentarily. A built-in driver would remain in the kernel and hence on RAM, as long as the system is running, even if the respective device is "not found"/"not necessary/"shutdown"), just wasting memory space (on RAM).
The Module (or modular driver), would only step-in, when necessary, from secondary storage to RAM, and can be removed if the device is removed or not-in-action. This saves RAM and helps dynamic allocation of resources.

How is /proc/io* populated?

So if I understand things correctly, cat /proc/iomem lists the memory addresses that are mapped to this and that device register and similarily for ioports. If you pick up some book on Linux device drivers, it will state something about iomem being populated by the driver calling request_region() or something like that.
But how does the device driver know where the hardware register is located at from the get-go? For example, rtc0 seems to occupy 0070:0071 for most people - how does Linux/the device driver know that the transistors and wires of my system are hooked up so that flipping exactly those bits corresponds to reading a signal from the RTC?
If you pick up some book on Linux device drivers, it will state something about iomem being populated by the driver calling request_region() or something like that.
The information in /proc/iomem comes from drivers calling request_mem_region().
See Content of /proc/iomem.
how does the device driver know where the hardware register is located
The address of a device register is typically specified by either the board (for an external peripheral) or SoC designer (for an integrated peripheral), and then conveyed in the board or SoC documentation. Some boards (e.g. PC ISA adapter boards) may allow address specification by some DIP switches.
The writer of the device driver then can
(a) hardcode the device address in the driver itself or a board file, or
(b) retrieve the device address using some bus configuration method (e.g. PCI configuration space), or
(c) retrieve the device address using a (handwritten) configuration list (e.g. Device Tree, FEX, ATAGs), or
(d) try to probe the device at runtime.
Note that conveying the system configuration and device addresses to device drivers is a longstanding issue.
The IBM PC's method of assigned addresses that were then hardcoded eventually led to the plug and play initiative for x86 PCs.
Issues with unique Linux kernel builds for each and every ARM board led to the adoption of Device Tree (from PowerPC) for that architecture.

what PSH kernel in intel edison mean? Is it the name of primary bootloader present inside ROM?

I was going through the logs after booting up the intel edison. I came accross the word. Is it the name of bios?Does it do some security verification like key matching/checking and all ?
Intel Edison board, more precisely Intel Tangier SoC, has a Minute IA (i486+, also known as Pentium ISA microarchitecture) based MCU (for example, Intel Quark D2000 SoC has it as far as I know) which is part of so called Platform Services Hub (PSH). PSH has own Page Cache (to keep RTOS and its applications), LAPIC. The peripheral, such as DMA and I2C, is shared with System Controller Unit (SCU). SCU actually controls PSH.
When system starts MCU boots first. Inside it is a Viper RTOS with some modifications, i.e. it has a library to support sensors.
There is no information available from Intel regarding use of open source RTOS, such as Zephyr, on PSH.

Porting a Linux kernel driver to libusb

So I was wondering: Since libusb provides userspace access to USB, is it possible to port already existing kernel drivers to libusb?
I do understand it might need rewriting of the driver, but do you think it is possible to write a "virtual kernel" that relies on libusb for access to devices and link already existing drivers to that? Essentially writing a layer between libusb and kernel modules that translates kernel USB commands to libusb commands.
Why bother? If you want to run a kernel driver on Android for example, you need to make sure it was compiled for a particular kernel version/device model. So an app will not be able to run on all devices. On the other hand libusb is fully compatible with most of the latest Android devcices.
AFAIK, libusb is a library that communicates with the higher level of the USB layer of the kernel. The lowest parts of the USB subsystem have to be written in kernel space, because they need to have access to the physical address space of the USB host controller and uses interrupts, and other low-level functions that are not possible to implement in user space.
So I don't think that it is possible to port low-level parts of the USB subsystem in user-space.

where is device driver code executed? Kernel space or User space?

Part1:
To the linux/unix experts out there, Could you please help me understanding about device drivers. As i understood, a driver is a piece of code that directly interacts with hardware and exposes some apis to access the device. My question is where does this piece of code runs, User space or Kernel space?
I know that code that is executed in kernel space has some extra privileges like accessing any memory location(pls correct if i'm wrong). If we install a third party driver and if it runs in kernel space, wouldn't this be harmful for the whole system? How any OS handles this?
Part2:
Lets take an example of USB device(camera, keyboard..), How the system recognizes these devices? how does the system know which driver to install? How does the driver know the address of the device to read and write the data?
(if this is too big to answer here, pls provide links of some good documentation or tutorials.., I've tried and couldn't find answers for these. pls help)
Part 1
On linux, drivers run in kernel space. And yes, as you state there a significant security implications to this. Most exceptions in drivers will take down the kernel, potentially corrupt kernel memory (with all manner of consequences). Buggy drivers also have an impact on system security, and malicious drivers can do absolutely anything they want.
A trend seen on MacOSX and Window NT kernels is user-space drivers. Microsoft has for some time been pushing the Windows Userspace Driver Framework, and MacOSX has long provided user-space APIs for Firewire and USB drivers, and class-compliant drivers for many USB peripherals. it is quite unusual to install 3rd party kernel-mode device drivers on MacOSX.
Arguably, the bad reputation Windows used to have for kernel panics can be attributed to the (often poor quality) kernel mode drivers that came with just about every mobile phone, camera and printer.
Linux graphics drivers are pretty much all implemented in user-space with a minimal kernel-resident portion, and Fuse allows the implementation of filing systems in user-space.
Part 2
USB, Firewire, MCI (and also PCI-e) all have enumeration mechanisms through which a bus driver can match the device to a driver. In practice this means that all devices expose metadata describing what they are.
Contained within the metadata is a DeviceID, VendorID and a description of functions the device provides and associated ClassIDs. ClassIDs facilitate generic Class Drivers.
Conceptually, the operating system will attempt to find a driver that specifically supports the VendorID and DeviceID, and then fall back to one that supports the ClassID(s).
Matching devices to drivers is a core concept at the heart of the Linux Device Model, and exact matching criteria used for matching is match() function in the specific bus driver.
Once device drivers are bound to a device, it uses the bus-driver (or addressing information given by it) to perform read and writes. In the case of PCI and Firewire, this is a memory mapped IO address. For USB it bus addressing information.
The Linux Documentation tree provides some insight into the design of the Linux Device Model, but isn't really entry-level reading.
I'd also recommend reading Linux Device Driver (3rd Edition)

Resources