Skip to content

Commit 22aab36

Browse files
JonathanWoollett-LightJonathan Woollett-Light
authored andcommitted
fix: Update Arm logging
For Arm specific code, adds additional `std::fmt::Debug` implementations, these require removing some dynamic dispatch which involves removing the `GICDevice` trait. Signed-off-by: Jonathan Woollett-Light <[email protected]>
1 parent c9dab3d commit 22aab36

File tree

14 files changed

+342
-232
lines changed

14 files changed

+342
-232
lines changed

src/logger/src/metrics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,17 @@ impl RtcEvents for RTCDeviceMetrics {
894894
}
895895
}
896896

897+
#[cfg(target_arch = "aarch64")]
898+
impl RtcEvents for &'static RTCDeviceMetrics {
899+
fn invalid_read(&self) {
900+
RTCDeviceMetrics::invalid_read(self);
901+
}
902+
903+
fn invalid_write(&self) {
904+
RTCDeviceMetrics::invalid_write(self);
905+
}
906+
}
907+
897908
/// Metrics for the seccomp filtering.
898909
#[derive(Debug, Default, Serialize)]
899910
pub struct SeccompMetrics {

src/vmm/src/arch/aarch64/fdt.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildHasher
7171
vcpu_mpidr: Vec<u64>,
7272
cmdline: CString,
7373
device_info: &HashMap<(DeviceType, String), T, S>,
74-
gic_device: &dyn GICDevice,
74+
gic_device: &GICDevice,
7575
initrd: &Option<InitrdConfig>,
7676
) -> Result<Vec<u8>> {
7777
// Allocate stuff necessary for storing the blob.
@@ -257,7 +257,7 @@ fn create_chosen_node(
257257
Ok(())
258258
}
259259

260-
fn create_gic_node(fdt: &mut FdtWriter, gic_device: &dyn GICDevice) -> Result<()> {
260+
fn create_gic_node(fdt: &mut FdtWriter, gic_device: &GICDevice) -> Result<()> {
261261
let interrupt = fdt.begin_node("intc")?;
262262
fdt.property_string("compatible", gic_device.fdt_compatibility())?;
263263
fdt.property_null("interrupt-controller")?;
@@ -490,7 +490,7 @@ mod tests {
490490
vec![0],
491491
CString::new("console=tty0").unwrap(),
492492
&dev_info,
493-
gic.as_ref(),
493+
&gic,
494494
&None,
495495
)
496496
.is_ok())
@@ -516,7 +516,7 @@ mod tests {
516516
vec![0],
517517
CString::new("console=tty0").unwrap(),
518518
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
519-
gic.as_ref(),
519+
&gic,
520520
&None,
521521
)
522522
.unwrap();
@@ -579,7 +579,7 @@ mod tests {
579579
vec![0],
580580
CString::new("console=tty0").unwrap(),
581581
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
582-
gic.as_ref(),
582+
&gic,
583583
&Some(initrd),
584584
)
585585
.unwrap();

src/vmm/src/arch/aarch64/gic/gicv2/mod.rs

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,24 @@
33

44
mod regs;
55

6-
use std::boxed::Box;
76
use std::result;
87

9-
use kvm_ioctls::DeviceFd;
8+
use kvm_ioctls::{DeviceFd, VmFd};
109

11-
use crate::arch::aarch64::gic::{Error, GICDevice, GicState};
10+
use crate::arch::aarch64::gic::{Error, GicState};
1211

1312
type Result<T> = result::Result<T, Error>;
1413

1514
/// Represent a GIC v2 device
16-
pub struct GICv2 {
17-
/// The file descriptor for the KVM device
18-
fd: DeviceFd,
15+
#[derive(Debug)]
16+
pub struct GICv2(super::GIC);
1917

20-
/// GIC device properties, to be used for setting up the fdt entry
21-
properties: [u64; 4],
18+
impl std::ops::Deref for GICv2 {
19+
type Target = super::GIC;
2220

23-
/// Number of CPUs handled by the device
24-
vcpu_count: u64,
21+
fn deref(&self) -> &Self::Target {
22+
&self.0
23+
}
2524
}
2625

2726
impl GICv2 {
@@ -52,35 +51,20 @@ impl GICv2 {
5251
const fn get_cpu_size() -> u64 {
5352
GICv2::KVM_VGIC_V2_CPU_SIZE
5453
}
55-
}
56-
57-
impl GICDevice for GICv2 {
58-
fn version() -> u32 {
59-
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2
60-
}
61-
62-
fn device_fd(&self) -> &DeviceFd {
63-
&self.fd
64-
}
6554

66-
fn device_properties(&self) -> &[u64] {
67-
&self.properties
68-
}
55+
pub const VERSION: u32 = kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2;
6956

70-
fn vcpu_count(&self) -> u64 {
71-
self.vcpu_count
72-
}
73-
74-
fn fdt_compatibility(&self) -> &str {
57+
pub fn fdt_compatibility(&self) -> &str {
7558
"arm,gic-400"
7659
}
7760

78-
fn fdt_maint_irq(&self) -> u32 {
61+
pub fn fdt_maint_irq(&self) -> u32 {
7962
GICv2::ARCH_GIC_V2_MAINT_IRQ
8063
}
8164

82-
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
83-
Box::new(GICv2 {
65+
/// Create the GIC device object
66+
pub fn create_device(fd: DeviceFd, vcpu_count: u64) -> Self {
67+
GICv2(super::GIC {
8468
fd,
8569
properties: [
8670
GICv2::get_dist_addr(),
@@ -92,15 +76,15 @@ impl GICDevice for GICv2 {
9276
})
9377
}
9478

95-
fn save_device(&self, mpidrs: &[u64]) -> Result<GicState> {
79+
pub fn save_device(&self, mpidrs: &[u64]) -> Result<GicState> {
9680
regs::save_state(&self.fd, mpidrs)
9781
}
9882

99-
fn restore_device(&self, mpidrs: &[u64], state: &GicState) -> Result<()> {
83+
pub fn restore_device(&self, mpidrs: &[u64], state: &GicState) -> Result<()> {
10084
regs::restore_state(&self.fd, mpidrs, state)
10185
}
10286

103-
fn init_device_attributes(gic_device: &dyn GICDevice) -> Result<()> {
87+
pub fn init_device_attributes(gic_device: &Self) -> Result<()> {
10488
// Setting up the distributor attribute.
10589
// We are placing the GIC below 1GB so we need to substract the size of the distributor.
10690
Self::set_device_attribute(
@@ -122,4 +106,78 @@ impl GICDevice for GICv2 {
122106

123107
Ok(())
124108
}
109+
110+
/// Initialize a GIC device
111+
pub fn init_device(vm: &VmFd) -> Result<DeviceFd> {
112+
let mut gic_device = kvm_bindings::kvm_create_device {
113+
type_: Self::VERSION,
114+
fd: 0,
115+
flags: 0,
116+
};
117+
118+
vm.create_device(&mut gic_device).map_err(Error::CreateGIC)
119+
}
120+
121+
/// Method to initialize the GIC device
122+
pub fn create(vm: &VmFd, vcpu_count: u64) -> Result<Self> {
123+
let vgic_fd = Self::init_device(vm)?;
124+
125+
let device = Self::create_device(vgic_fd, vcpu_count);
126+
127+
Self::init_device_attributes(&device)?;
128+
129+
Self::finalize_device(&device)?;
130+
131+
Ok(device)
132+
}
133+
134+
/// Finalize the setup of a GIC device
135+
pub fn finalize_device(gic_device: &Self) -> Result<()> {
136+
// On arm there are 3 types of interrupts: SGI (0-15), PPI (16-31), SPI (32-1020).
137+
// SPIs are used to signal interrupts from various peripherals accessible across
138+
// the whole system so these are the ones that we increment when adding a new virtio device.
139+
// KVM_DEV_ARM_VGIC_GRP_NR_IRQS sets the highest SPI number. Consequently, we will have a
140+
// total of `super::layout::IRQ_MAX - 32` usable SPIs in our microVM.
141+
let nr_irqs: u32 = super::layout::IRQ_MAX;
142+
let nr_irqs_ptr = &nr_irqs as *const u32;
143+
Self::set_device_attribute(
144+
gic_device.device_fd(),
145+
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
146+
0,
147+
nr_irqs_ptr as u64,
148+
0,
149+
)?;
150+
151+
// Finalize the GIC.
152+
// See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211.
153+
Self::set_device_attribute(
154+
gic_device.device_fd(),
155+
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
156+
u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
157+
0,
158+
0,
159+
)?;
160+
161+
Ok(())
162+
}
163+
164+
/// Set a GIC device attribute
165+
pub fn set_device_attribute(
166+
fd: &DeviceFd,
167+
group: u32,
168+
attr: u64,
169+
addr: u64,
170+
flags: u32,
171+
) -> Result<()> {
172+
let attr = kvm_bindings::kvm_device_attr {
173+
flags,
174+
group,
175+
attr,
176+
addr,
177+
};
178+
fd.set_device_attr(&attr)
179+
.map_err(|err| Error::DeviceAttribute(err, true, group))?;
180+
181+
Ok(())
182+
}
125183
}

0 commit comments

Comments
 (0)