How is /proc/io* populated? - linux-kernel

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.

Related

Problem identifying correct driver for I/O expanders on embedded device

I'm using the embedded device(USRP N310) and I've been trying to figure out what drivers are associated with particular devices on the platform such as the I/O expanders, the TCA6408 and the TCA6424A. From the device, I go into /sys/bus/i2c/drivers directory and I'm able to see all the drivers associated with i2c. There is a driver listed, pca953x, that that lists the addresses of the I/O expander devices of interest. Furthermore, when I go into one of the subdirectories for one of the devices, 10-0020, which describes adapter number and the address of the device, there is symlink to the pca953x driver as shown here
I believe this to be the driver associated with the I/O expander devices of interest but I would have expected the drivers to be different. Namely, I would have expected a driver named tca6408 for that particular chip and perhaps a different driver named tca6424 for the other chip. Is this the correct driver for these chips or am I misinterpreting what I'm seeing here?

How do PCIe devices advertise multiple virtual functions to Linux?

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.

How do the files in '/dev' match Linux's model of a device? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Here is my understanding in opening to a file for reading/writing.
In the application layer, I can invoke the fopen() function.
The fwrite() function will invoke a system call open().
After the OS receives the open() call, it will pass the command to VFS(virtual file system).
VFS looks up the file name, including any directories needed and does the necessary access checks.
If this is in RAM cache then no disk access is needed. If not, the VFS sends a read request to the specific file system which is probably EXT4.
Then the EXT4 file system driver will determine in what disk block that directory is located in. It will then send a read command to the disk device driver.
So now let's say I want to read an i2c device A attached to the board. And the file directory is /dev/i2c/A
Is there a major number for all devices? For example, Linux OS sets 180 as the major number for USB. So at the device side, is there a major number 180 in each USB device?
If the answer to 1st question is NO, then how can the Linux OS determine which type of device A is, is it just according to the file directory?
I think the answer to 2nd question maybe: at the boot initialization stage, there are some certain codes that have already mount that port to the file system using something like export()? So in fact, right after the booting stage, file directory /dev/i2c/A exists there and it is bind with a major number for i2c devices. So when I want to open dev/i2c/A, the OS will find the right i2c driver for me, not the SPI or USB driver.I'm not sure about this part, i need more information on this.
The above situation happens when the device is mounted to the file system right after the booting stage. so what happened if I have a usb, how can this usb be mounted to the file system with the right major number 180 after it is plugged in? And I guess there is a irq when the usb is plugged in before the mounting stage starts?
See: hotplug doc. If you run the sample code, you can see that a netlink event is sent when a device is added/removed from USB. This is part of the driver model. Each driver should attach to a BUS; this can be platform, USB, I2C, SPI, PCI, etc. As well, with in the sysfs, there will be entries to identify the particular device. Often an I2C address can be used to identify a particular client/slave chip. The driver model also facilitates suspend, resume, ordered shutdown, etc.
The files in /dev/ are created by udev or mdevuser-space programs . They associate a name with a device node (major,minor,char/block). You can use sysfs and/or your udev script to create a device name that you want based on netlink information; most of which is available to udev scripts.
Edit: For i2c the bus master driver discovers the address of devices by running a probeNote 1. A device is associated with a particular driver with a table. For example, the stargate machine file has imote2_i2c_board_info which associates i2c addresses with drivers. A similar table exists for SPI devices. PlatformNote 2 devices are added with platform_add_devices(). USB and PCI devices are identified by similar BUS specific ids of a device. Usually a machine file (or more recently device tree) associates the two.
See Also: Linux Journal - I2C Drivers pt1, Linux Journal - I2C Drivers pt2
I believe a source of confusion is that all drivers/devices are those you see in the /dev/ directory. This is not true. Only top level drivers are seen by users. Many Linux drivers/devices are used by a master device. They can form a hierarchy of devices. Usually only the top level device is exposed to the user. There are functions such as spi_write(), that a higher level driver can use to talk via SPI, the SPI device is not exposed to user space. Sound and media/tv capture cards often use an SPI device, but the user never knows this BUS exists and is being used. Often multiple card vendors will use the same chip-sets underneath. Instead of writing drivers for every card, only some glue for the card is written. Then a generic collection of chip drivers are used with the glue to tie it all together at the top of the hierarchy; this is the top level driver that is exposed to user space. This also allows smartTM chip vendors to create good drivers that system integrators can use.
Note 1: By i2c probe, I mean an I2C message that requests all registered addresses on the bus. I am not sure if probe is the correct i2c nomenclature.
Note 2 Platform devices are SOC devices. They have no associated BUS, so platform is a catch-all. Typically, platform devices are integrated with the CPU (SOC stands for system on chip).
Every device has a major and minor number. You can see them by doing
ls -n /dev
For some drivers, like the disk, the major numbers are hard coded. For others it is dynamic. Minor numbers can be assigned dynamically as devices are discovered at runtime, not just at boot. The kernel maintains an internal device switch table that maps the dev numbers to the correct driver.

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)

Keeping device functionality inside device controller rather than OS kernel. What are consequences?

A friend of mine asked me this question in the class and I could not answer it. He asked:
Since we know kernel controls the physical hardware via device drivers. What if all this functionality is kept inside the device controller itself rather than kernel managing them. What would be the consequences of such scenario? Good or Bad?
I searched online for this question but could not get information about this scenario. May be I'm not googling in the right keyword.
You insight into this will help me getting clearing my concepts.
Please answer.
Thanks.
Your question seems to propose the elimination of the "device driver" by "keeping" "control (of) the physical hardware ... inside the device controller". The premise for this seems to be:
kernel controls the physical hardware via device drivers.
That description of a device driver is something similar to what I've seem for end-user comprehension rather than from a developer's perspective. The end-user is aware of the device, and it is the device driver that takes that abstraction and can control that device down to the specific control bits of each device port.
But a device driver is responsible for mundane housekeeping tasks such as:
maintaining device status and availability;
configuring the device for operation;
managing data flow, setting-up/tearing-down data transfers, copying data between user space and kernel space;
handling interrupts and exceptions.
These tasks are integral to a device driver. These tasks cannot be transferred out of the purview of the kernel driver to a peripheral device.
Sometimes the device driver can only try to manage the device, rather than fully control it, for example, a NIC driver during a packet flood.
There is simply no possibility that you can eliminate a device driver no matter how much of "all this functionality is kept inside the device controller itself". And there would still be control directives/commands issued from the device driver to the peripheral.
The hardware device in question should be a computer peripheral device, not an autonomous robot device. The device should be designed to operate with a computer. Whatever interface there is between processor and device should be suitable for the task. If the peripheral is made more "intelligent", then perhaps the CPU can be unburdened and a high-level command interface can replace low-level sub-operation directives. But only "some" functionality can be transferred to the peripheral, not "all".

Resources