Skip to content

Commit 5fbf260

Browse files
xuejun-xjstudychao
authored andcommitted
dbs-boot: fdt_utils: create a new module
This commit creates a new module called fdt_utils. It abstracts the parameters for constructing fdt on aarch64. It contains three structs for now: 1. FdtVmInfo: saves information about micro vm 2. FdtNumaInfo: saves information about numa 3. FdtDeviceInfo: saves information about devices Fixes: openanolis#276 Opensource: y Signed-off-by: xuejun-xj <[email protected]>
1 parent 9ee3590 commit 5fbf260

File tree

4 files changed

+487
-94
lines changed

4 files changed

+487
-94
lines changed

crates/dbs-boot/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ vm-fdt = "0.2.0"
2323
[dev-dependencies]
2424
vm-memory = { version = "0.9.0", features = ["backend-mmap"] }
2525
device_tree = ">=1.1.0"
26+
dbs-device = { path = "../dbs-device", version = "0.2.0" }

crates/dbs-boot/src/aarch64/fdt.rs

Lines changed: 75 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ use vm_fdt::FdtWriter;
2020
use vm_memory::GuestMemoryRegion;
2121
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory};
2222

23+
use super::fdt_utils::*;
2324
use super::Error;
24-
use crate::{InitrdConfig, Result};
25+
use crate::Result;
2526

2627
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
2728
const GIC_PHANDLE: u32 = 1;
@@ -48,19 +49,15 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
4849
const IRQ_TYPE_EDGE_RISING: u32 = 1;
4950
const IRQ_TYPE_LEVEL_HI: u32 = 4;
5051

