From 4eaeef7cc6d2e2e0817f9b02eb3d415fd9463f37 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Wed, 22 Apr 2026 22:56:20 +0800 Subject: [PATCH 1/6] feat: Impl translate for aarch64 --- Cargo.lock | 9 ++ Cargo.toml | 1 + crates/vm-aarch64/Cargo.toml | 7 + crates/vm-aarch64/src/lib.rs | 16 ++ crates/vm-aarch64/src/register.rs | 5 + crates/vm-aarch64/src/register/cnthctl_el2.rs | 21 +++ .../src/register/id_aa64mmfr0_el1.rs | 9 ++ crates/vm-aarch64/src/register/sctlr_el1.rs | 62 ++++++++ crates/vm-aarch64/src/register/tcr_el1.rs | 28 ++++ crates/vm-aarch64/src/register/ttbr1_el1.rs | 15 ++ crates/vm-core/Cargo.toml | 2 + crates/vm-core/src/arch.rs | 1 + crates/vm-core/src/arch/aarch64/vcpu.rs | 5 +- crates/vm-core/src/arch/aarch64/vcpu/reg.rs | 89 ------------ crates/vm-core/src/arch/mmu.rs | 2 + crates/vm-core/src/arch/mmu/aarch64.rs | 137 ++++++++++++++++++ crates/vm-core/src/arch/registers/aarch64.rs | 5 +- crates/vm-core/src/cpu/error.rs | 3 + crates/vm-core/src/utils.rs | 1 + crates/vm-core/src/utils/bits.rs | 6 + 20 files changed, 330 insertions(+), 94 deletions(-) create mode 100644 crates/vm-aarch64/Cargo.toml create mode 100644 crates/vm-aarch64/src/lib.rs create mode 100644 crates/vm-aarch64/src/register.rs create mode 100644 crates/vm-aarch64/src/register/cnthctl_el2.rs create mode 100644 crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs create mode 100644 crates/vm-aarch64/src/register/sctlr_el1.rs create mode 100644 crates/vm-aarch64/src/register/tcr_el1.rs create mode 100644 crates/vm-aarch64/src/register/ttbr1_el1.rs create mode 100644 crates/vm-core/src/arch/mmu.rs create mode 100644 crates/vm-core/src/arch/mmu/aarch64.rs create mode 100644 crates/vm-core/src/utils/bits.rs diff --git a/Cargo.lock b/Cargo.lock index 74f81ed..27e6b55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1047,6 +1047,13 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vm-aarch64" +version = "0.1.0" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "vm-bootloader" version = "0.1.0" @@ -1096,7 +1103,9 @@ dependencies = [ "thiserror", "tokio", "tracing", + "vm-aarch64", "vm-fdt", + "vm-mm", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7d43123..8336c76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ thiserror = "2.0.17" tokio = { version = "1.49.0", features = ["full"] } tracing = "0.1.44" tracing-subscriber = { version = "0.3.22", features = ["fmt", "env-filter"] } +vm-aarch64 = { path = "crates/vm-aarch64" } vm-bootloader = { path = "crates/vm-bootloader" } vm-core = { path = "crates/vm-core" } vm-device = { path = "crates/vm-device" } diff --git a/crates/vm-aarch64/Cargo.toml b/crates/vm-aarch64/Cargo.toml new file mode 100644 index 0000000..6ef8f9c --- /dev/null +++ b/crates/vm-aarch64/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "vm-aarch64" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitflags = { workspace = true } diff --git a/crates/vm-aarch64/src/lib.rs b/crates/vm-aarch64/src/lib.rs new file mode 100644 index 0000000..31ad066 --- /dev/null +++ b/crates/vm-aarch64/src/lib.rs @@ -0,0 +1,16 @@ +#[deny(warnings)] +pub mod register; + +#[macro_export] +macro_rules! get_field { + ($v:expr, $hi:expr, $lo:expr) => { + (($v >> $lo) & ((1u64 << ($hi - $lo + 1)) - 1)) + }; +} + +#[macro_export] +macro_rules! get_field_bit { + ($v:expr, $b:expr) => { + (($v >> $b) & 0x1) != 0 + }; +} diff --git a/crates/vm-aarch64/src/register.rs b/crates/vm-aarch64/src/register.rs new file mode 100644 index 0000000..7f1700c --- /dev/null +++ b/crates/vm-aarch64/src/register.rs @@ -0,0 +1,5 @@ +pub mod cnthctl_el2; +pub mod id_aa64mmfr0_el1; +pub mod sctlr_el1; +pub mod tcr_el1; +pub mod ttbr1_el1; diff --git a/crates/vm-aarch64/src/register/cnthctl_el2.rs b/crates/vm-aarch64/src/register/cnthctl_el2.rs new file mode 100644 index 0000000..d207453 --- /dev/null +++ b/crates/vm-aarch64/src/register/cnthctl_el2.rs @@ -0,0 +1,21 @@ +use bitflags::bitflags; + +bitflags! { + pub struct CnthctlEl2: u64 { + const EL0PCTEN = 1 << 0; + const EL0VCTEN = 1 << 1; + const EVNTEN = 1 << 2; + const EVNTDIR = 1 << 3; + const EVNTI = 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7; + const EL0VTEN = 1 << 8; + const EL0PTEN = 1 << 9; + const EL1PCTEN = 1 << 10; + const EL1PTEN = 1 << 11; + const ECV = 1 << 12; + const EL1TVT = 1 << 13; + const EL1TVCT = 1 << 14; + const EL1NVPCT = 1 << 15; + const EL1NVVCT = 1 << 16; + const EVNTIS = 1 << 17; + } +} diff --git a/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs b/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs new file mode 100644 index 0000000..bc82924 --- /dev/null +++ b/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs @@ -0,0 +1,9 @@ +use crate::get_field; + +pub struct IdAa64mmfr0El1(u64); + +impl IdAa64mmfr0El1 { + pub fn pa_range(&self) -> u8 { + get_field!(self.0, 3, 0) as u8 + } +} diff --git a/crates/vm-aarch64/src/register/sctlr_el1.rs b/crates/vm-aarch64/src/register/sctlr_el1.rs new file mode 100644 index 0000000..2b38ad5 --- /dev/null +++ b/crates/vm-aarch64/src/register/sctlr_el1.rs @@ -0,0 +1,62 @@ +use bitflags::bitflags; + +bitflags! { + pub struct SctlrEl1: u64 { + const M = 1 << 0; + const A = 1 << 1; + const C = 1 << 2; + const SA = 1 << 3; + const SA0 = 1 << 4; + const CP15BEN = 1 << 5; + const nAA = 1 << 6; + const ITD = 1 << 7; + const SED = 1 << 8; + const UMA = 1 << 9; + const EnRCTX = 1 << 10; + const EOS = 1 << 11; + const I = 1 << 12; + const EnDB = 1 << 13; + const DZE = 1 << 14; + const UCT = 1 << 15; + const nTWI = 1 << 16; + + // RESERVE + + const nTWE = 1 << 18; + const WXN = 1 << 19; + const TSCXT = 1 << 20; + const IESB = 1 << 21; + const EIS = 1 << 22; + const SPAN = 1 << 23; + const EOE = 1 << 24; + const EE = 1 << 25; + const UCI = 1 << 26; + const EnDA = 1 << 27; + const nTLSMD = 1 << 28; + const LSMAOE = 1 << 29; + const EnIB = 1 << 30; + const EnIA = 1 << 31; + + // RESERVE + + const BT0 = 1 << 35; + const BT1 = 1 << 36; + const ITFSB = 1 << 37; + const TCF0 = 1 << 38 | 1 << 39; + const TCF = 1 << 40 | 1 << 41; + const ATA0 = 1 << 42; + const ATA = 1 << 43; + const DSSBS = 1 << 44; + const TWEDEn = 1 << 45; + const TWEDEL = 1 << 46 | 1 << 47 | 1 << 48 | 1 << 49; + + // RESERVE + + const EnASR = 1 << 54; + const EnAS0 = 1 << 55; + const EnALS = 1 << 56; + const EPAN = 1 << 57; + + // RESERVE + } +} diff --git a/crates/vm-aarch64/src/register/tcr_el1.rs b/crates/vm-aarch64/src/register/tcr_el1.rs new file mode 100644 index 0000000..abaf77a --- /dev/null +++ b/crates/vm-aarch64/src/register/tcr_el1.rs @@ -0,0 +1,28 @@ +use crate::get_field; +use crate::get_field_bit; + +pub struct TcrEl1(u64); + +impl From for TcrEl1 { + fn from(v: u64) -> Self { + TcrEl1(v) + } +} + +impl TcrEl1 { + pub fn ds(&self) -> bool { + get_field_bit!(self.0, 59) + } + + pub fn ips(&self) -> u8 { + get_field!(self.0, 34, 32) as u8 + } + + pub fn tg1(&self) -> u8 { + get_field!(self.0, 31, 30) as u8 + } + + pub fn t1sz(&self) -> u8 { + get_field!(self.0, 21, 16) as u8 + } +} diff --git a/crates/vm-aarch64/src/register/ttbr1_el1.rs b/crates/vm-aarch64/src/register/ttbr1_el1.rs new file mode 100644 index 0000000..4590709 --- /dev/null +++ b/crates/vm-aarch64/src/register/ttbr1_el1.rs @@ -0,0 +1,15 @@ +use crate::get_field; + +pub struct Ttbr1El1(u64); + +impl From for Ttbr1El1 { + fn from(value: u64) -> Self { + Ttbr1El1(value) + } +} + +impl Ttbr1El1 { + pub fn baddr(&self) -> u64 { + get_field!(self.0, 47, 0) + } +} diff --git a/crates/vm-core/Cargo.toml b/crates/vm-core/Cargo.toml index 2a5d608..142e11c 100644 --- a/crates/vm-core/Cargo.toml +++ b/crates/vm-core/Cargo.toml @@ -18,10 +18,12 @@ tokio = { workspace = true } vm-fdt = { workspace = true } [target.'cfg(target_arch = "aarch64")'.dependencies] +vm-aarch64 = { workspace = true } futures = { workspace = true } static_assertions = { workspace = true } strum_macros = { workspace = true } tracing = { workspace = true } +vm-mm = { workspace = true } [features] kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"] diff --git a/crates/vm-core/src/arch.rs b/crates/vm-core/src/arch.rs index d9770fc..00bd7a0 100644 --- a/crates/vm-core/src/arch.rs +++ b/crates/vm-core/src/arch.rs @@ -6,4 +6,5 @@ pub mod x86_64; pub mod irq; pub mod layout; +pub mod mmu; pub mod registers; diff --git a/crates/vm-core/src/arch/aarch64/vcpu.rs b/crates/vm-core/src/arch/aarch64/vcpu.rs index 86e6c22..9e222b4 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu.rs @@ -1,8 +1,9 @@ +use vm_aarch64::register::cnthctl_el2::CnthctlEl2; +use vm_aarch64::register::sctlr_el1::SctlrEl1; + use crate::arch::aarch64::vcpu::reg::CoreRegister; use crate::arch::aarch64::vcpu::reg::FpRegister; use crate::arch::aarch64::vcpu::reg::SysRegister; -use crate::arch::aarch64::vcpu::reg::cnthctl_el2::CnthctlEl2; -use crate::arch::aarch64::vcpu::reg::sctlr_el1::SctlrEl1; use crate::arch::registers::aarch64::AArch64CoreRegisters; use crate::arch::registers::aarch64::AArch64Registers; use crate::arch::registers::aarch64::AArch64SysRegisters; diff --git a/crates/vm-core/src/arch/aarch64/vcpu/reg.rs b/crates/vm-core/src/arch/aarch64/vcpu/reg.rs index f2b0643..3a6f783 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu/reg.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu/reg.rs @@ -170,92 +170,3 @@ impl SysRegister { // } // } // } - -pub mod sctlr_el1 { - use bitflags::bitflags; - - bitflags! { - pub struct SctlrEl1: u64 { - const M = 1 << 0; - const A = 1 << 1; - const C = 1 << 2; - const SA = 1 << 3; - const SA0 = 1 << 4; - const CP15BEN = 1 << 5; - const nAA = 1 << 6; - const ITD = 1 << 7; - const SED = 1 << 8; - const UMA = 1 << 9; - const EnRCTX = 1 << 10; - const EOS = 1 << 11; - const I = 1 << 12; - const EnDB = 1 << 13; - const DZE = 1 << 14; - const UCT = 1 << 15; - const nTWI = 1 << 16; - - // RESERVE - - const nTWE = 1 << 18; - const WXN = 1 << 19; - const TSCXT = 1 << 20; - const IESB = 1 << 21; - const EIS = 1 << 22; - const SPAN = 1 << 23; - const EOE = 1 << 24; - const EE = 1 << 25; - const UCI = 1 << 26; - const EnDA = 1 << 27; - const nTLSMD = 1 << 28; - const LSMAOE = 1 << 29; - const EnIB = 1 << 30; - const EnIA = 1 << 31; - - // RESERVE - - const BT0 = 1 << 35; - const BT1 = 1 << 36; - const ITFSB = 1 << 37; - const TCF0 = 1 << 38 | 1 << 39; - const TCF = 1 << 40 | 1 << 41; - const ATA0 = 1 << 42; - const ATA = 1 << 43; - const DSSBS = 1 << 44; - const TWEDEn = 1 << 45; - const TWEDEL = 1 << 46 | 1 << 47 | 1 << 48 | 1 << 49; - - // RESERVE - - const EnASR = 1 << 54; - const EnAS0 = 1 << 55; - const EnALS = 1 << 56; - const EPAN = 1 << 57; - - // RESERVE - } - } -} - -pub mod cnthctl_el2 { - use bitflags::bitflags; - - bitflags! { - pub struct CnthctlEl2: u64 { - const EL0PCTEN = 1 << 0; - const EL0VCTEN = 1 << 1; - const EVNTEN = 1 << 2; - const EVNTDIR = 1 << 3; - const EVNTI = 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7; - const EL0VTEN = 1 << 8; - const EL0PTEN = 1 << 9; - const EL1PCTEN = 1 << 10; - const EL1PTEN = 1 << 11; - const ECV = 1 << 12; - const EL1TVT = 1 << 13; - const EL1TVCT = 1 << 14; - const EL1NVPCT = 1 << 15; - const EL1NVVCT = 1 << 16; - const EVNTIS = 1 << 17; - } - } -} diff --git a/crates/vm-core/src/arch/mmu.rs b/crates/vm-core/src/arch/mmu.rs new file mode 100644 index 0000000..0690543 --- /dev/null +++ b/crates/vm-core/src/arch/mmu.rs @@ -0,0 +1,2 @@ +#[cfg(target_arch = "aarch64")] +pub mod aarch64; diff --git a/crates/vm-core/src/arch/mmu/aarch64.rs b/crates/vm-core/src/arch/mmu/aarch64.rs new file mode 100644 index 0000000..de9f727 --- /dev/null +++ b/crates/vm-core/src/arch/mmu/aarch64.rs @@ -0,0 +1,137 @@ +use std::u64; + +use vm_aarch64::register::id_aa64mmfr0_el1::IdAa64mmfr0El1; +use vm_aarch64::register::tcr_el1::TcrEl1; +use vm_aarch64::register::ttbr1_el1::Ttbr1El1; +use vm_mm::manager::MemoryAddressSpace; + +use crate::cpu::error::VcpuError; + +fn walk( + mm: &MemoryAddressSpace, + gva: u64, + index_of_gva: impl Fn(usize) -> u64, + granule_size_bits: u8, + descriptor_addr_mask: u64, + baddr: u64, + current_level: usize, + maximal_level: usize, +) -> Result { + assert!(current_level < maximal_level); + + let index = index_of_gva(current_level); + let descriptor_addr = (baddr | (index << granule_size_bits)) & !0b11; + + let descriptor; + { + let mut buf = [0; 8]; + for (offset, b) in buf.iter_mut().enumerate() { + let hva = mm + .gpa_to_hva(descriptor_addr + offset as u64) + .map_err(|_| VcpuError::TranslateErr)?; + *b = unsafe { *hva }; + } + descriptor = u64::from_le_bytes(buf); + } + + let next_addr = descriptor & descriptor_addr_mask; + + if (descriptor & 0b11) == 0b11 && current_level != 3 { + // table descriptor + + walk( + mm, + gva, + index_of_gva, + granule_size_bits, + descriptor_addr_mask, + next_addr, + current_level + 1, + maximal_level, + ) + } else { + // block descriptor or page descriptor + + let page_or_block_size = + 1 << ((granule_size_bits - 3) as u64 * (maximal_level - current_level) as u64 + 3); + + let mut gpa = next_addr; + gpa &= !(page_or_block_size - 1); // Mask flags + gpa |= gva & (page_or_block_size - 1); + Ok(gpa) + } +} + +pub fn translate_gva_to_gpa( + mm: &MemoryAddressSpace, + tcr_el1: impl FnOnce() -> TcrEl1, + ttbr1_el1: impl FnOnce() -> Ttbr1El1, + id_aa64mmfr0_el1: impl FnOnce() -> IdAa64mmfr0El1, + gva: u64, +) -> Result { + let tcr_el1 = tcr_el1(); + let ttbr1_el1 = ttbr1_el1(); + let id_aa64mmfr0_el1 = id_aa64mmfr0_el1(); + + let t1sz = tcr_el1.t1sz(); + let va_size = 64 - t1sz; + let tg1 = tcr_el1.tg1(); + + let ds = tcr_el1.ds(); + + let ips = tcr_el1.ips(); + let pa_range = id_aa64mmfr0_el1.pa_range(); + assert_eq!(ips, pa_range); + + let pa_range = match pa_range { + 0b0000 => 32, + 0b0001 => 36, + 0b0010 => 40, + 0b0011 => 42, + 0b0100 => 44, + 0b0101 => 48, + 0b0110 => 52, + 0b0111 => 56, + _ => return Err(VcpuError::TranslateErr), + }; + + let granule_size_bits = match tg1 { + 0b01 => 14, // 16KB + 0b10 => 12, // 4KB + 0b11 => 16, // 64KB + _ => return Err(VcpuError::TranslateErr), + }; + let index_bits = granule_size_bits - 3; + let index_mask = (1 << index_bits) - 1; + + let descriptor_addr_mask = if ds { + u64::MAX >> (64 - 50) + } else { + u64::MAX >> (64 - 48) + } & !(u64::MAX >> (64 - granule_size_bits)); + + let baddr = ttbr1_el1.baddr(); + // If FEAT_LPA is implemented and the value of TCR_EL1.IPS is 0b110, then: + if pa_range == 52 { + // ttbr_baddr |= ((ttbr >> 2) & 0b1111) >> 48; + todo!() + } + + let level = 4 - (va_size - 4) / index_bits; + + let index_of_gva = |level: usize| { + let skip_level = 4 - 1 - level; + ((gva >> granule_size_bits) >> (index_bits as u64 * skip_level as u64)) & index_mask + }; + + walk( + mm, + gva, + index_of_gva, + granule_size_bits, + descriptor_addr_mask, + baddr, + level as usize, + 4, + ) +} diff --git a/crates/vm-core/src/arch/registers/aarch64.rs b/crates/vm-core/src/arch/registers/aarch64.rs index 0e3a6d7..8e302fc 100644 --- a/crates/vm-core/src/arch/registers/aarch64.rs +++ b/crates/vm-core/src/arch/registers/aarch64.rs @@ -1,7 +1,6 @@ use gdbstub_arch::aarch64::reg::AArch64CoreRegs; - -use crate::arch::aarch64::vcpu::reg::cnthctl_el2::CnthctlEl2; -use crate::arch::aarch64::vcpu::reg::sctlr_el1::SctlrEl1; +use vm_aarch64::register::cnthctl_el2::CnthctlEl2; +use vm_aarch64::register::sctlr_el1::SctlrEl1; pub struct AArch64CoreRegisters { pub general_purpose: [u64; 31], diff --git a/crates/vm-core/src/cpu/error.rs b/crates/vm-core/src/cpu/error.rs index 67f1bb8..3bcbe2c 100644 --- a/crates/vm-core/src/cpu/error.rs +++ b/crates/vm-core/src/cpu/error.rs @@ -26,4 +26,7 @@ pub enum VcpuError { #[error("{0}")] VmExitHandlerErr(#[from] VmExitHandlerError), + + #[error("Failed to translate va to pa")] + TranslateErr, } diff --git a/crates/vm-core/src/utils.rs b/crates/vm-core/src/utils.rs index f2763a0..51c42fc 100644 --- a/crates/vm-core/src/utils.rs +++ b/crates/vm-core/src/utils.rs @@ -1 +1,2 @@ pub mod address_space; +pub mod bits; diff --git a/crates/vm-core/src/utils/bits.rs b/crates/vm-core/src/utils/bits.rs new file mode 100644 index 0000000..bb55672 --- /dev/null +++ b/crates/vm-core/src/utils/bits.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! get_field { + ($v:expr, $hi:expr, $lo:expr) => { + (($v >> $lo) & ((1u64 << ($hi - $lo + 1)) - 1)) + }; +} From 69f869c9f06cb356422cf0d17905e6451044f629 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 00:18:24 +0800 Subject: [PATCH 2/6] feat: Impl translate for hvp --- .../src/register/id_aa64mmfr0_el1.rs | 8 ++++- crates/vm-aarch64/src/register/tcr_el1.rs | 2 +- crates/vm-aarch64/src/register/ttbr1_el1.rs | 2 +- crates/vm-core/src/arch/aarch64/vcpu.rs | 2 +- crates/vm-core/src/arch/aarch64/vcpu/reg.rs | 3 ++ crates/vm-core/src/arch/mmu/aarch64.rs | 21 +++++++++---- crates/vm-core/src/cpu/vcpu_manager.rs | 5 ++- crates/vm-core/src/virtualization/hvp/vcpu.rs | 27 +++++++++++++--- .../src/virtualization/hvp/vcpu/register.rs | 3 ++ crates/vm-core/src/virtualization/hvp/vm.rs | 4 ++- crates/vm-core/src/virtualization/vm.rs | 2 ++ crates/vm-vmm/src/service/gdbstub/command.rs | 2 ++ crates/vm-vmm/src/service/gdbstub/target.rs | 3 ++ crates/vm-vmm/src/vm.rs | 14 +++++++-- crates/vm-vmm/src/vmm/command.rs | 31 +++++++++++++++---- 15 files changed, 103 insertions(+), 26 deletions(-) diff --git a/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs b/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs index bc82924..9063a0c 100644 --- a/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs +++ b/crates/vm-aarch64/src/register/id_aa64mmfr0_el1.rs @@ -1,6 +1,12 @@ use crate::get_field; -pub struct IdAa64mmfr0El1(u64); +pub struct IdAa64mmfr0El1(pub u64); + +impl From for IdAa64mmfr0El1 { + fn from(value: u64) -> Self { + IdAa64mmfr0El1(value) + } +} impl IdAa64mmfr0El1 { pub fn pa_range(&self) -> u8 { diff --git a/crates/vm-aarch64/src/register/tcr_el1.rs b/crates/vm-aarch64/src/register/tcr_el1.rs index abaf77a..17a9855 100644 --- a/crates/vm-aarch64/src/register/tcr_el1.rs +++ b/crates/vm-aarch64/src/register/tcr_el1.rs @@ -1,7 +1,7 @@ use crate::get_field; use crate::get_field_bit; -pub struct TcrEl1(u64); +pub struct TcrEl1(pub u64); impl From for TcrEl1 { fn from(v: u64) -> Self { diff --git a/crates/vm-aarch64/src/register/ttbr1_el1.rs b/crates/vm-aarch64/src/register/ttbr1_el1.rs index 4590709..5d735db 100644 --- a/crates/vm-aarch64/src/register/ttbr1_el1.rs +++ b/crates/vm-aarch64/src/register/ttbr1_el1.rs @@ -1,6 +1,6 @@ use crate::get_field; -pub struct Ttbr1El1(u64); +pub struct Ttbr1El1(pub u64); impl From for Ttbr1El1 { fn from(value: u64) -> Self { diff --git a/crates/vm-core/src/arch/aarch64/vcpu.rs b/crates/vm-core/src/arch/aarch64/vcpu.rs index 9e222b4..3f02557 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu.rs @@ -32,7 +32,7 @@ pub trait AArch64Vcpu { fn set_fp_reg(&mut self, reg: FpRegister, value: u128) -> Result<(), VcpuError>; - fn get_sys_reg(&mut self, reg: SysRegister) -> Result; + fn get_sys_reg(&self, reg: SysRegister) -> Result; fn set_sys_reg(&mut self, reg: SysRegister, value: u64) -> Result<(), VcpuError>; diff --git a/crates/vm-core/src/arch/aarch64/vcpu/reg.rs b/crates/vm-core/src/arch/aarch64/vcpu/reg.rs index 3a6f783..4508c9b 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu/reg.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu/reg.rs @@ -125,6 +125,9 @@ pub enum SysRegister { OslarEl1, OslsrEl1, OsdlrEl1, + TcrEl1, + Ttbr1El1, + IdAa64mmfr0El1, } impl SysRegister { diff --git a/crates/vm-core/src/arch/mmu/aarch64.rs b/crates/vm-core/src/arch/mmu/aarch64.rs index de9f727..a754aed 100644 --- a/crates/vm-core/src/arch/mmu/aarch64.rs +++ b/crates/vm-core/src/arch/mmu/aarch64.rs @@ -64,14 +64,23 @@ fn walk( pub fn translate_gva_to_gpa( mm: &MemoryAddressSpace, - tcr_el1: impl FnOnce() -> TcrEl1, - ttbr1_el1: impl FnOnce() -> Ttbr1El1, - id_aa64mmfr0_el1: impl FnOnce() -> IdAa64mmfr0El1, + tcr_el1: impl FnOnce() -> Result, + ttbr1_el1: impl FnOnce() -> Result, + id_aa64mmfr0_el1: impl FnOnce() -> Result, gva: u64, ) -> Result { - let tcr_el1 = tcr_el1(); - let ttbr1_el1 = ttbr1_el1(); - let id_aa64mmfr0_el1 = id_aa64mmfr0_el1(); + let tcr_el1 = tcr_el1()?; + let ttbr1_el1 = ttbr1_el1()?; + let id_aa64mmfr0_el1 = id_aa64mmfr0_el1()?; + + if ttbr1_el1.0 == 0 { + return Err(VcpuError::TranslateErr); + } + + // println!( + // "tcr_el1: {:x} ttbr1_el1: {:x}, id_aa64mmfr0_el1: {:x}", + // tcr_el1.0, ttbr1_el1.0, id_aa64mmfr0_el1.0 + // ); let t1sz = tcr_el1.t1sz(); let va_size = 64 - t1sz; diff --git a/crates/vm-core/src/cpu/vcpu_manager.rs b/crates/vm-core/src/cpu/vcpu_manager.rs index 063c961..6e4cf44 100644 --- a/crates/vm-core/src/cpu/vcpu_manager.rs +++ b/crates/vm-core/src/cpu/vcpu_manager.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use vm_mm::manager::MemoryAddressSpace; + use crate::cpu::error::VcpuError; use crate::cpu::vcpu::Vcpu; use crate::cpu::vm_exit::VmExit; @@ -38,9 +40,10 @@ impl VcpuManager { pub fn create_vcpu( &mut self, vcpu_id: usize, + mm: Arc, vm_exit_handler: Arc, ) -> Result<(), VmError> { - let vcpu_instance = self.vm_instance.create_vcpu(vcpu_id, vm_exit_handler)?; + let vcpu_instance = self.vm_instance.create_vcpu(vcpu_id, mm, vm_exit_handler)?; let vcpu = Vcpu::new(vcpu_id, vcpu_instance); diff --git a/crates/vm-core/src/virtualization/hvp/vcpu.rs b/crates/vm-core/src/virtualization/hvp/vcpu.rs index c7f9b4a..5a9589a 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu.rs @@ -18,6 +18,10 @@ use applevisor_sys::hv_vcpu_set_sys_reg; use applevisor_sys::hv_vcpu_t; use applevisor_sys::hv_vcpus_exit; use async_trait::async_trait; +use vm_aarch64::register::id_aa64mmfr0_el1::IdAa64mmfr0El1; +use vm_aarch64::register::tcr_el1::TcrEl1; +use vm_aarch64::register::ttbr1_el1::Ttbr1El1; +use vm_mm::manager::MemoryAddressSpace; use crate::arch::aarch64::vcpu::AArch64Vcpu; use crate::arch::aarch64::vcpu::reg::CoreRegister; @@ -25,6 +29,7 @@ use crate::arch::aarch64::vcpu::reg::FpRegister; use crate::arch::aarch64::vcpu::reg::SysRegister; use crate::arch::aarch64::vm_exit::HandleVmExitResult; use crate::arch::aarch64::vm_exit::handle_vm_exit; +use crate::arch::mmu::aarch64::translate_gva_to_gpa; use crate::arch::registers::aarch64::AArch64CoreRegisters; use crate::arch::registers::aarch64::AArch64Registers; use crate::arch::registers::aarch64::AArch64SysRegisters; @@ -44,6 +49,7 @@ mod vm_exit; struct HvpVcpuInternal { /// handler for apple hypervisor vcpu vcpu: hv_vcpu_t, + mm: Arc, } impl AArch64Vcpu for HvpVcpuInternal { @@ -156,7 +162,7 @@ impl AArch64Vcpu for HvpVcpuInternal { Ok(()) } - fn get_sys_reg(&mut self, reg: SysRegister) -> Result { + fn get_sys_reg(&self, reg: SysRegister) -> Result { let mut value = 0; hv_unsafe_call!(hv_vcpu_get_sys_reg(self.vcpu, reg.into(), &mut value))?; @@ -168,8 +174,15 @@ impl AArch64Vcpu for HvpVcpuInternal { hv_unsafe_call!(hv_vcpu_set_sys_reg(self.vcpu, reg.into(), value)).map_err(Into::into) } - fn translate_gva_to_gpa(&self, _gva: u64) -> Result { - todo!() + fn translate_gva_to_gpa(&self, gva: u64) -> Result { + let tcr_el1 = || Ok(TcrEl1::from(self.get_sys_reg(SysRegister::TcrEl1)?)); + let ttbr1_el1 = || Ok(Ttbr1El1::from(self.get_sys_reg(SysRegister::Ttbr1El1)?)); + let id_aa64mmfr0_el1 = || { + Ok(IdAa64mmfr0El1::from( + self.get_sys_reg(SysRegister::IdAa64mmfr0El1)?, + )) + }; + translate_gva_to_gpa(&self.mm, tcr_el1, ttbr1_el1, id_aa64mmfr0_el1, gva) } } @@ -180,7 +193,11 @@ pub struct HvpVcpu { } impl HvpVcpu { - pub fn new(vcpu_id: usize, vm_exit_handler: Arc) -> Result { + pub fn new( + vcpu_id: usize, + mm: Arc, + vm_exit_handler: Arc, + ) -> Result { let (handler_tx, handler_rx) = mpsc::channel(); let (command_tx, command_rx) = mpsc::channel(); @@ -189,7 +206,7 @@ impl HvpVcpu { let mut exit = null_mut() as *const hv_vcpu_exit_t; hv_unsafe_call!(hv_vcpu_create(&mut vcpu, &mut exit, null_mut()))?; - let hvp_vcpu_handler = Arc::new(Mutex::new(HvpVcpuInternal { vcpu })); + let hvp_vcpu_handler = Arc::new(Mutex::new(HvpVcpuInternal { vcpu, mm })); handler_tx.send(hvp_vcpu_handler.clone()).unwrap(); diff --git a/crates/vm-core/src/virtualization/hvp/vcpu/register.rs b/crates/vm-core/src/virtualization/hvp/vcpu/register.rs index 40e3bc6..dfc627e 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu/register.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu/register.rs @@ -106,6 +106,9 @@ impl From for hv_sys_reg_t { SysRegister::OslarEl1 => todo!(), SysRegister::OslsrEl1 => todo!(), SysRegister::OsdlrEl1 => todo!(), + SysRegister::TcrEl1 => hv_sys_reg_t::TCR_EL1, + SysRegister::Ttbr1El1 => hv_sys_reg_t::TTBR1_EL1, + SysRegister::IdAa64mmfr0El1 => hv_sys_reg_t::ID_AA64MMFR0_EL1, } } } diff --git a/crates/vm-core/src/virtualization/hvp/vm.rs b/crates/vm-core/src/virtualization/hvp/vm.rs index c29fc79..e08b97c 100644 --- a/crates/vm-core/src/virtualization/hvp/vm.rs +++ b/crates/vm-core/src/virtualization/hvp/vm.rs @@ -11,6 +11,7 @@ use applevisor_sys::hv_gic_config_set_redistributor_base; use applevisor_sys::hv_gic_config_t; use applevisor_sys::hv_gic_create; use applevisor_sys::hv_vm_map; +use vm_mm::manager::MemoryAddressSpace; use crate::arch::aarch64::layout::GIC_DISTRIBUTOR; use crate::arch::aarch64::layout::GIC_MSI; @@ -41,9 +42,10 @@ impl HypervisorVm for AppleHypervisorVm { fn create_vcpu( &self, vcpu_id: usize, + mm: Arc, vm_exit_handler: Arc, ) -> Result, VmError> { - let vcpu = Box::new(HvpVcpu::new(vcpu_id, vm_exit_handler)?); + let vcpu = Box::new(HvpVcpu::new(vcpu_id, mm, vm_exit_handler)?); Ok(vcpu as _) } diff --git a/crates/vm-core/src/virtualization/vm.rs b/crates/vm-core/src/virtualization/vm.rs index bdc5057..5efe973 100644 --- a/crates/vm-core/src/virtualization/vm.rs +++ b/crates/vm-core/src/virtualization/vm.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use thiserror::Error; +use vm_mm::manager::MemoryAddressSpace; use crate::arch::irq::InterruptController; use crate::cpu::error::VcpuError; @@ -34,6 +35,7 @@ pub trait HypervisorVm: Send + Sync { fn create_vcpu( &self, vcpu_id: usize, + mm: Arc, vm_exit_handler: Arc, ) -> Result, VmError>; diff --git a/crates/vm-vmm/src/service/gdbstub/command.rs b/crates/vm-vmm/src/service/gdbstub/command.rs index 5c363a1..0beb67f 100644 --- a/crates/vm-vmm/src/service/gdbstub/command.rs +++ b/crates/vm-vmm/src/service/gdbstub/command.rs @@ -48,6 +48,8 @@ pub enum GdbStubCommandResponse { ListActiveThreads(usize), Resume, + + Err, } #[derive(Error, Debug)] diff --git a/crates/vm-vmm/src/service/gdbstub/target.rs b/crates/vm-vmm/src/service/gdbstub/target.rs index c172ad5..ad75dd4 100644 --- a/crates/vm-vmm/src/service/gdbstub/target.rs +++ b/crates/vm-vmm/src/service/gdbstub/target.rs @@ -114,6 +114,9 @@ impl MultiThreadBase for VmGdbStubTarget { data[..buf.len()].copy_from_slice(&buf); Ok(data.len()) } + Ok(GdbStubCommandResponse::Err) => { + return Err(TargetError::NonFatal); + } Ok(_) => { error!("Unexpected response to ReadAddrs command"); Err(TargetError::NonFatal) diff --git a/crates/vm-vmm/src/vm.rs b/crates/vm-vmm/src/vm.rs index cfb20b8..a50d66e 100644 --- a/crates/vm-vmm/src/vm.rs +++ b/crates/vm-vmm/src/vm.rs @@ -53,7 +53,7 @@ const PAGE_SIZE: usize = 4 << 10; pub struct Vm { _vm_instance: Arc, vcpu_manager: Arc>, - _memory_address_space: Arc, + memory_address_space: Arc, _irq_chip: Arc, _device_manager: Arc, gdb_stub: Option, @@ -122,7 +122,11 @@ impl Vm { let mut vcpu_manager = vcpu_manager.lock().await; for vcpu_id in 0..vm_config.vcpus { - vcpu_manager.create_vcpu(vcpu_id, vm_exit_handler.clone())?; + vcpu_manager.create_vcpu( + vcpu_id, + memory_address_space.clone(), + vm_exit_handler.clone(), + )?; } } @@ -152,7 +156,7 @@ impl Vm { let vm = Vm { _vm_instance: vm_instance, vcpu_manager, - _memory_address_space: memory_address_space, + memory_address_space, _irq_chip: irq_chip, _device_manager: device_manager, gdb_stub: vm_config @@ -171,6 +175,10 @@ impl Vm { self.vcpu_manager.clone() } + pub fn memory_address_space(&self) -> &MemoryAddressSpace { + self.memory_address_space.as_ref() + } + pub async fn boot(&mut self) -> Result<()> { let mut stop_on_boot = false; diff --git a/crates/vm-vmm/src/vmm/command.rs b/crates/vm-vmm/src/vmm/command.rs index acb3fc2..3e4c16b 100644 --- a/crates/vm-vmm/src/vmm/command.rs +++ b/crates/vm-vmm/src/vmm/command.rs @@ -47,17 +47,21 @@ impl Vmm { ) -> Result { match cmd { GdbStubCommand::ReadRegisters { vcpu_id } => { + trace!(vcpu_id, "ReadRegisters"); + let vcpu_manager = self.try_get_vm()?.vcpu_manager(); let mut vcpu_manager = vcpu_manager.lock().await; let vcpu = vcpu_manager.get_vcpu_mut(vcpu_id)?; - let registers = vcpu.read_core_registers().await?; + let registers = vcpu.read_core_registers().await.unwrap(); Ok(GdbStubCommandResponse::ReadRegisters { registers: Box::new(registers.into()), }) } GdbStubCommand::WriteRegisters { vcpu_id, registers } => { + trace!(vcpu_id, "WriteRegisters"); + let vcpu_manager = self.try_get_vm_mut()?.vcpu_manager(); let mut vcpu_manager = vcpu_manager.lock().await; let vcpu = vcpu_manager.get_vcpu_mut(vcpu_id)?; @@ -72,11 +76,22 @@ impl Vmm { let vm = self.try_get_vm_mut()?; let vcpu_manager = vm.vcpu_manager(); let vcpu_manager = vcpu_manager.lock().await; - let _vcpu = vcpu_manager.get_vcpu(vcpu_id)?; - - let _buf = todo!(); - - // Ok(GdbStubCommandResponse::ReadAddrs { buf }) + let vcpu = vcpu_manager.get_vcpu(vcpu_id)?; + + let mut len = len; + let mut buf = Vec::with_capacity(len); + while len > 0 { + let gpa = match vcpu.translate_gva_to_gpa(gva).await { + Ok(gpa) => gpa, + Err(_err) => return Ok(GdbStubCommandResponse::Err), + }; + let hva = vm.memory_address_space().gpa_to_hva(gpa).unwrap(); + buf.push(unsafe { *hva }); + // TODO: Opt + len -= 1; + } + + Ok(GdbStubCommandResponse::ReadAddrs { buf }) } GdbStubCommand::WriteAddrs { gva, data, vcpu_id } => { trace!(gva, len = data.len(), vcpu_id, "WriteAddrs"); @@ -91,11 +106,15 @@ impl Vmm { // Ok(GdbStubCommandResponse::WriteAddrs) } GdbStubCommand::ListActiveThreads => { + trace!("ListActiveThreads"); + let vm = self.try_get_vm()?; let vcpu = vm.vcpu_manager().lock().await.get_active_vcpus(); Ok(GdbStubCommandResponse::ListActiveThreads(vcpu)) } GdbStubCommand::Resume => { + trace!("Resume"); + let vm = self.try_get_vm_mut()?; vm.resume().await?; Ok(GdbStubCommandResponse::Resume) From 8eca2d511405c4869b37575425b20ebcdb0c8d2f Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 00:19:24 +0800 Subject: [PATCH 3/6] fix: Fix attribute --- crates/vm-aarch64/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/vm-aarch64/src/lib.rs b/crates/vm-aarch64/src/lib.rs index 31ad066..21394c7 100644 --- a/crates/vm-aarch64/src/lib.rs +++ b/crates/vm-aarch64/src/lib.rs @@ -1,4 +1,5 @@ -#[deny(warnings)] +#![deny(warnings)] + pub mod register; #[macro_export] From 8b7e002e59cfcd8b1c542b3823083180a8aabeb5 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 00:23:02 +0800 Subject: [PATCH 4/6] fix: Fix compiling errors --- crates/vm-core/Cargo.toml | 2 +- crates/vm-core/src/arch/mmu/aarch64.rs | 2 -- crates/vm-vmm/src/service/gdbstub/target.rs | 4 +--- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/vm-core/Cargo.toml b/crates/vm-core/Cargo.toml index 142e11c..19a9a52 100644 --- a/crates/vm-core/Cargo.toml +++ b/crates/vm-core/Cargo.toml @@ -16,6 +16,7 @@ serde_json = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } vm-fdt = { workspace = true } +vm-mm = { workspace = true } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-aarch64 = { workspace = true } @@ -23,7 +24,6 @@ futures = { workspace = true } static_assertions = { workspace = true } strum_macros = { workspace = true } tracing = { workspace = true } -vm-mm = { workspace = true } [features] kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"] diff --git a/crates/vm-core/src/arch/mmu/aarch64.rs b/crates/vm-core/src/arch/mmu/aarch64.rs index a754aed..31280b6 100644 --- a/crates/vm-core/src/arch/mmu/aarch64.rs +++ b/crates/vm-core/src/arch/mmu/aarch64.rs @@ -1,5 +1,3 @@ -use std::u64; - use vm_aarch64::register::id_aa64mmfr0_el1::IdAa64mmfr0El1; use vm_aarch64::register::tcr_el1::TcrEl1; use vm_aarch64::register::ttbr1_el1::Ttbr1El1; diff --git a/crates/vm-vmm/src/service/gdbstub/target.rs b/crates/vm-vmm/src/service/gdbstub/target.rs index ad75dd4..01512bd 100644 --- a/crates/vm-vmm/src/service/gdbstub/target.rs +++ b/crates/vm-vmm/src/service/gdbstub/target.rs @@ -114,9 +114,7 @@ impl MultiThreadBase for VmGdbStubTarget { data[..buf.len()].copy_from_slice(&buf); Ok(data.len()) } - Ok(GdbStubCommandResponse::Err) => { - return Err(TargetError::NonFatal); - } + Ok(GdbStubCommandResponse::Err) => Err(TargetError::NonFatal), Ok(_) => { error!("Unexpected response to ReadAddrs command"); Err(TargetError::NonFatal) From 83df7398f2ac5e96d67b2602a6fdb7977ed6f024 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 11:33:03 +0800 Subject: [PATCH 5/6] fix: Fix translate err --- crates/vm-core/src/arch/aarch64/vcpu.rs | 2 +- crates/vm-core/src/arch/mmu/aarch64.rs | 10 ++++++---- crates/vm-core/src/cpu/vcpu.rs | 2 +- crates/vm-core/src/virtualization/hvp/vcpu.rs | 4 ++-- crates/vm-core/src/virtualization/vcpu.rs | 2 +- crates/vm-core/src/virtualization/vcpu/command.rs | 2 +- crates/vm-vmm/src/vmm/command.rs | 6 +++--- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/crates/vm-core/src/arch/aarch64/vcpu.rs b/crates/vm-core/src/arch/aarch64/vcpu.rs index 3f02557..c14a8e7 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu.rs @@ -87,5 +87,5 @@ pub trait AArch64Vcpu { Ok(()) } - fn translate_gva_to_gpa(&self, gva: u64) -> Result; + fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError>; } diff --git a/crates/vm-core/src/arch/mmu/aarch64.rs b/crates/vm-core/src/arch/mmu/aarch64.rs index 31280b6..1b84af2 100644 --- a/crates/vm-core/src/arch/mmu/aarch64.rs +++ b/crates/vm-core/src/arch/mmu/aarch64.rs @@ -66,13 +66,13 @@ pub fn translate_gva_to_gpa( ttbr1_el1: impl FnOnce() -> Result, id_aa64mmfr0_el1: impl FnOnce() -> Result, gva: u64, -) -> Result { +) -> Result, VcpuError> { let tcr_el1 = tcr_el1()?; let ttbr1_el1 = ttbr1_el1()?; let id_aa64mmfr0_el1 = id_aa64mmfr0_el1()?; if ttbr1_el1.0 == 0 { - return Err(VcpuError::TranslateErr); + return Ok(None); } // println!( @@ -131,7 +131,7 @@ pub fn translate_gva_to_gpa( ((gva >> granule_size_bits) >> (index_bits as u64 * skip_level as u64)) & index_mask }; - walk( + let gpa = walk( mm, gva, index_of_gva, @@ -140,5 +140,7 @@ pub fn translate_gva_to_gpa( baddr, level as usize, 4, - ) + )?; + + Ok(Some(gpa)) } diff --git a/crates/vm-core/src/cpu/vcpu.rs b/crates/vm-core/src/cpu/vcpu.rs index 68e8ff2..9b6a172 100644 --- a/crates/vm-core/src/cpu/vcpu.rs +++ b/crates/vm-core/src/cpu/vcpu.rs @@ -62,7 +62,7 @@ impl Vcpu { self.vcpu_instance.write_registers(registers).await } - pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result { + pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { self.vcpu_instance.translate_gva_to_gpa(gva).await } diff --git a/crates/vm-core/src/virtualization/hvp/vcpu.rs b/crates/vm-core/src/virtualization/hvp/vcpu.rs index 5a9589a..cf46f5f 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu.rs @@ -174,7 +174,7 @@ impl AArch64Vcpu for HvpVcpuInternal { hv_unsafe_call!(hv_vcpu_set_sys_reg(self.vcpu, reg.into(), value)).map_err(Into::into) } - fn translate_gva_to_gpa(&self, gva: u64) -> Result { + fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { let tcr_el1 = || Ok(TcrEl1::from(self.get_sys_reg(SysRegister::TcrEl1)?)); let ttbr1_el1 = || Ok(Ttbr1El1::from(self.get_sys_reg(SysRegister::Ttbr1El1)?)); let id_aa64mmfr0_el1 = || { @@ -381,7 +381,7 @@ impl HypervisorVcpu for HvpVcpu { Ok(()) } - async fn translate_gva_to_gpa(&self, gva: u64) -> Result { + async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::TranslateGvaToGpa(gva)); self.command_tx diff --git a/crates/vm-core/src/virtualization/vcpu.rs b/crates/vm-core/src/virtualization/vcpu.rs index 70cf929..82a2368 100644 --- a/crates/vm-core/src/virtualization/vcpu.rs +++ b/crates/vm-core/src/virtualization/vcpu.rs @@ -19,7 +19,7 @@ pub trait HypervisorVcpu: Send { async fn write_core_registers(&mut self, registers: ArchCoreRegisters) -> Result<(), VcpuError>; - async fn translate_gva_to_gpa(&self, gva: u64) -> Result; + async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError>; async fn resume(&mut self) -> Result<(), VcpuError>; diff --git a/crates/vm-core/src/virtualization/vcpu/command.rs b/crates/vm-core/src/virtualization/vcpu/command.rs index bb7e0e0..a491082 100644 --- a/crates/vm-core/src/virtualization/vcpu/command.rs +++ b/crates/vm-core/src/virtualization/vcpu/command.rs @@ -17,7 +17,7 @@ pub enum VcpuCommandResponse { Empty, CoreRegisters(Box), Registers(Box), - TranslateGvaToGpa(u64), + TranslateGvaToGpa(Option), } pub struct VcpuCommandRequest { diff --git a/crates/vm-vmm/src/vmm/command.rs b/crates/vm-vmm/src/vmm/command.rs index 3e4c16b..948d64b 100644 --- a/crates/vm-vmm/src/vmm/command.rs +++ b/crates/vm-vmm/src/vmm/command.rs @@ -81,10 +81,10 @@ impl Vmm { let mut len = len; let mut buf = Vec::with_capacity(len); while len > 0 { - let gpa = match vcpu.translate_gva_to_gpa(gva).await { - Ok(gpa) => gpa, - Err(_err) => return Ok(GdbStubCommandResponse::Err), + let Some(gpa) = vcpu.translate_gva_to_gpa(gva).await? else { + return Ok(GdbStubCommandResponse::Err); }; + let hva = vm.memory_address_space().gpa_to_hva(gpa).unwrap(); buf.push(unsafe { *hva }); // TODO: Opt From 777ef3688d8eeeb43ad1489cb10a50e37aa644b8 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 17:18:55 +0800 Subject: [PATCH 6/6] fix: Do nothing in wait_for_stop_reason to avoid panic --- crates/vm-vmm/src/service/gdbstub/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/vm-vmm/src/service/gdbstub/event_loop.rs b/crates/vm-vmm/src/service/gdbstub/event_loop.rs index d4c61c0..c7ce07a 100644 --- a/crates/vm-vmm/src/service/gdbstub/event_loop.rs +++ b/crates/vm-vmm/src/service/gdbstub/event_loop.rs @@ -23,7 +23,7 @@ impl BlockingEventLoop for VmEventLoop { Event::Usize>>, WaitForStopReasonError, > { - todo!() + loop {} } fn on_interrupt(