From: Waldemar Kozaczuk <jwkozac...@gmail.com> Committer: Waldemar Kozaczuk <jwkozac...@gmail.com> Branch: master
aarch64: parse and activate virtio mmio devices The aarch64 version of firecracker (unlike the x64 one) passes the configuration information of virtio devices using dtb. This patch adds necessary logic to parse this information from dtb and activate the relevant devices. This patch effectively enables support of virtio net and block devices on aarch64 version of firecracker. Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com> --- diff --git a/arch/aarch64/arch-dtb.cc b/arch/aarch64/arch-dtb.cc --- a/arch/aarch64/arch-dtb.cc +++ b/arch/aarch64/arch-dtb.cc @@ -16,6 +16,7 @@ #include <osv/mempool.hh> #include <osv/commands.hh> #include <osv/elf.hh> +#include "drivers/virtio-mmio.hh" #define DTB_INTERRUPT_CELLS 3 @@ -219,6 +220,49 @@ u64 dtb_get_mmio_serial_console(int *irqid) return address; } +#define VIRTIO_MMIO_DEV_COMPAT "virtio,mmio" +#define DTB_MAX_VIRTIO_MMIO_DEV_COUNT 8 +static virtio::mmio_device_info dtb_dtb_virtio_mmio_devices_infos[DTB_MAX_VIRTIO_MMIO_DEV_COUNT]; +static unsigned int dtb_virtio_mmio_dev_count; +static void dtb_parse_mmio_virtio_devices() +{ + int node; + struct dtb_int_spec int_spec[1]; + + if (!dtb) + return; + + dtb_virtio_mmio_dev_count = 0; + node = fdt_node_offset_by_compatible(dtb, -1, VIRTIO_MMIO_DEV_COMPAT); + while (node != -FDT_ERR_NOTFOUND && dtb_virtio_mmio_dev_count < DTB_MAX_VIRTIO_MMIO_DEV_COUNT) { + int value_size; + int required = 2 * sizeof(u64); // We expect two fields - address and length, each u64 size + u64 *reg = (u64 *)fdt_getprop(dtb, node, "reg", &value_size); + if (!reg || value_size < required) { + break; + } + + dtb_dtb_virtio_mmio_devices_infos[dtb_virtio_mmio_dev_count]._address = fdt64_to_cpu(reg[0]); + dtb_dtb_virtio_mmio_devices_infos[dtb_virtio_mmio_dev_count]._size = fdt64_to_cpu(reg[1]); + + if( !dtb_get_int_spec(node, int_spec, 1)) { + break; + }; + + dtb_dtb_virtio_mmio_devices_infos[dtb_virtio_mmio_dev_count++]._irq_no = int_spec[0].irq_id; + + // Move to the next node + node = fdt_node_offset_by_compatible(dtb, node, VIRTIO_MMIO_DEV_COMPAT); + } +} + +void dtb_collect_parsed_mmio_virtio_devices() +{ + for( unsigned int idx = 0; idx < dtb_virtio_mmio_dev_count; idx++) { + virtio::add_mmio_device_configuration(dtb_dtb_virtio_mmio_devices_infos[idx]); + } +} + /* this gets the virtual timer irq, we are not interested * about the other timers. */ @@ -653,6 +697,8 @@ void __attribute__((constructor(init_prio::dtb))) dtb_setup() abort("dtb_setup: failed to parse pci_irq_map.\n"); } + dtb_parse_mmio_virtio_devices(); + register u64 edata; asm volatile ("adrp %0, .edata" : "=r"(edata)); diff --git a/arch/aarch64/arch-dtb.hh b/arch/aarch64/arch-dtb.hh --- a/arch/aarch64/arch-dtb.hh +++ b/arch/aarch64/arch-dtb.hh @@ -57,6 +57,13 @@ u64 dtb_get_uart(int *irqid); */ u64 dtb_get_mmio_serial_console(int *irqid); +/* dtb_collect_parsed_mmio_virtio_devices() + * + * collect and add any parsed mmio devices + * to be recognized and potentially recognized + */ +void dtb_collect_parsed_mmio_virtio_devices(); + /* int gdb_get_timer_irq() * * returns the irqid of the virtual timer from the dtb, diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc --- a/arch/aarch64/arch-setup.cc +++ b/arch/aarch64/arch-setup.cc @@ -118,6 +118,8 @@ void arch_setup_free_memory() console::mmio_isa_serial_console::clean_cmdline(cmdline); osv::parse_cmdline(cmdline); + dtb_collect_parsed_mmio_virtio_devices(); + mmu::switch_to_runtime_page_tables(); console::mmio_isa_serial_console::memory_map(); @@ -147,6 +149,7 @@ void arch_init_premain() #include "drivers/virtio-rng.hh" #include "drivers/virtio-blk.hh" #include "drivers/virtio-net.hh" +#include "drivers/virtio-mmio.hh" void arch_init_drivers() { @@ -168,10 +171,13 @@ void arch_init_drivers() // Enumerate PCI devices size_t pci_cfg_len; if (pci::get_pci_cfg(&pci_cfg_len)) { - pci::pci_device_enumeration(); - boot_time.event("pci enumerated"); + pci::pci_device_enumeration(); + boot_time.event("pci enumerated"); } + // Register any parsed virtio-mmio devices + virtio::register_mmio_devices(device_manager::instance()); + // Initialize all drivers hw::driver_manager* drvman = hw::driver_manager::instance(); drvman->register_driver(virtio::rng::probe); diff --git a/drivers/virtio-mmio.cc b/drivers/virtio-mmio.cc --- a/drivers/virtio-mmio.cc +++ b/drivers/virtio-mmio.cc @@ -140,6 +140,7 @@ bool mmio_device::parse_config() return true; } +#ifndef AARCH64_PORT_STUB #define VIRTIO_MMIO_DEVICE_CMDLINE_PREFIX "virtio_mmio.device=" static mmio_device_info* parse_mmio_device_info(char *cmdline) { // @@ -190,18 +191,31 @@ static mmio_device_info* parse_mmio_device_info(char *cmdline) return new mmio_device_info(address, size, irq); } +#endif static std::vector<struct mmio_device_info> *mmio_device_info_entries = 0; +#ifndef AARCH64_PORT_STUB void parse_mmio_device_configuration(char *cmdline) { // // We are assuming the mmio devices information is appended to the // command line (at least it is the case with the firecracker) so // once we parse those we strip it away so only plain OSv command line is left - mmio_device_info_entries = new std::vector<struct mmio_device_info>(); + if (!mmio_device_info_entries) { + mmio_device_info_entries = new std::vector<struct mmio_device_info>(); + } for( auto device_info = parse_mmio_device_info(cmdline); device_info != nullptr; device_info = parse_mmio_device_info(cmdline)) mmio_device_info_entries->push_back(*device_info); } +#else +void add_mmio_device_configuration(mmio_device_info device_info) +{ + if (!mmio_device_info_entries) { + mmio_device_info_entries = new std::vector<struct mmio_device_info>(); + } + mmio_device_info_entries->push_back(device_info); +} +#endif void register_mmio_devices(hw::device_manager *dev_manager) { diff --git a/drivers/virtio-mmio.hh b/drivers/virtio-mmio.hh --- a/drivers/virtio-mmio.hh +++ b/drivers/virtio-mmio.hh @@ -92,6 +92,7 @@ namespace virtio { struct mmio_device_info { mmio_device_info(u64 address, u64 size, unsigned int irq) : _address(address), _size(size), _irq_no(irq) {} + mmio_device_info() : mmio_device_info(0, 0, 0) {} u64 _address; u64 _size; @@ -151,7 +152,11 @@ private: #endif }; +#ifndef AARCH64_PORT_STUB void parse_mmio_device_configuration(char *cmdline); +#else +void add_mmio_device_configuration(mmio_device_info device_info); +#endif void register_mmio_devices(hw::device_manager *dev_manager); } -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/000000000000f2f05b05aaa95b2e%40google.com.