51-
#[allow(clippy::borrowed_box)]
5252
/// Creates the flattened device tree for this aarch64 microVM.
53-
pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
54-
guest_mem: &M,
55-
// field 0: boot_onlined, decides whether to online this cpu at boot
56-
// field 1: vcpu_mpidr
57-
vcpu_state: Vec<(u32, u64)>,
58-
cmdline: &str,
59-
device_info: Option<&HashMap<(DeviceType, String), T>>,
60-
gic_device: &Box<dyn GICDevice>,
61-
initrd: &Option<InitrdConfig>,
62-
vpmu_feature: &VpmuFeatureLevel,
63-
) -> Result<Vec<u8>> {
53+
pub fn create_fdt<T>(
54+
fdt_vm_info: FdtVmInfo,
55+
_fdt_numa_info: FdtNumaInfo,
56+
fdt_device_info: FdtDeviceInfo<T>,
57+
) -> Result<Vec<u8>>
58+
where
59+
T: DeviceInfoForFDT + Clone + Debug,
60+
{
6461
let mut fdt = FdtWriter::new()?;
6562

6663
// For an explanation why these nodes were introduced in the blob take a look at
@@ -77,15 +74,17 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
7774
// This is not mandatory but we use it to point the root node to the node
7875
// containing description of the interrupt controller for this VM.
7976
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
80-
create_cpu_nodes(&mut fdt, &vcpu_state)?;
81-
create_memory_node(&mut fdt, guest_mem)?;
82-
create_chosen_node(&mut fdt, cmdline, initrd)?;
83-
create_gic_node(&mut fdt, gic_device.as_ref())?;
77+
create_cpu_nodes(&mut fdt, &fdt_vm_info)?;
78+
create_memory_node(&mut fdt, fdt_vm_info.get_guest_memory())?;
79+
create_chosen_node(&mut fdt, &fdt_vm_info)?;
80+
create_gic_node(&mut fdt, fdt_device_info.get_irqchip())?;
8481
create_timer_node(&mut fdt)?;
8582
create_clock_node(&mut fdt)?;
8683
create_psci_node(&mut fdt)?;
87-
device_info.map_or(Ok(()), |v| create_devices_node(&mut fdt, v))?;
88-
create_pmu_node(&mut fdt, vpmu_feature)?;
84+
fdt_device_info
85+
.get_mmio_device_info()
86+
.map_or(Ok(()), |v| create_devices_node(&mut fdt, v))?;
87+
create_pmu_node(&mut fdt, fdt_vm_info.get_vpmu_feature())?;
8988

9089
// End Header node.
9190
fdt.end_node(root_node)?;
@@ -94,21 +93,25 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
9493
let fdt_final = fdt.finish()?;
9594

9695
// Write FDT to memory.
97-
let fdt_address = GuestAddress(super::get_fdt_addr(guest_mem));
98-
guest_mem.write_slice(fdt_final.as_slice(), fdt_address)?;
96+
let fdt_address = GuestAddress(super::get_fdt_addr(fdt_vm_info.get_guest_memory()));
97+
fdt_vm_info
98+
.get_guest_memory()
99+
.write_slice(fdt_final.as_slice(), fdt_address)?;
99100
Ok(fdt_final)
100101
}
101102

102103
// Following are the auxiliary function for creating the different nodes that we append to our FDT.
103-
fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_state: &[(u32, u64)]) -> Result<()> {
104+
fn create_cpu_nodes(fdt: &mut FdtWriter, fdt_vm_info: &FdtVmInfo) -> Result<()> {
104105
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
105106
let cpus_node = fdt.begin_node("cpus")?;
106107
// As per documentation, on ARM v8 64-bit systems value should be set to 2.
107108
fdt.property_u32("#address-cells", 0x02)?;
108109
fdt.property_u32("#size-cells", 0x0)?;
109-
let num_cpus = vcpu_state.len();
110+
let vcpu_mpidr = fdt_vm_info.get_vcpu_mpidr();
111+
let vcpu_boot_onlined = fdt_vm_info.get_boot_onlined();
112+
let num_cpus = vcpu_mpidr.len();
110113

111-
for (cpu_index, iter) in vcpu_state.iter().enumerate().take(num_cpus) {
114+
for (cpu_index, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
112115
let cpu_name = format!("cpu@{cpu_index:x}");
113116
let cpu_node = fdt.begin_node(&cpu_name)?;
114117
fdt.property_string("device_type", "cpu")?;
@@ -119,10 +122,10 @@ fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_state: &[(u32, u64)]) -> Result<()
119122
}
120123
// boot-onlined attribute is used to indicate whether this cpu should be onlined at boot.
121124
// 0 means offline, 1 means online.
122-
fdt.property_u32("boot-onlined", iter.0)?;
125+
fdt.property_u32("boot-onlined", vcpu_boot_onlined[cpu_index])?;
123126
// Set the field to first 24 bits of the MPIDR - Multiprocessor Affinity Register.
124127
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABHBJCI.html.
125-
fdt.property_u64("reg", iter.1 & 0x7FFFFF)?;
128+
fdt.property_u64("reg", mpidr & 0x7FFFFF)?;
126129
fdt.end_node(cpu_node)?;
127130
}
128131
fdt.end_node(cpus_node)?;
@@ -142,15 +145,11 @@ fn create_memory_node<M: GuestMemory>(fdt: &mut FdtWriter, guest_mem: &M) -> Res
142145
Ok(())
143146
}
144147

