diff --git a/hypervisor/src/kvm/aarch64.rs b/hypervisor/src/kvm/aarch64.rs index b896190b56..f6fd78caf6 100644 --- a/hypervisor/src/kvm/aarch64.rs +++ b/hypervisor/src/kvm/aarch64.rs @@ -20,6 +20,7 @@ use libc::ENOTSUP; use libc::ENXIO; use vm_memory::GuestAddress; +use super::Config; use super::Kvm; use super::KvmCap; use super::KvmVcpu; @@ -76,6 +77,16 @@ impl Kvm { } impl KvmVm { + /// Does platform specific initialization for the KvmVm. + pub fn init_arch(&self, cfg: &Config) -> Result<()> { + #[cfg(target_arch = "aarch64")] + if cfg.mte { + // Safe because it does not take pointer arguments. + unsafe { self.enable_raw_capability(KvmCap::ArmMte, 0, &[0, 0, 0, 0])? } + } + Ok(()) + } + /// Checks if a particular `VmCap` is available, or returns None if arch-independent /// Vm.check_capability() should handle the check. pub fn check_capability_arch(&self, _c: VmCap) -> Option { diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 6fbef77099..64a9d9f41b 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -238,13 +238,15 @@ impl KvmVm { } })?; - Ok(KvmVm { + let vm = KvmVm { kvm: kvm.try_clone()?, vm: vm_descriptor, guest_mem, mem_regions: Arc::new(Mutex::new(BTreeMap::new())), mem_slot_gaps: Arc::new(Mutex::new(BinaryHeap::new())), - }) + }; + vm.init_arch(&cfg)?; + Ok(vm) } fn create_vcpu(&self, id: usize) -> Result { diff --git a/hypervisor/src/kvm/x86_64.rs b/hypervisor/src/kvm/x86_64.rs index 1ebfe98f5a..977b764a7f 100644 --- a/hypervisor/src/kvm/x86_64.rs +++ b/hypervisor/src/kvm/x86_64.rs @@ -23,6 +23,7 @@ use libc::E2BIG; use libc::ENXIO; use vm_memory::GuestAddress; +use super::Config; use super::Kvm; use super::KvmVcpu; use super::KvmVm; @@ -158,6 +159,11 @@ impl HypervisorX86_64 for Kvm { } impl KvmVm { + /// Does platform specific initialization for the KvmVm. + pub fn init_arch(&self, _cfg: &Config) -> Result<()> { + Ok(()) + } + /// Checks if a particular `VmCap` is available, or returns None if arch-independent /// Vm.check_capability() should handle the check. pub fn check_capability_arch(&self, c: VmCap) -> Option { diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index d30592ce06..e494c0e245 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -561,12 +561,17 @@ pub enum ProtectionType { #[derive(Clone, Copy)] pub struct Config { + #[cfg(target_arch = "aarch64")] + /// enable the Memory Tagging Extension in the guest + pub mte: bool, pub protection_type: ProtectionType, } impl Default for Config { fn default() -> Config { Config { + #[cfg(target_arch = "aarch64")] + mte: false, protection_type: ProtectionType::Unprotected, } } diff --git a/kvm/src/cap.rs b/kvm/src/cap.rs index f353686ad7..e17174d543 100644 --- a/kvm/src/cap.rs +++ b/kvm/src/cap.rs @@ -122,4 +122,5 @@ pub enum Cap { ArmPmuV3 = KVM_CAP_ARM_PMU_V3, IoapicNumPins = KVM_CAP_IOAPIC_NUM_PINS, ArmProtectedVm = KVM_CAP_ARM_PROTECTED_VM, + ArmMte = KVM_CAP_ARM_MTE, } diff --git a/kvm_sys/bindgen.sh b/kvm_sys/bindgen.sh index 63723dd9d4..e04c48a8bb 100755 --- a/kvm_sys/bindgen.sh +++ b/kvm_sys/bindgen.sh @@ -10,7 +10,9 @@ cd "$(dirname "${BASH_SOURCE[0]}")/.." source tools/impl/bindgen-common.sh -KVM_EXTRAS="// Added by kvm_sys/bindgen.sh +KVM_EXTRAS="// TODO(pcc): Remove this when Chrome OS updates its kernel. +pub const KVM_CAP_ARM_MTE: u32 = 205; +// Added by kvm_sys/bindgen.sh pub const KVM_SYSTEM_EVENT_S2IDLE: u32 = 4; pub const KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2: u64 = 0x1; // TODO(tjeznach): Remove this when reporting KVM_IOAPIC_NUM_PINS is no longer required. diff --git a/kvm_sys/src/aarch64/bindings.rs b/kvm_sys/src/aarch64/bindings.rs index 052a5f6e29..d16718fbf0 100644 --- a/kvm_sys/src/aarch64/bindings.rs +++ b/kvm_sys/src/aarch64/bindings.rs @@ -5,6 +5,8 @@ #![allow(non_snake_case)] #![allow(dead_code)] +// TODO(pcc): Remove this when Chrome OS updates its kernel. +pub const KVM_CAP_ARM_MTE: u32 = 205; // Added by kvm_sys/bindgen.sh pub const KVM_SYSTEM_EVENT_S2IDLE: u32 = 4; pub const KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2: u64 = 0x1; diff --git a/kvm_sys/src/x86/bindings.rs b/kvm_sys/src/x86/bindings.rs index 78983ff889..8229c88a46 100644 --- a/kvm_sys/src/x86/bindings.rs +++ b/kvm_sys/src/x86/bindings.rs @@ -5,6 +5,8 @@ #![allow(non_snake_case)] #![allow(dead_code)] +// TODO(pcc): Remove this when Chrome OS updates its kernel. +pub const KVM_CAP_ARM_MTE: u32 = 205; // Added by kvm_sys/bindgen.sh pub const KVM_SYSTEM_EVENT_S2IDLE: u32 = 4; pub const KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2: u64 = 0x1; diff --git a/src/crosvm/cmdline.rs b/src/crosvm/cmdline.rs index 9f4f0cd2ef..6e21018223 100644 --- a/src/crosvm/cmdline.rs +++ b/src/crosvm/cmdline.rs @@ -753,6 +753,10 @@ pub struct RunCommand { )] /// MMIO address ranges pub mmio_address_ranges: Option>, + #[cfg(target_arch = "aarch64")] + #[argh(switch)] + /// enable the Memory Tagging Extension in the guest + pub mte: bool, #[cfg(unix)] #[argh(option, arg_name = "N")] /// virtio net virtual queue pairs. (default: 1) @@ -1351,6 +1355,13 @@ impl TryFrom for super::config::Config { #[cfg(target_arch = "aarch64")] { + if cmd.mte && !(cmd.pmem_devices.is_empty() && cmd.rw_pmem_devices.is_empty()) { + return Err( + "--mte cannot be specified together with --pmem-device or --rw-pmem-device" + .to_string(), + ); + } + cfg.mte = cmd.mte; cfg.swiotlb = cmd.swiotlb; } diff --git a/src/crosvm/config.rs b/src/crosvm/config.rs index 900f17572b..b76dee8d56 100644 --- a/src/crosvm/config.rs +++ b/src/crosvm/config.rs @@ -1235,6 +1235,8 @@ pub struct Config { pub memory: Option, pub memory_file: Option, pub mmio_address_ranges: Vec, + #[cfg(target_arch = "aarch64")] + pub mte: bool, #[cfg(windows)] pub net_vhost_user_tube: Option, pub net_vq_pairs: Option, @@ -1440,6 +1442,8 @@ impl Default for Config { memory: None, memory_file: None, mmio_address_ranges: Vec::new(), + #[cfg(target_arch = "aarch64")] + mte: false, #[cfg(windows)] net_vhost_user_tube: None, net_vq_pairs: None, diff --git a/src/crosvm/sys/unix.rs b/src/crosvm/sys/unix.rs index 23665fab81..67a316232f 100644 --- a/src/crosvm/sys/unix.rs +++ b/src/crosvm/sys/unix.rs @@ -1150,6 +1150,8 @@ fn setup_vm_components(cfg: &Config) -> Result { no_smt: cfg.no_smt, hugepages: cfg.hugepages, hv_cfg: hypervisor::Config { + #[cfg(target_arch = "aarch64")] + mte: cfg.mte, protection_type: cfg.protection_type, }, vm_image,