diff --git a/Cargo.lock b/Cargo.lock index 48b495809..153fd18dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,6 +970,7 @@ version = "0.1.0" dependencies = [ "anyhow", "arc-swap", + "bitfield-struct", "byteorder", "cfg-if", "concat-idents", @@ -983,6 +984,7 @@ dependencies = [ "log", "mshv-bindings", "mshv-ioctls", + "open-enum", "serde", "serde_json", "serde_with", @@ -990,6 +992,7 @@ dependencies = [ "vfio-ioctls", "vm-memory", "vmm-sys-util", + "zerocopy 0.8.24", ] [[package]] diff --git a/hypervisor/Cargo.toml b/hypervisor/Cargo.toml index b4b68bd12..bfb669e1f 100644 --- a/hypervisor/Cargo.toml +++ b/hypervisor/Cargo.toml @@ -15,6 +15,7 @@ tdx = [] [dependencies] anyhow = "1.0.94" arc-swap = "1.7.1" +bitfield-struct = "0.10.1" byteorder = "1.5.0" cfg-if = "1.0.0" concat-idents = "1.1.5" @@ -29,6 +30,7 @@ mshv-bindings = { workspace = true, features = [ "with-serde", ], optional = true } mshv-ioctls = { workspace = true, optional = true } +open-enum = "0.5.2" serde = { version = "1.0.208", features = ["derive", "rc"] } serde_json = { workspace = true } serde_with = { version = "3.9.0", default-features = false, features = [ @@ -42,6 +44,7 @@ vm-memory = { workspace = true, features = [ "backend-mmap", ] } vmm-sys-util = { workspace = true, features = ["with-serde"] } +zerocopy = { version = "0.8.24", features = ["derive"] } [target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86] default-features = false diff --git a/hypervisor/src/arch/aarch64/mod.rs b/hypervisor/src/arch/aarch64/mod.rs index f3a15462d..9d19f44bf 100644 --- a/hypervisor/src/arch/aarch64/mod.rs +++ b/hypervisor/src/arch/aarch64/mod.rs @@ -3,3 +3,4 @@ // SPDX-License-Identifier: Apache-2.0 pub mod gic; +pub mod regs; diff --git a/hypervisor/src/arch/aarch64/regs.rs b/hypervisor/src/arch/aarch64/regs.rs new file mode 100644 index 000000000..0c79e1531 --- /dev/null +++ b/hypervisor/src/arch/aarch64/regs.rs @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause +// +// Copyright © 2025, Microsoft Corporation +// + +use bitfield_struct::bitfield; +use open_enum::open_enum; +use zerocopy::{FromBytes, IntoBytes}; + +/// ESR_EL2, exception syndrome register. +#[bitfield(u64)] +#[derive(IntoBytes, FromBytes)] +pub struct EsrEl2 { + #[bits(25)] + pub iss: u32, + pub il: bool, + #[bits(6)] + pub ec: u8, + #[bits(5)] + pub iss2: u8, + #[bits(27)] + _rsvd: u32, +} + +#[open_enum] +#[derive(Debug)] +#[repr(u8)] +pub enum FaultStatusCode { + ADDRESS_SIZE_FAULT_LEVEL0 = 0b000000, + ADDRESS_SIZE_FAULT_LEVEL1 = 0b000001, + ADDRESS_SIZE_FAULT_LEVEL2 = 0b000010, + ADDRESS_SIZE_FAULT_LEVEL3 = 0b000011, + TRANSLATION_FAULT_LEVEL0 = 0b000100, + TRANSLATION_FAULT_LEVEL1 = 0b000101, + TRANSLATION_FAULT_LEVEL2 = 0b000110, + TRANSLATION_FAULT_LEVEL3 = 0b000111, + ACCESS_FLAG_FAULT_LEVEL0 = 0b001000, + ACCESS_FLAG_FAULT_LEVEL1 = 0b001001, + ACCESS_FLAG_FAULT_LEVEL2 = 0b001010, + ACCESS_FLAG_FAULT_LEVEL3 = 0b001011, + PERMISSION_FAULT_LEVEL0 = 0b001100, + PERMISSION_FAULT_LEVEL1 = 0b001101, + PERMISSION_FAULT_LEVEL2 = 0b001110, + PERMISSION_FAULT_LEVEL3 = 0b001111, + SYNCHRONOUS_EXTERNAL_ABORT = 0b010000, + SYNC_TAG_CHECK_FAULT = 0b010001, + SEA_TTW_LEVEL_NEG1 = 0b010011, + SEA_TTW_LEVEL0 = 0b010100, + SEA_TTW_LEVEL1 = 0b010101, + SEA_TTW_LEVEL2 = 0b010110, + SEA_TTW_LEVEL3 = 0b010111, + ECC_PARITY = 0b011000, + ECC_PARITY_TTW_LEVEL_NEG1 = 0b011011, + ECC_PARITY_TTW_LEVEL0 = 0b011100, + ECC_PARITY_TTW_LEVEL1 = 0b011101, + ECC_PARITY_TTW_LEVEL2 = 0b011110, + ECC_PARITY_TTW_LEVEL3 = 0b011111, + /// Valid only for data fault. + ALIGNMENT_FAULT = 0b100001, + /// Valid only for instruction fault. + GRANULE_PROTECTION_FAULT_LEVEL_NEG = 0b100011, + /// Valid only for instruction fault. + GRANULE_PROTECTION_FAULT_LEVEL0 = 0b100100, + /// Valid only for instruction fault. + GRANULE_PROTECTION_FAULT_LEVEL1 = 0b100101, + /// Valid only for instruction fault. + GRANULE_PROTECTION_FAULT_LEVEL2 = 0b100110, + /// Valid only for instruction fault. + GRANULE_PROTECTION_FAULT_LEVEL3 = 0b100111, + ADDRESS_SIZE_FAULT_LEVEL_NEG1 = 0b101001, + TRANSLATION_FAULT_LEVEL_NEG1 = 0b101011, + TLB_CONFLICT_ABORT = 0b110000, + UNSUPPORTED_HW_UPDATE_FAULT = 0b110001, +} + +/// Support for embedding within IssDataAbort/IssInstructionAbort +impl FaultStatusCode { + const fn from_bits(bits: u32) -> Self { + FaultStatusCode((bits & 0x3f) as u8) + } + + const fn into_bits(self) -> u32 { + self.0 as u32 + } +} + +#[bitfield(u32)] +pub struct IssDataAbort { + #[bits(6)] + pub dfsc: FaultStatusCode, + // Write operation (write not read) + pub wnr: bool, + pub s1ptw: bool, + pub cm: bool, + pub ea: bool, + /// FAR not valid + pub fnv: bool, + #[bits(2)] + pub set: u8, + pub vncr: bool, + /// Acquire/release + pub ar: bool, + /// (ISV==1) 64-bit, (ISV==0) FAR is approximate + pub sf: bool, + #[bits(5)] + /// Register index. + pub srt: u8, + /// Sign extended. + pub sse: bool, + #[bits(2)] + /// access width log2 + pub sas: u8, + /// Valid ESREL2 iss field. + pub isv: bool, + #[bits(7)] + _unused: u8, +} + +#[open_enum] +#[repr(u8)] +pub enum ExceptionClass { + UNKNOWN = 0b000000, + WFI = 0b000001, + MCR_MRC_COPROC_15 = 0b000011, + MCRR_MRRC_COPROC_15 = 0b000100, + MCR_MRC_COPROC_14 = 0b000101, + LDC_STC = 0b000110, + FP_OR_SIMD = 0b000111, + VMRS = 0b001000, + POINTER_AUTH_HCR_OR_SCR = 0b001001, + LS64 = 0b001010, + MRRC_COPROC_14 = 0b001100, + BRANCH_TARGET = 0b001101, + ILLEGAL_STATE = 0b001110, + SVC32 = 0b010001, + HVC32 = 0b010010, + SMC32 = 0b010011, + SVC = 0b010101, + HVC = 0b010110, + SMC = 0b010111, + SYSTEM = 0b011000, + SVE = 0b011001, + ERET = 0b011010, + TSTART = 0b011011, + POINTER_AUTH = 0b011100, + SME = 0b011101, + INSTRUCTION_ABORT_LOWER = 0b100000, + INSTRUCTION_ABORT = 0b100001, + PC_ALIGNMENT = 0b100010, + DATA_ABORT_LOWER = 0b100100, + DATA_ABORT = 0b100101, + SP_ALIGNMENT_FAULT = 0b100110, + MEMORY_OP = 0b100111, + FP_EXCEPTION_32 = 0b101000, + FP_EXCEPTION_64 = 0b101100, + SERROR = 0b101111, + BREAKPOINT_LOWER = 0b110000, + BREAKPOINT = 0b110001, + STEP_LOWER = 0b110010, + STEP = 0b110011, + WATCHPOINT_LOWER = 0b110100, + WATCHPOINT = 0b110101, + BRK32 = 0b111000, + VECTOR_CATCH_32 = 0b111010, + BRK = 0b111100, +}