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.

Reply via email to