[[!template id=project title="Userland PCI drivers (350h)" contact=""" [tech-kern](mailto:tech-kern@NetBSD.org) """ mentors=""" [Taylor R Campbell](mailto:riastradh@NetBSD.org) """ category="kernel" difficulty="medium" duration="350h" description=""" When developing device drivers inside the kernel, mistakes will usually cause the whole kernel to crash unrecoverably and require a reboot. But device drivers need not run inside the kernel: with [rump](https://github.com/rumpkernel/wiki/wiki/), device driver code can be run as a process inside userland. However, userland code has only limited access to the hardware registers needed to control devices: currently, NetBSD supports only USB device drivers in userland, via [[!template id=man name="ugen" section="4"]]. NetBSD should additionally support developing PCI drivers in userland with rump -- at least one driver, [[!template id=man name="iwm" section="4"]], was developed using rump, but on a Linux host! There are several milestones to this project: 1. Implement enough of the [[!template id=man name="bus_space" section="9"]] and `pci_mapreg()` ([[!template id=man name="pci" section="9"]]) APIs to map device registers from PCI BARs, using a [[!template id=man name="pci" section="4"]] device (/dev/pciN). A first approximation can be done using [[!template id=man name="pci" section="3"]] and simply mmapping from [[!template id=man name="mem" section="4"]] (/dev/mem), but it would be better to cooperate with the kernel so that the kernel can limit the user to mapping ranges listed in PCI BARs without granting privileges to read all physical pages in the system. Cooperation with the kernel will also be necessary to implement port I/O instead of memory-mapped I/O, without raising the I/O privilege level of the userland process, on x86 systems. 2. Expose PCI interrupts as events that can be read from a [[!template id=man name="pci" section="4"]] (/dev/pciN) device instance, and use that to implement the [[!template id=man name="pci_intr" section="9"]] API in userland. For many devices, this may require a small device-specific shim in the kernel to acknowledge interrupts while they are masked -- but that is a small price to pay for rapidly iterating driver development in userland. 3. Devise a scheme for userland allocate and map memory for DMA in order to implement [[!template id=man name="bus_dma" section="9"]]. Again, a first approximation can be done by simply wiring pages with [[!template id=man name="mlock" section="3"]] and then asking the kernel for a virtual-to-physical translation to program hardware DMA registers. However, this will not work on any machines with an IOMMU, which would help to prevent certain classes of catastrophic memory corruption in the case of a buggy driver. Cooperation with the kernel, and maintaining a kernel-side mirror of each `bus_dmamem` allocation and each `bus_dmamap`. Inspiration may be found in the Linux [uio](https://www.kernel.org/doc/htmldocs/uio-howto/about.html) framework. This project is not necessarily PCI-specific -- ideally, most of the code to manage [[!template id=man name="bus_space" section="9"]], [[!template id=man name="bus_dma" section="9"]], and interrupt event delivery should be generic. The focus is PCI because it is widely used and would be applicable to many drivers and devices for which someone has yet to write drivers. """ ]] [[!tag gsoc]] [[!tag gsoc350h]]