From 83411a05971932051b541ca3001f7db56d3ec5ff Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Sat, 5 Aug 2017 12:32:24 +0100 Subject: [PATCH] sketch uio --- kernel_config_fragment | 27 ++++++++++++++++++ kernel_module/pci.c | 7 +++++ kernel_module/user/pagemap_dump.c | 1 + kernel_module/user/uio_read.c | 46 ++++++++++++++++++++++++++++++ rootfs_overlay/character_device.sh | 2 +- rootfs_overlay/mknoddev.sh | 2 +- rootfs_overlay/pci.sh | 2 +- 7 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 kernel_module/user/uio_read.c diff --git a/kernel_config_fragment b/kernel_config_fragment index 7dde26c..41f5db1 100644 --- a/kernel_config_fragment +++ b/kernel_config_fragment @@ -135,3 +135,30 @@ CONFIG_PCI=y # Like CONFIG_X86_PTDUMP for ARM. CONFIG_ARM64_PTDUMP=y + +## UIO + +# Userspace drivers. +# +# Superseded by the more featureful VFIO. +# +# Documentation/DocBook/uio-howto.tmpl +# +# UIO interface in a nutshell: +# +# - blocking read / poll: waits until interrupts +# - write: call irqcontrol callback. Default: 0 or 1 to enable / disable interrupts. +# - mmap: access device memory + +# All other UIO depend on this module. +CONFIG_UIO=m + +# Generic platform devices. +# https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/ +CONFIG_UIO_DMEM_GENIRQ=m +CONFIG_UIO_PDRV_GENIRQ=m + +# https://github.com/rumpkernel/wiki/wiki/Howto:-Accessing-PCI-devices-from-userspace +# /sys/class/uio/ +# /sys/class/uio/uio0 +CONFIG_UIO_PCI_GENERIC=m diff --git a/kernel_module/pci.c b/kernel_module/pci.c index 92ffeb0..f10990b 100644 --- a/kernel_module/pci.c +++ b/kernel_module/pci.c @@ -50,6 +50,12 @@ Often abbreviated to BDF. - device: maps to one slot - function: https://stackoverflow.com/questions/19223394/what-is-the-function-number-in-pci/44735372#44735372 +Sometimes a fourth number is also added, e.g.: + + 0000:00:04.0 + +TODO is that the domain? + Class: pure magic: https://www-s.acm.illinois.edu/sigops/2007/roll_your_own/7.c.1.html TODO: does it have any side effects? Set in the edu device at: @@ -279,6 +285,7 @@ static int pci_probe(struct pci_dev *dev, const struct pci_device_id *id) * - https://stackoverflow.com/questions/17913679/how-to-instantiate-and-use-a-dma-driver-linux-module * - https://stackoverflow.com/questions/5539375/linux-kernel-device-driver-to-dma-from-a-device-into-user-space-memory * - RPI userland /dev/mem https://github.com/Wallacoloo/Raspberry-Pi-DMA-Example + * - https://stackoverflow.com/questions/34188369/easiest-way-to-use-dma-in-linux */ { dma_addr_t dma_handle_from, dma_handle_to; diff --git a/kernel_module/user/pagemap_dump.c b/kernel_module/user/pagemap_dump.c index 144a8b3..bfa7cb1 100644 --- a/kernel_module/user/pagemap_dump.c +++ b/kernel_module/user/pagemap_dump.c @@ -5,6 +5,7 @@ Adapted from: https://github.com/dwks/pagemap/blob/8a25747bc79d6080c8b94eac80807 - https://stackoverflow.com/questions/17021214/how-to-decode-proc-pid-pagemap-entries-in-linux/45126141#45126141 - https://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li +- https://stackoverflow.com/questions/6284810/proc-pid-pagemaps-and-proc-pid-maps-linux/45500208#45500208 Dump the page map of a given process PID. diff --git a/kernel_module/user/uio_read.c b/kernel_module/user/uio_read.c new file mode 100644 index 0000000..4e8a414 --- /dev/null +++ b/kernel_module/user/uio_read.c @@ -0,0 +1,46 @@ +/* +Adapted from: https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/ + + modprobe uio_pdrv_genirq + +TODO get working. + +Handle interrupts from userland and print a message to stdout. +*/ + +#define _XOPEN_SOURCE 700 +#include /* open */ +#include +#include +#include +#include +#include +#include /* write */ + +int main(int argc, char **argv) +{ + + char *dev; + if (argc < 2) { + } + int fd = open("/dev/uio", O_RDWR); + if (fd < 0) { + perror("open"); + exit(EXIT_FAILURE); + } + while (1) { + uint32_t info = 1; + size_t nb = write(fd, &info, sizeof(info)); + if (nb < sizeof(info)) { + perror("write"); + close(fd); + exit(EXIT_FAILURE); + } + nb = read(fd, &info, sizeof(info)); + if (nb == sizeof(info)) { + printf("Interrupt #%u\n", info); + } + } + close(fd); + exit(EXIT_SUCCESS); +} diff --git a/rootfs_overlay/character_device.sh b/rootfs_overlay/character_device.sh index cb693c9..e57dc57 100755 --- a/rootfs_overlay/character_device.sh +++ b/rootfs_overlay/character_device.sh @@ -1,6 +1,6 @@ #!/bin/sh insmod /character_device.ko -/mknoddev.sh character_device +/mknoddev.sh lkmc_character_device cat /dev/lkmc_character_device # => abcd rm /dev/lkmc_character_device diff --git a/rootfs_overlay/mknoddev.sh b/rootfs_overlay/mknoddev.sh index 65d3899..87a7848 100755 --- a/rootfs_overlay/mknoddev.sh +++ b/rootfs_overlay/mknoddev.sh @@ -1,4 +1,4 @@ #!/bin/sh -dev="lkmc_$1" +dev="$1" major="$(grep "$dev" /proc/devices | cut -d ' ' -f 1)" mknod "/dev/$dev" c "$major" 0 diff --git a/rootfs_overlay/pci.sh b/rootfs_overlay/pci.sh index e0333a8..321ba5e 100755 --- a/rootfs_overlay/pci.sh +++ b/rootfs_overlay/pci.sh @@ -11,7 +11,7 @@ cat /proc/interrupts # Setup. insmod /pci.ko -/mknoddev.sh pci +/mknoddev.sh lkmc_pci # Shows that this module owns the PCI device. lspci -k