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.
arch/aarch64/arch-dtb.cc | 46 ++++++++++++++++++++++++++++++++++++++
arch/aarch64/arch-dtb.hh | 7 ++++++
arch/aarch64/arch-setup.cc | 10 +++++++--
drivers/virtio-mmio.cc | 16 ++++++++++++-
drivers/virtio-mmio.hh | 5 +++++
5 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/arch/aarch64/arch-dtb.cc b/arch/aarch64/arch-dtb.cc
index a0ec2acf..462d2fb9 100644
--- 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
index a52c5160..7f2eb18d 100644
--- 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
index 90eff282..351ac0da 100644
--- 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
index b2f84d09..43db8130 100644
--- 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
index 27632971..98f8ad5b 100644
--- 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);
}
--
2.26.2