Skip to content

Commit fa0b2dd

Browse files
authored
Merge branch 'main' into block-latency-test
2 parents 804f9a6 + 6a8347f commit fa0b2dd

File tree

2 files changed

+74
-22
lines changed

2 files changed

+74
-22
lines changed

src/vmm/src/arch/aarch64/regs.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Use of this source code is governed by a BSD-style license that can be
66
// found in the THIRD-PARTY file.
77

8+
use std::fmt::Write;
89
use std::mem::offset_of;
910

1011
use kvm_bindings::*;
@@ -404,6 +405,15 @@ impl<'a> Aarch64RegisterRef<'a> {
404405
T::from_slice(self.data)
405406
}
406407

408+
/// Returns a string with hex formatted value of the register.
409+
pub fn value_str(&self) -> String {
410+
let hex = self.data.iter().rev().fold(String::new(), |mut acc, byte| {
411+
write!(&mut acc, "{:02x}", byte).unwrap();
412+
acc
413+
});
414+
format!("0x{hex}")
415+
}
416+
407417
/// Returns register data as a byte slice
408418
pub fn as_slice(&self) -> &[u8] {
409419
self.data
@@ -695,6 +705,32 @@ mod tests {
695705
assert_eq!(reg_ref.value::<u64, 8>(), 69);
696706
}
697707

708+
#[test]
709+
fn test_reg_ref_value_str() {
710+
let bytes = 0x10_u8.to_le_bytes();
711+
let reg_ref = Aarch64RegisterRef::new(KVM_REG_SIZE_U8 as u64, &bytes);
712+
assert_eq!(reg_ref.value_str(), "0x10");
713+
714+
let bytes = 0x1020_u16.to_le_bytes();
715+
let reg_ref = Aarch64RegisterRef::new(KVM_REG_SIZE_U16, &bytes);
716+
assert_eq!(reg_ref.value_str(), "0x1020");
717+
718+
let bytes = 0x10203040_u32.to_le_bytes();
719+
let reg_ref = Aarch64RegisterRef::new(KVM_REG_SIZE_U32, &bytes);
720+
assert_eq!(reg_ref.value_str(), "0x10203040");
721+
722+
let bytes = 0x1020304050607080_u64.to_le_bytes();
723+
let reg_ref = Aarch64RegisterRef::new(KVM_REG_SIZE_U64, &bytes);
724+
assert_eq!(reg_ref.value_str(), "0x1020304050607080");
725+
726+
let bytes = [
727+
0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30,
728+
0x20, 0x10,
729+
];
730+
let reg_ref = Aarch64RegisterRef::new(KVM_REG_SIZE_U128, &bytes);
731+
assert_eq!(reg_ref.value_str(), "0x10203040506070809011213141516171");
732+
}
733+
698734
/// Should panic because ID has different size from a slice length.
699735
/// - Size in ID: 128
700736
/// - Length of slice: 1

src/vmm/src/arch/aarch64/vcpu.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
use std::fmt::{Debug, Write};
99
use std::mem::offset_of;
10-
use std::path::PathBuf;
1110

1211
use kvm_bindings::*;
1312
use kvm_ioctls::{VcpuExit, VcpuFd, VmFd};
@@ -31,8 +30,8 @@ use crate::vstate::vm::Vm;
3130
pub enum VcpuArchError {
3231
/// Failed to get register {0}: {1}
3332
GetOneReg(u64, kvm_ioctls::Error),
34-
/// Failed to set register {0}: {1}
35-
SetOneReg(u64, kvm_ioctls::Error),
33+
/// Failed to set register {0:#x} to value {1}: {2}
34+
SetOneReg(u64, String, kvm_ioctls::Error),
3635
/// Failed to retrieve list of registers: {0}
3736
GetRegList(kvm_ioctls::Error),
3837
/// Failed to get multiprocessor state: {0}
@@ -48,9 +47,7 @@ pub enum VcpuArchError {
4847
/// Extract the Manufacturer ID from the host.
4948
/// The ID is found between bits 24-31 of MIDR_EL1 register.
5049
pub fn get_manufacturer_id_from_host() -> Result<u32, VcpuArchError> {
51-
let midr_el1_path =
52-
&PathBuf::from("/sys/devices/system/cpu/cpu0/regs/identification/midr_el1".to_string());
53-
50+
let midr_el1_path = "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1";
5451
let midr_el1 = std::fs::read_to_string(midr_el1_path).map_err(|err| {
5552
VcpuArchError::GetMidrEl1(format!("Failed to get MIDR_EL1 from host path: {err}"))
5653
})?;
@@ -181,7 +178,11 @@ impl KvmVcpu {
181178
) -> Result<(), KvmVcpuError> {
182179
for reg in vcpu_config.cpu_config.regs.iter() {
183180
self.fd.set_one_reg(reg.id, reg.as_slice()).map_err(|err| {
184-
KvmVcpuError::ApplyCpuTemplate(VcpuArchError::SetOneReg(reg.id, err))
181+
KvmVcpuError::ApplyCpuTemplate(VcpuArchError::SetOneReg(
182+
reg.id,
183+
reg.value_str(),
184+
err,
185+
))
185186
})?;
186187
}
187188

@@ -325,7 +326,9 @@ impl KvmVcpu {
325326
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate);
326327
self.fd
327328
.set_one_reg(id, &PSTATE_FAULT_BITS_64.to_le_bytes())
328-
.map_err(|err| VcpuArchError::SetOneReg(id, err))?;
329+
.map_err(|err| {
330+
VcpuArchError::SetOneReg(id, format!("{PSTATE_FAULT_BITS_64:#x}"), err)
331+
})?;
329332

330333
// Other vCPUs are powered off initially awaiting PSCI wakeup.
331334
if self.index == 0 {
@@ -334,17 +337,18 @@ impl KvmVcpu {
334337
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pc);
335338
self.fd
336339
.set_one_reg(id, &boot_ip.to_le_bytes())
337-
.map_err(|err| VcpuArchError::SetOneReg(id, err))?;
340+
.map_err(|err| VcpuArchError::SetOneReg(id, format!("{boot_ip:#x}"), err))?;
338341

339342
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
340343
// "The device tree blob (dtb) must be placed on an 8-byte boundary and must
341344
// not exceed 2 megabytes in size." -> https://www.kernel.org/doc/Documentation/arm64/booting.txt.
342345
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
343346
let regs0 = offset_of!(user_pt_regs, regs) + kreg_off;
344347
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0);
348+
let fdt_addr = get_fdt_addr(mem);
345349
self.fd
346-
.set_one_reg(id, &get_fdt_addr(mem).to_le_bytes())
347-
.map_err(|err| VcpuArchError::SetOneReg(id, err))?;
350+
.set_one_reg(id, &fdt_addr.to_le_bytes())
351+
.map_err(|err| VcpuArchError::SetOneReg(id, format!("{fdt_addr:#x}"), err))?;
348352

349353
// Reset the physical counter for the guest. This way we avoid guest reading
350354
// host physical counter.
@@ -360,7 +364,9 @@ impl KvmVcpu {
360364
if optional_capabilities.counter_offset {
361365
self.fd
362366
.set_one_reg(KVM_REG_ARM_PTIMER_CNT, &[0; 8])
363-
.map_err(|err| VcpuArchError::SetOneReg(id, err))?;
367+
.map_err(|err| {
368+
VcpuArchError::SetOneReg(id, format!("{KVM_REG_ARM_PTIMER_CNT:#x}"), err)
369+
})?;
364370
}
365371
}
366372
Ok(())
@@ -412,7 +418,7 @@ impl KvmVcpu {
412418
pub fn set_register(&self, reg: Aarch64RegisterRef) -> Result<(), VcpuArchError> {
413419
self.fd
414420
.set_one_reg(reg.id, reg.as_slice())
415-
.map_err(|e| VcpuArchError::SetOneReg(reg.id, e))?;
421+
.map_err(|e| VcpuArchError::SetOneReg(reg.id, reg.value_str(), e))?;
416422
Ok(())
417423
}
418424

@@ -526,13 +532,16 @@ mod tests {
526532
unsafe { libc::close(vm.fd().as_raw_fd()) };
527533

528534
let err = KvmVcpu::new(0, &vm);
535+
536+
// dropping vm would double close the gic fd, so leak it
537+
// do the drop before assertion. Otherwise if assert fails,
538+
// we get IO runtime error instead of assert error.
539+
std::mem::forget(vm);
540+
529541
assert_eq!(
530542
err.err().unwrap().to_string(),
531543
"Error creating vcpu: Bad file descriptor (os error 9)".to_string()
532544
);
533-
534-
// dropping vm would double close the gic fd, so leak it
535-
std::mem::forget(vm);
536545
}
537546

538547
#[test]
@@ -568,16 +577,20 @@ mod tests {
568577
&vcpu_config,
569578
&optional_capabilities,
570579
);
580+
581+
// dropping vcpu would double close the gic fd, so leak it
582+
// do the drop before assertion. Otherwise if assert fails,
583+
// we get IO runtime error instead of assert error.
584+
std::mem::forget(vcpu);
585+
571586
assert_eq!(
572587
err.unwrap_err(),
573588
KvmVcpuError::ConfigureRegisters(VcpuArchError::SetOneReg(
574589
0x6030000000100042,
590+
"0x3c5".to_string(),
575591
kvm_ioctls::Error::new(9)
576592
))
577593
);
578-
579-
// dropping vcpu would double close the gic fd, so leak it
580-
std::mem::forget(vcpu);
581594
}
582595

583596
#[test]
@@ -629,7 +642,7 @@ mod tests {
629642
let res = vcpu.restore_state(&faulty_vcpu_state);
630643
assert!(matches!(
631644
res.unwrap_err(),
632-
KvmVcpuError::RestoreState(VcpuArchError::SetOneReg(0, _))
645+
KvmVcpuError::RestoreState(VcpuArchError::SetOneReg(0, _, _))
633646
));
634647

635648
vcpu.init(&[]).unwrap();
@@ -699,7 +712,7 @@ mod tests {
699712
let res = vcpu.setup_boot_regs(0x0, &mem, &optional_capabilities);
700713
assert!(matches!(
701714
res.unwrap_err(),
702-
VcpuArchError::SetOneReg(0x6030000000100042, _)
715+
VcpuArchError::SetOneReg(0x6030000000100042, _, _)
703716
));
704717

705718
vcpu.init_vcpu().unwrap();
@@ -773,9 +786,12 @@ mod tests {
773786
assert!(matches!(res, Err(VcpuArchError::GetMp(_))), "{:?}", res);
774787

775788
let res = vcpu.set_mpstate(kvm_mp_state::default());
776-
assert!(matches!(res, Err(VcpuArchError::SetMp(_))), "{:?}", res);
777789

778790
// dropping vcpu would double close the fd, so leak it
791+
// do the drop before assertion. Otherwise if assert fails,
792+
// we get IO runtime error instead of assert error.
779793
std::mem::forget(vcpu);
794+
795+
assert!(matches!(res, Err(VcpuArchError::SetMp(_))), "{:?}", res);
780796
}
781797
}

0 commit comments

Comments
 (0)