stratovirt/0013-machine-micro_vm-use-fdt-API-of-mod-fdt-instead-of-d.patch

454 lines
20 KiB
Diff
Raw Normal View History

From 999b6194eff54881f3ce4181f2355113fc72435b Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Wed, 23 Jun 2021 15:20:54 +0800
Subject: [PATCH 3/5] machine/micro_vm: use fdt API of mod fdt instead of
device_tree
Use fdt API provided by mod fdt, instead of mod device_tree
which is a wrapper around libfdt.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
---
micro_vm/src/lib.rs | 291 ++++++++++++++++++++++----------------------
1 file changed, 143 insertions(+), 148 deletions(-)
diff --git a/micro_vm/src/lib.rs b/micro_vm/src/lib.rs
index 7188f21..dd6cf97 100644
--- a/micro_vm/src/lib.rs
+++ b/micro_vm/src/lib.rs
@@ -111,7 +111,7 @@ use sysbus::{SysBusDevType, SysRes};
#[cfg(target_arch = "aarch64")]
use util::device_tree;
#[cfg(target_arch = "aarch64")]
-use util::device_tree::CompileFDT;
+use util::fdt::{self, CompileFDT, FdtBuilder};
use util::loop_context::{
EventLoopManager, EventNotifier, EventNotifierHelper, NotifierCallback, NotifierOperation,
};
@@ -628,12 +628,13 @@ impl LightMachine {
drop(boot_source);
#[cfg(target_arch = "aarch64")]
{
- let mut fdt = vec![0; device_tree::FDT_MAX_SIZE as usize];
- vm.generate_fdt_node(&mut fdt)?;
+ let mut fdt_helper = FdtBuilder::new();
+ vm.generate_fdt_node(&mut fdt_helper)?;
+ let fdt_vec = fdt_helper.finish()?;
vm.sys_mem.write(
- &mut fdt.as_slice(),
+ &mut fdt_vec.as_slice(),
GuestAddress(boot_config.fdt_addr as u64),
- fdt.len() as u64,
+ fdt_vec.len() as u64,
)?;
}
vm.register_power_event()?;
@@ -1477,23 +1478,23 @@ impl EventLoopManager for LightMachine {
// * `dev_info` - Device resource info of serial device.
// * `fdt` - Flatted device-tree blob where serial node will be filled into.
#[cfg(target_arch = "aarch64")]
-fn generate_serial_device_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors::Result<()> {
- let node = format!("/uart@{:x}", res.region_base);
- device_tree::add_sub_node(fdt, &node)?;
- device_tree::set_property_string(fdt, &node, "compatible", "ns16550a")?;
- device_tree::set_property_string(fdt, &node, "clock-names", "apb_pclk")?;
- device_tree::set_property_u32(fdt, &node, "clocks", device_tree::CLK_PHANDLE)?;
- device_tree::set_property_array_u64(fdt, &node, "reg", &[res.region_base, res.region_size])?;
- device_tree::set_property_array_u32(
- fdt,
- &node,
+fn generate_serial_device_node(fdt: &mut FdtBuilder, res: &SysRes) -> util::errors::Result<()> {
+ let node = format!("uart@{:x}", res.region_base);
+ let serial_node_dep = fdt.begin_node(&node)?;
+ fdt.set_property_string("compatible", "ns16550a")?;
+ fdt.set_property_string("clock-names", "apb_pclk")?;
+ fdt.set_property_u32("clocks", fdt::CLK_PHANDLE)?;
+ fdt.set_property_array_u64("reg", &[res.region_base, res.region_size])?;
+ fdt.set_property_array_u32(
"interrupts",
&[
- device_tree::GIC_FDT_IRQ_TYPE_SPI,
+ fdt::GIC_FDT_IRQ_TYPE_SPI,
res.irq as u32,
- device_tree::IRQ_TYPE_EDGE_RISING,
+ fdt::IRQ_TYPE_EDGE_RISING,
],
)?;
+ fdt.end_node(serial_node_dep)?;
+
Ok(())
}
@@ -1504,23 +1505,23 @@ fn generate_serial_device_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors:
// * `dev_info` - Device resource info of RTC device.
// * `fdt` - Flatted device-tree blob where RTC node will be filled into.
#[cfg(target_arch = "aarch64")]
-fn generate_rtc_device_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors::Result<()> {
- let node = format!("/pl031@{:x}", res.region_base);
- device_tree::add_sub_node(fdt, &node)?;
- device_tree::set_property_string(fdt, &node, "compatible", "arm,pl031\0arm,primecell\0")?;
- device_tree::set_property_string(fdt, &node, "clock-names", "apb_pclk")?;
- device_tree::set_property_u32(fdt, &node, "clocks", device_tree::CLK_PHANDLE)?;
- device_tree::set_property_array_u64(fdt, &node, "reg", &[res.region_base, res.region_size])?;
- device_tree::set_property_array_u32(
- fdt,
- &node,
+fn generate_rtc_device_node(fdt: &mut FdtBuilder, res: &SysRes) -> util::errors::Result<()> {
+ let node = format!("pl031@{:x}", res.region_base);
+ let rtc_node_dep = fdt.begin_node(&node)?;
+ fdt.set_property_string("compatible", "arm,pl031\0arm,primecell\0")?;
+ fdt.set_property_string("clock-names", "apb_pclk")?;
+ fdt.set_property_u32("clocks", fdt::CLK_PHANDLE)?;
+ fdt.set_property_array_u64("reg", &[res.region_base, res.region_size])?;
+ fdt.set_property_array_u32(
"interrupts",
&[
- device_tree::GIC_FDT_IRQ_TYPE_SPI,
+ fdt::GIC_FDT_IRQ_TYPE_SPI,
res.irq as u32,
- device_tree::IRQ_TYPE_LEVEL_HIGH,
+ fdt::IRQ_TYPE_LEVEL_HIGH,
],
)?;
+ fdt.end_node(rtc_node_dep)?;
+
Ok(())
}
@@ -1531,22 +1532,21 @@ fn generate_rtc_device_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors::Re
// * `dev_info` - Device resource info of Virtio-Mmio device.
// * `fdt` - Flatted device-tree blob where node will be filled into.
#[cfg(target_arch = "aarch64")]
-fn generate_virtio_devices_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors::Result<()> {
- let node = format!("/virtio_mmio@{:x}", res.region_base);
- device_tree::add_sub_node(fdt, &node)?;
- device_tree::set_property_string(fdt, &node, "compatible", "virtio,mmio")?;
- device_tree::set_property_u32(fdt, &node, "interrupt-parent", device_tree::GIC_PHANDLE)?;
- device_tree::set_property_array_u64(fdt, &node, "reg", &[res.region_base, res.region_size])?;
- device_tree::set_property_array_u32(
- fdt,
- &node,
+fn generate_virtio_devices_node(fdt: &mut FdtBuilder, res: &SysRes) -> util::errors::Result<()> {
+ let node = format!("virtio_mmio@{:x}", res.region_base);
+ let virtio_node_dep = fdt.begin_node(&node)?;
+ fdt.set_property_string("compatible", "virtio,mmio")?;
+ fdt.set_property_u32("interrupt-parent", fdt::GIC_PHANDLE)?;
+ fdt.set_property_array_u64("reg", &[res.region_base, res.region_size])?;
+ fdt.set_property_array_u32(
"interrupts",
&[
- device_tree::GIC_FDT_IRQ_TYPE_SPI,
+ fdt::GIC_FDT_IRQ_TYPE_SPI,
res.irq as u32,
- device_tree::IRQ_TYPE_EDGE_RISING,
+ fdt::IRQ_TYPE_EDGE_RISING,
],
)?;
+ fdt.end_node(virtio_node_dep)?;
Ok(())
}
@@ -1555,73 +1555,72 @@ fn generate_virtio_devices_node(fdt: &mut Vec<u8>, res: &SysRes) -> util::errors
#[cfg(target_arch = "aarch64")]
trait CompileFDTHelper {
/// Function that helps to generate cpu nodes.
- fn generate_cpu_nodes(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()>;
+ fn generate_cpu_nodes(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()>;
/// Function that helps to generate memory nodes.
- fn generate_memory_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()>;
+ fn generate_memory_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()>;
/// Function that helps to generate Virtio-mmio devices' nodes.
- fn generate_devices_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()>;
+ fn generate_devices_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()>;
/// Function that helps to generate the chosen node.
- fn generate_chosen_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()>;
+ fn generate_chosen_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()>;
}
#[cfg(target_arch = "aarch64")]
impl CompileFDTHelper for LightMachine {
- fn generate_cpu_nodes(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()> {
- let node = "/cpus";
+ fn generate_cpu_nodes(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()> {
+ let node = "cpus";
- device_tree::add_sub_node(fdt, node)?;
- device_tree::set_property_u32(fdt, node, "#address-cells", 0x02)?;
- device_tree::set_property_u32(fdt, node, "#size-cells", 0x0)?;
+ let cpus_node_dep = fdt.begin_node(node)?;
+ fdt.set_property_u32("#address-cells", 0x02)?;
+ fdt.set_property_u32("#size-cells", 0x0)?;
// Generate CPU topology
if self.cpu_topo.max_cpus > 0 && self.cpu_topo.max_cpus % 8 == 0 {
- device_tree::add_sub_node(fdt, "/cpus/cpu-map")?;
+ let cpu_map_node_dep = fdt.begin_node("cpu-map")?;
let sockets = self.cpu_topo.max_cpus / 8;
for cluster in 0..u32::from(sockets) {
- let clster = format!("/cpus/cpu-map/cluster{}", cluster);
- device_tree::add_sub_node(fdt, &clster)?;
+ let clster = format!("cluster{}", cluster);
+ let cluster_node_dep = fdt.begin_node(&clster)?;
for i in 0..2_u32 {
- let sub_cluster = format!("{}/cluster{}", clster, i);
- device_tree::add_sub_node(fdt, &sub_cluster)?;
-
- let core0 = format!("{}/core0", sub_cluster);
- device_tree::add_sub_node(fdt, &core0)?;
- let thread0 = format!("{}/thread0", core0);
- device_tree::add_sub_node(fdt, &thread0)?;
- device_tree::set_property_u32(fdt, &thread0, "cpu", cluster * 8 + i * 4 + 10)?;
-
- let thread1 = format!("{}/thread1", core0);
- device_tree::add_sub_node(fdt, &thread1)?;
- device_tree::set_property_u32(
- fdt,
- &thread1,
- "cpu",
- cluster * 8 + i * 4 + 10 + 1,
- )?;
-
- let core1 = format!("{}/core1", sub_cluster);
- device_tree::add_sub_node(fdt, &core1)?;
- let thread0 = format!("{}/thread0", core1);
- device_tree::add_sub_node(fdt, &thread0)?;
- device_tree::set_property_u32(
- fdt,
- &thread0,
- "cpu",
- cluster * 8 + i * 4 + 10 + 2,
- )?;
-
- let thread1 = format!("{}/thread1", core1);
- device_tree::add_sub_node(fdt, &thread1)?;
- device_tree::set_property_u32(
- fdt,
- &thread1,
- "cpu",
- cluster * 8 + i * 4 + 10 + 3,
- )?;
+ let sub_cluster = format!("cluster{}", i);
+ let sub_cluster_node_dep = fdt.begin_node(&sub_cluster)?;
+
+ let core0 = "core0".to_string();
+ let core0_node_dep = fdt.begin_node(&core0)?;
+
+ let thread0 = "thread0".to_string();
+ let thread0_node_dep = fdt.begin_node(&thread0)?;
+ fdt.set_property_u32("cpu", cluster * 8 + i * 4 + 10)?;
+ fdt.end_node(thread0_node_dep)?;
+
+ let thread1 = "thread1".to_string();
+ let thread1_node_dep = fdt.begin_node(&thread1)?;
+ fdt.set_property_u32("cpu", cluster * 8 + i * 4 + 10 + 1)?;
+ fdt.end_node(thread1_node_dep)?;
+
+ fdt.end_node(core0_node_dep)?;
+
+ let core1 = "core1".to_string();
+ let core1_node_dep = fdt.begin_node(&core1)?;
+
+ let thread0 = "thread0".to_string();
+ let thread0_node_dep = fdt.begin_node(&thread0)?;
+ fdt.set_property_u32("cpu", cluster * 8 + i * 4 + 10 + 2)?;
+ fdt.end_node(thread0_node_dep)?;
+
+ let thread1 = "thread1".to_string();
+ let thread1_node_dep = fdt.begin_node(&thread1)?;
+ fdt.set_property_u32("cpu", cluster * 8 + i * 4 + 10 + 3)?;
+ fdt.end_node(thread1_node_dep)?;
+
+ fdt.end_node(core1_node_dep)?;
+
+ fdt.end_node(sub_cluster_node_dep)?;
}
+ fdt.end_node(cluster_node_dep)?;
}
+ fdt.end_node(cpu_map_node_dep)?;
}
let cpu_list = self.cpus.lock().unwrap();
@@ -1632,68 +1631,69 @@ impl CompileFDTHelper for LightMachine {
.unwrap()
.get_mpidr(cpu_list[cpu_index as usize].fd());
- let node = format!("/cpus/cpu@{:x}", mpidr);
- device_tree::add_sub_node(fdt, &node)?;
- device_tree::set_property_u32(
- fdt,
- &node,
- "phandle",
- u32::from(cpu_index) + device_tree::CPU_PHANDLE_START,
- )?;
- device_tree::set_property_string(fdt, &node, "device_type", "cpu")?;
- device_tree::set_property_string(fdt, &node, "compatible", "arm,arm-v8")?;
+ let node = format!("cpu@{:x}", mpidr);
+ let mpidr_node_dep = fdt.begin_node(&node)?;
+ fdt.set_property_u32("phandle", u32::from(cpu_index) + fdt::CPU_PHANDLE_START)?;
+ fdt.set_property_string("device_type", "cpu")?;
+ fdt.set_property_string("compatible", "arm,arm-v8")?;
if self.cpu_topo.max_cpus > 1 {
- device_tree::set_property_string(fdt, &node, "enable-method", "psci")?;
+ fdt.set_property_string("enable-method", "psci")?;
}
- device_tree::set_property_u64(fdt, &node, "reg", mpidr & 0x007F_FFFF)?;
+ fdt.set_property_u64("reg", mpidr & 0x007F_FFFF)?;
+ fdt.end_node(mpidr_node_dep)?;
}
+ fdt.end_node(cpus_node_dep)?;
+
Ok(())
}
- fn generate_memory_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()> {
+ fn generate_memory_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()> {
let mem_base = MEM_LAYOUT[LayoutEntryType::Mem as usize].0;
let mem_size = self.sys_mem.memory_end_address().raw_value()
- MEM_LAYOUT[LayoutEntryType::Mem as usize].0;
- let node = "/memory";
- device_tree::add_sub_node(fdt, node)?;
- device_tree::set_property_string(fdt, node, "device_type", "memory")?;
- device_tree::set_property_array_u64(fdt, node, "reg", &[mem_base, mem_size as u64])?;
+ let node = "memory";
+ let memory_node_dep = fdt.begin_node(node)?;
+ fdt.set_property_string("device_type", "memory")?;
+ fdt.set_property_array_u64("reg", &[mem_base, mem_size as u64])?;
+ fdt.end_node(memory_node_dep)?;
Ok(())
}
- fn generate_devices_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()> {
+ fn generate_devices_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()> {
// timer
let mut cells: Vec<u32> = Vec::new();
for &irq in [13, 14, 11, 10].iter() {
- cells.push(device_tree::GIC_FDT_IRQ_TYPE_PPI);
+ cells.push(fdt::GIC_FDT_IRQ_TYPE_PPI);
cells.push(irq);
- cells.push(device_tree::IRQ_TYPE_LEVEL_HIGH);
+ cells.push(fdt::IRQ_TYPE_LEVEL_HIGH);
}
- let node = "/timer";
- device_tree::add_sub_node(fdt, node)?;
- device_tree::set_property_string(fdt, node, "compatible", "arm,armv8-timer")?;
- device_tree::set_property(fdt, node, "always-on", None)?;
- device_tree::set_property_array_u32(fdt, node, "interrupts", &cells)?;
+ let node = "timer";
+ let timer_node_dep = fdt.begin_node(node)?;
+ fdt.set_property_string("compatible", "arm,armv8-timer")?;
+ fdt.set_property("always-on", &Vec::new())?;
+ fdt.set_property_array_u32("interrupts", &cells)?;
+ fdt.end_node(timer_node_dep)?;
// clock
- let node = "/apb-pclk";
- device_tree::add_sub_node(fdt, node)?;
- device_tree::set_property_string(fdt, node, "compatible", "fixed-clock")?;
- device_tree::set_property_string(fdt, node, "clock-output-names", "clk24mhz")?;
- device_tree::set_property_u32(fdt, node, "#clock-cells", 0x0)?;
- device_tree::set_property_u32(fdt, node, "clock-frequency", 24_000_000)?;
- device_tree::set_property_u32(fdt, node, "phandle", device_tree::CLK_PHANDLE)?;
+ let node = "apb-pclk";
+ let clock_node_dep = fdt.begin_node(node)?;
+ fdt.set_property_string("compatible", "fixed-clock")?;
+ fdt.set_property_string("clock-output-names", "clk24mhz")?;
+ fdt.set_property_u32("#clock-cells", 0x0)?;
+ fdt.set_property_u32("clock-frequency", 24_000_000)?;
+ fdt.set_property_u32("phandle", fdt::CLK_PHANDLE)?;
+ fdt.end_node(clock_node_dep)?;
// psci
- let node = "/psci";
- device_tree::add_sub_node(fdt, node)?;
- device_tree::set_property_string(fdt, node, "compatible", "arm,psci-0.2")?;
- device_tree::set_property_string(fdt, node, "method", "hvc")?;
+ let node = "psci";
+ let psci_node_dep = fdt.begin_node(node)?;
+ fdt.set_property_string("compatible", "arm,psci-0.2")?;
+ fdt.set_property_string("method", "hvc")?;
+ fdt.end_node(psci_node_dep)?;
- // Reversing vector is needed because FDT node is added in reverse.
- for dev in self.sysbus.devices.iter().rev() {
+ for dev in self.sysbus.devices.iter() {
let mut locked_dev = dev.lock().unwrap();
let dev_type = locked_dev.get_type();
let sys_res = locked_dev.get_sys_resource();
@@ -1707,46 +1707,39 @@ impl CompileFDTHelper for LightMachine {
Ok(())
}
- fn generate_chosen_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()> {
- let node = "/chosen";
-
+ fn generate_chosen_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()> {
+ let node = "chosen";
let boot_source = self.boot_source.lock().unwrap();
- device_tree::add_sub_node(fdt, node)?;
+ let chosen_node_dep = fdt.begin_node(node)?;
let cmdline = &boot_source.kernel_cmdline.to_string();
- device_tree::set_property_string(fdt, node, "bootargs", cmdline.as_str())?;
+ fdt.set_property_string("bootargs", cmdline.as_str())?;
match &boot_source.initrd {
Some(initrd) => {
- device_tree::set_property_u64(
- fdt,
- node,
- "linux,initrd-start",
- *initrd.initrd_addr.lock().unwrap(),
- )?;
- device_tree::set_property_u64(
- fdt,
- node,
+ fdt.set_property_u64("linux,initrd-start", *initrd.initrd_addr.lock().unwrap())?;
+ fdt.set_property_u64(
"linux,initrd-end",
*initrd.initrd_addr.lock().unwrap() + initrd.initrd_size,
)?;
}
None => {}
}
+ fdt.end_node(chosen_node_dep)?;
Ok(())
}
}
#[cfg(target_arch = "aarch64")]
-impl device_tree::CompileFDT for LightMachine {
- fn generate_fdt_node(&self, fdt: &mut Vec<u8>) -> util::errors::Result<()> {
- device_tree::create_device_tree(fdt)?;
+impl fdt::CompileFDT for LightMachine {
+ fn generate_fdt_node(&self, fdt: &mut FdtBuilder) -> util::errors::Result<()> {
+ let node_dep = fdt.begin_node("")?;
- device_tree::set_property_string(fdt, "/", "compatible", "linux,dummy-virt")?;
- device_tree::set_property_u32(fdt, "/", "#address-cells", 0x2)?;
- device_tree::set_property_u32(fdt, "/", "#size-cells", 0x2)?;
- device_tree::set_property_u32(fdt, "/", "interrupt-parent", device_tree::GIC_PHANDLE)?;
+ fdt.set_property_string("compatible", "linux,dummy-virt")?;
+ fdt.set_property_u32("#address-cells", 0x2)?;
+ fdt.set_property_u32("#size-cells", 0x2)?;
+ fdt.set_property_u32("interrupt-parent", fdt::GIC_PHANDLE)?;
self.generate_cpu_nodes(fdt)?;
self.generate_memory_node(fdt)?;
@@ -1754,6 +1747,8 @@ impl device_tree::CompileFDT for LightMachine {
self.generate_chosen_node(fdt)?;
self.irq_chip.as_ref().unwrap().generate_fdt_node(fdt)?;
+ fdt.end_node(node_dep)?;
+
Ok(())
}
}
--
2.31.1