145-
fn create_chosen_node(
146-
fdt: &mut FdtWriter,
147-
cmdline: &str,
148-
initrd: &Option<InitrdConfig>,
149-
) -> Result<()> {
148+
fn create_chosen_node(fdt: &mut FdtWriter, fdt_vm_info: &FdtVmInfo) -> Result<()> {
150149
let chosen_node = fdt.begin_node("chosen")?;
151-
fdt.property_string("bootargs", cmdline)?;
150+
fdt.property_string("bootargs", fdt_vm_info.get_cmdline())?;
152151

153-
if let Some(initrd_config) = initrd {
152+
if let Some(initrd_config) = fdt_vm_info.get_initrd_config() {
154153
fdt.property_u64("linux,initrd-start", initrd_config.address.raw_value())?;
155154
fdt.property_u64(
156155
"linux,initrd-end",
@@ -373,8 +372,8 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug>(
373372
Ok(())
374373
}
375374

376-
fn create_pmu_node(fdt: &mut FdtWriter, vpmu_feature: &VpmuFeatureLevel) -> Result<()> {
377-
if *vpmu_feature == VpmuFeatureLevel::Disabled {
375+
fn create_pmu_node(fdt: &mut FdtWriter, vpmu_feature: VpmuFeatureLevel) -> Result<()> {
376+
if vpmu_feature == VpmuFeatureLevel::Disabled {
378377
return Ok(());
379378
};
380379

@@ -396,14 +395,16 @@ mod tests {
396395
use std::io::Write;
397396
use std::path::PathBuf;
398397

399-
use dbs_arch::{gic::create_gic, pmu::initialize_pmu, Error as ArchError};
398+
use dbs_arch::{gic::create_gic, pmu::initialize_pmu};
400399
use device_tree::DeviceTree;
401400
use kvm_bindings::{kvm_vcpu_init, KVM_ARM_VCPU_PMU_V3, KVM_ARM_VCPU_PSCI_0_2};
402401
use kvm_ioctls::{Kvm, VcpuFd, VmFd};
403402
use vm_memory::GuestMemoryMmap;
404403

404+
use super::super::tests::MMIODeviceInfo;
405405
use super::*;
406406
use crate::layout::{DRAM_MEM_MAX_SIZE, DRAM_MEM_START, FDT_MAX_SIZE};
407+
use crate::InitrdConfig;
407408

408409
const LEN: u64 = 4096;
409410

@@ -412,27 +413,6 @@ mod tests {
412413
vec![(GuestAddress(DRAM_MEM_START), dram_size)]
413414
}
414415

415-
#[derive(Clone, Debug)]
416-
pub struct MMIODeviceInfo {
417-
addr: u64,
418-
irq: u32,
419-
}
420-
421-
impl DeviceInfoForFDT for MMIODeviceInfo {
422-
fn addr(&self) -> u64 {
423-
self.addr
424-
}
425-
fn irq(&self) -> std::result::Result<u32, ArchError> {
426-
Ok(self.irq)
427-
}
428-
fn length(&self) -> u64 {
429-
LEN
430-
}
431-
fn get_device_id(&self) -> Option<u32> {
432-
None
433-
}
434-
}
435-
436416
// The `load` function from the `device_tree` will mistakenly check the actual size
437417
// of the buffer with the allocated size. This works around that.
438418
fn set_size(buf: &mut [u8], pos: usize, val: usize) {
@@ -485,18 +465,15 @@ mod tests {
485465
let dev_info: HashMap<(DeviceType, String), MMIODeviceInfo> = [
486466
(
487467
(DeviceType::Serial, DeviceType::Serial.to_string()),
488-
MMIODeviceInfo { addr: 0x00, irq: 1 },
468+
MMIODeviceInfo::new(0, 1),
489469
),
490470
(
491471
(DeviceType::Virtio(1), "virtio".to_string()),
492-
MMIODeviceInfo { addr: LEN, irq: 2 },
472+
MMIODeviceInfo::new(LEN, 2),
493473
),
494474
(
495475
(DeviceType::RTC, "rtc".to_string()),
496-
MMIODeviceInfo {
497-
addr: 2 * LEN,
498-
irq: 3,
499-
},
476+
MMIODeviceInfo::new(2 * LEN, 3),
500477
),
501478
]
502479
.iter()
@@ -507,13 +484,14 @@ mod tests {
507484
let gic = create_gic(&vm, 1).unwrap();
508485
let vpmu_feature = VpmuFeatureLevel::Disabled;
509486
assert!(create_fdt(
510-
&mem,
511-
vec![(1, 0)],
512-
"console=tty0",
513-
Some(&dev_info),
514-
&gic,
515-
&None,
516-
&vpmu_feature
487+
FdtVmInfo::new(
488+
&mem,
489+
"console=tty0",
490+
None,
491+
FdtVcpuInfo::new(vec![0], vec![1], vpmu_feature, false)
492+
),
493+
FdtNumaInfo::default(),
494+
FdtDeviceInfo::new(Some(&dev_info), gic.as_ref())
517495
)
518496
.is_ok())
519497
}
@@ -527,13 +505,14 @@ mod tests {
527505
let gic = create_gic(&vm, 1).unwrap();
528506
let vpmu_feature = VpmuFeatureLevel::Disabled;
529507
let dtb = create_fdt(
530-
&mem,
531-
vec![(1, 0)],
532-
"console=tty0",
533-
None::<&HashMap<(DeviceType, String), MMIODeviceInfo>>,
534-
&gic,
535-
&None,
536-
&vpmu_feature,
508+
FdtVmInfo::new(
509+
&mem,
510+
"console=tty0",
511+
None,
512+
FdtVcpuInfo::new(vec![0], vec![1], vpmu_feature, false),
513+
),
514+
FdtNumaInfo::default(),
515+
FdtDeviceInfo::<MMIODeviceInfo>::new(None, gic.as_ref()),
537516
)
538517
.unwrap();
539518

@@ -548,7 +527,7 @@ mod tests {
548527

549528
let original_fdt = DeviceTree::load(&buf).unwrap();
550529
let generated_fdt = DeviceTree::load(&dtb).unwrap();
551-
assert!(format!("{original_fdt:?}") == format!("{generated_fdt:?}"));
530+
assert_eq!(format!("{original_fdt:?}"), format!("{generated_fdt:?}"));
552531
}
553532

554533
#[test]
@@ -564,13 +543,14 @@ mod tests {
564543
};
565544
let vpmu_feature = VpmuFeatureLevel::Disabled;
566545
let dtb = create_fdt(
567-
&mem,
568-
vec![(1, 0)],
569-
"console=tty0",
570-
None::<&HashMap<(DeviceType, String), MMIODeviceInfo>>,
571-
&gic,
572-
&Some(initrd),
573-
&vpmu_feature,
546+
FdtVmInfo::new(
547+
&mem,
548+
"console=tty0",
549+
Some(&initrd),
550+
FdtVcpuInfo::new(vec![0], vec![1], vpmu_feature, false),
551+
),
552+
FdtNumaInfo::default(),
553+
FdtDeviceInfo::<MMIODeviceInfo>::new(None, gic.as_ref()),
574554
)
575555
.unwrap();
576556

@@ -585,7 +565,7 @@ mod tests {
585565

586566
let original_fdt = DeviceTree::load(&buf).unwrap();
587567
let generated_fdt = DeviceTree::load(&dtb).unwrap();
588-
assert!(format!("{original_fdt:?}") == format!("{generated_fdt:?}"));
568+
assert_eq!(format!("{original_fdt:?}"), format!("{generated_fdt:?}"));
589569
}
590570

591571
#[test]
@@ -601,13 +581,14 @@ mod tests {
601581

602582
let vpmu_feature = VpmuFeatureLevel::FullyEnabled;
603583
let dtb = create_fdt(
604-
&mem,
605-
vec![(1, 0)],
606-
"console=tty0",
607-
None::<&std::collections::HashMap<(DeviceType, std::string::String), MMIODeviceInfo>>,
608-
&gic,
609-
&None,
610-
&vpmu_feature,
584+
FdtVmInfo::new(
585+
&mem,
586+
"console=tty0",
587+
None,
588+
FdtVcpuInfo::new(vec![0], vec![1], vpmu_feature, false),
589+
),
590+
FdtNumaInfo::default(),
591+
FdtDeviceInfo::<MMIODeviceInfo>::new(None, gic.as_ref()),
611592
)
612593
.unwrap();
613594

@@ -622,6 +603,6 @@ mod tests {
622603

623604
let original_fdt = DeviceTree::load(&buf).unwrap();
624605
let generated_fdt = DeviceTree::load(&dtb).unwrap();
625-
assert!(format!("{original_fdt:?}") == format!("{generated_fdt:?}"));
606+
assert_eq!(format!("{original_fdt:?}"), format!("{generated_fdt:?}"));
626607
}
627608
}

0 commit comments

Comments
 (0)