From 0ec65f741e4247a7a341a44b35d8d47f6c241702 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sat, 23 Mar 2024 00:45:43 -0700 Subject: [PATCH] WIP virtio-pci --- dev/bus/pci/bus_mgr/bus_mgr.cpp | 12 ++++++++++++ dev/bus/pci/bus_mgr/device.cpp | 29 ++++++++++++++++++++++++++++ dev/bus/pci/bus_mgr/device.h | 1 + dev/bus/pci/drivers/rules.mk | 4 +++- dev/bus/pci/include/dev/bus/pci.h | 3 +++ dev/virtio/rules.mk | 4 ++-- scripts/do-qemuarm | 32 ++++++++++++++++++++++++------- 7 files changed, 75 insertions(+), 10 deletions(-) diff --git a/dev/bus/pci/bus_mgr/bus_mgr.cpp b/dev/bus/pci/bus_mgr/bus_mgr.cpp index 9c9756afe6..75e46d8237 100644 --- a/dev/bus/pci/bus_mgr/bus_mgr.cpp +++ b/dev/bus/pci/bus_mgr/bus_mgr.cpp @@ -323,6 +323,18 @@ status_t pci_bus_mgr_allocate_irq(const pci_location_t loc, uint *irqbase) { return d->allocate_irq(irqbase); } +ssize_t pci_read_vendor_capability(const pci_location_t loc, size_t index, void *buf, size_t buflen) { + char str[14]; + LTRACEF("%s\n", pci_loc_string(loc, str)); + + device *d = lookup_device_by_loc(loc); + if (!d) { + return ERR_NOT_FOUND; + } + + return d->read_vendor_capability(index, buf, buflen); +} + void pci_dump_bar(const pci_bar_t *bar, int index) { if (bar->addr >= UINT32_MAX || bar->size >= UINT32_MAX) { printf("BAR %d: addr %-#16llx size %-#16zx io %d 64b %d pref %d\n", diff --git a/dev/bus/pci/bus_mgr/device.cpp b/dev/bus/pci/bus_mgr/device.cpp index ac071d6349..5611472f7d 100644 --- a/dev/bus/pci/bus_mgr/device.cpp +++ b/dev/bus/pci/bus_mgr/device.cpp @@ -133,6 +133,14 @@ void device::dump(size_t indent) { pci_dump_bar(bars_ + b, b); } } + + capability *cap; + list_for_every_entry(&capability_list_, cap, capability, node) { + for (size_t i = 0; i < indent + 2; i++) { + printf(" "); + } + printf("capability: offset %#x id %#x\n", cap->config_offset, cap->id); + } } status_t device::enable() { @@ -220,6 +228,27 @@ status_t device::probe_capabilities() { return NO_ERROR; } +ssize_t device::read_vendor_capability(size_t index, void *buf, size_t buflen) { + const capability *cap; + list_for_every_entry(&capability_list_, cap, capability, node) { + if (cap->id == 0x9) { // vendor specific + if (index == 0) { + uint8_t len; + pci_read_config_byte(loc(), cap->config_offset + 2, &len); + + const size_t readlen = MIN(len, buflen); + for (size_t i = 0; i < readlen; i++) { + pci_read_config_byte(loc(), cap->config_offset + i, static_cast(buf) + i); + } + return len; + } + index--; + } + } + + return ERR_NOT_FOUND; +} + status_t device::init_msi_capability(capability *cap) { LTRACE_ENTRY; diff --git a/dev/bus/pci/bus_mgr/device.h b/dev/bus/pci/bus_mgr/device.h index ae2b9f28c7..df2a6d5764 100644 --- a/dev/bus/pci/bus_mgr/device.h +++ b/dev/bus/pci/bus_mgr/device.h @@ -90,6 +90,7 @@ class device { uint8_t header_type() const { return config_.header_type & PCI_HEADER_TYPE_MASK; } status_t read_bars(pci_bar_t bar[6]); + ssize_t read_vendor_capability(size_t index, void *buf, size_t buflen); bool has_msi() const { return msi_cap_; } bool has_msix() const { return msix_cap_; } diff --git a/dev/bus/pci/drivers/rules.mk b/dev/bus/pci/drivers/rules.mk index 6a3ac16c57..ea86441d3f 100644 --- a/dev/bus/pci/drivers/rules.mk +++ b/dev/bus/pci/drivers/rules.mk @@ -1,5 +1,7 @@ # Fake module that just declares deps on all the PCI drivers in the system. # MODULES += dev/bus/pci - MODULES += dev/net/e1000 +MODULES += dev/virtio/block +MODULES += dev/virtio/net +MODULES += dev/virtio/gpu diff --git a/dev/bus/pci/include/dev/bus/pci.h b/dev/bus/pci/include/dev/bus/pci.h index 10e90d197e..e74fc70762 100644 --- a/dev/bus/pci/include/dev/bus/pci.h +++ b/dev/bus/pci/include/dev/bus/pci.h @@ -119,6 +119,9 @@ status_t pci_bus_mgr_allocate_msi(const pci_location_t loc, size_t num_requested // allocate a regular irq for this device and return it in irqbase status_t pci_bus_mgr_allocate_irq(const pci_location_t loc, uint *irqbase); +// XXX sort this nicely +ssize_t pci_read_vendor_capability(const pci_location_t loc, size_t index, void *buf, size_t buflen); + // return a pointer to a formatted string const char *pci_loc_string(pci_location_t loc, char out_str[14]); diff --git a/dev/virtio/rules.mk b/dev/virtio/rules.mk index 22c8c0b1b2..0570ed0405 100644 --- a/dev/virtio/rules.mk +++ b/dev/virtio/rules.mk @@ -2,7 +2,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) -MODULE_SRCS += \ - $(LOCAL_DIR)/virtio.c +MODULE_SRCS += $(LOCAL_DIR)/virtio.c +MODULE_SRCS += $(LOCAL_DIR)/virtio_pci.c include make/module.mk diff --git a/scripts/do-qemuarm b/scripts/do-qemuarm index d5ea9a1dbb..5eac08d4f7 100755 --- a/scripts/do-qemuarm +++ b/scripts/do-qemuarm @@ -4,6 +4,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" function HELP { echo "help:" + echo "-p : override LK project" echo "-6 : 64bit arm" echo "-3 : cortex-m3 based platform" echo "-v : boot kernel at EL2" @@ -17,6 +18,7 @@ function HELP { echo "-n : a virtio network device" echo "-t : a virtio tap network device" echo "-g : a virtio display" + echo "-P : PCI based virtio devices" echo echo "-h for help" echo "all arguments after -- are passed to qemu directly" @@ -33,12 +35,13 @@ DO_CORTEX_M3=0 DO_DISPLAY=0 DO_CMPCTMALLOC=0 DO_MINIHEAP=0 +DO_PCI_VIRTIO=0 SMP=1 MEMSIZE=512 SUDO="" PROJECT="" -while getopts cd:ghm:Mnt36vp:s: FLAG; do +while getopts cd:ghm:Mnt36vp:Ps: FLAG; do case $FLAG in c) DO_CMPCTMALLOC=1;; d) DO_DISK=1; DISK_IMAGE=$OPTARG;; @@ -52,6 +55,7 @@ while getopts cd:ghm:Mnt36vp:s: FLAG; do m) MEMSIZE=$OPTARG;; s) SMP=$OPTARG;; p) PROJECT=$OPTARG;; + P) DO_PCI_VIRTIO=1;; h) HELP;; \?) echo unrecognized option @@ -90,14 +94,28 @@ fi ARGS=" -cpu $CPU -m $MEMSIZE -smp $SMP -machine $MACHINE -kernel build-${PROJECT}/lk.elf" +if (( $DO_PCI_VIRTIO )); then + VIRTIO_BLOCK_DEVICE="virtio-blk-pci" + VIRTIO_NET_DEVICE="virtio-net-pci" + VIRTIO_GPU_DEVICE="virtio-gpu-pci" + VIRTIO_KEYBOARD_DEVICE="virtio-keyboard-pci" + VIRTIO_MOUSE_DEVICE="virtio-mouse-pci" +else + VIRTIO_BLOCK_DEVICE="virtio-blk-device" + VIRTIO_NET_DEVICE="virtio-net-device" + VIRTIO_GPU_DEVICE="virtio-gpu-device" + VIRTIO_KEYBOARD_DEVICE="virtio-keyboard-device" + VIRTIO_MOUSE_DEVICE="virtio-mouse-device" +fi + if (( $DO_DISK )); then ARGS+=" -drive if=none,file=${DISK_IMAGE},id=blk,format=raw" - ARGS+=" -device virtio-blk-device,drive=blk" + ARGS+=" -device ${VIRTIO_BLOCK_DEVICE},drive=blk" fi if (( $DO_NET )); then ARGS+=" -netdev user,id=vmnic,hostname=qemu " - ARGS+=" -device virtio-net-device,netdev=vmnic" + ARGS+=" -device ${VIRTIO_NET_DEVICE},netdev=vmnic" elif (( $DO_NET_TAP )); then # quick note to enable tap interface # IFNAME=qemu0 @@ -106,7 +124,7 @@ elif (( $DO_NET_TAP )); then # sudo ifconfig ${IFNAME} up # sudo ip link set ${IFNAME} master ${BRIDGE} ARGS+=" -netdev tap,id=vmnic,ifname=qemu0,script=no,downscript=no" - ARGS+=" -device virtio-net-device,netdev=vmnic" + ARGS+=" -device ${VIRTIO_NET_DEVICE},netdev=vmnic" #SUDO="sudo " else NO_NET_ARGS=" -net none" @@ -114,9 +132,9 @@ else fi if (( $DO_DISPLAY )); then - ARGS+=" -device virtio-gpu-device -serial stdio" - ARGS+=" -device virtio-keyboard-device" - ARGS+=" -device virtio-mouse-device" + ARGS+=" -device ${VIRTIO_GPU_DEVICE} -serial stdio" + ARGS+=" -device ${VIRTIO_KEYBOARD_DEVICE}" + ARGS+=" -device ${VIRTIO_MOUSE_DEVICE}" else ARGS+=" -nographic" fi