diff --git a/src/arch/src/aarch64/linux/regs.rs b/src/arch/src/aarch64/linux/regs.rs index 81146b8a1..d60f0318c 100644 --- a/src/arch/src/aarch64/linux/regs.rs +++ b/src/arch/src/aarch64/linux/regs.rs @@ -5,11 +5,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. -use std::{mem, num::TryFromIntError, result}; +use std::{mem, mem::offset_of, num::TryFromIntError, result}; use super::super::get_fdt_addr; use kvm_bindings::{ - user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK, + kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_CRN_SHIFT, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT, @@ -42,24 +42,9 @@ const PSR_D_BIT: u64 = 0x0000_0200; // Taken from arch/arm64/kvm/inject_fault.c. const PSTATE_FAULT_BITS_64: u64 = PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_BIT | PSR_D_BIT; -// Following are macros that help with getting the ID of a aarch64 core register. +// This is a macro that helps with getting the ID of a aarch64 core register. // The core register are represented by the user_pt_regs structure. Look for it in // arch/arm64/include/uapi/asm/ptrace.h. - -// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having -// an instance of that structure. -// It uses a null pointer to retrieve the offset to the field. -// Inspired by C solution: `#define offsetof(str, f) ((size_t)(&((str *)0)->f))`. -// Doing `offset__of!(user_pt_regs, pstate)` in our rust code will trigger the following: -// unsafe { &(*(0 as *const user_pt_regs)).pstate as *const _ as usize } -// The dereference expression produces an lvalue, but that lvalue is not actually read from, -// we're just doing pointer math on it, so in theory, it should safe. -macro_rules! offset__of { - ($str:ty, $field:ident) => { - unsafe { &(*(std::ptr::null::())).$field as *const _ as usize } - }; -} - macro_rules! arm64_core_reg { ($reg: tt) => { // As per `kvm_arm_copy_reg_indices`, the id of a core register can be obtained like this: @@ -87,7 +72,7 @@ macro_rules! arm64_core_reg { KVM_REG_ARM64 as u64 | KVM_REG_SIZE_U64 as u64 | u64::from(KVM_REG_ARM_CORE) - | ((offset__of!(user_pt_regs, $reg) / mem::size_of::()) as u64) + | (((offset_of!(kvm_regs, regs) + offset_of!(user_pt_regs, $reg)) / mem::size_of::()) as u64) }; } @@ -126,14 +111,12 @@ arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5); /// * `mem` - Reserved DRAM for current VM. pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap) -> Result<()> { // Get the register index of the PSTATE (Processor State) register. - #[allow(deref_nullptr)] vcpu.set_one_reg(arm64_core_reg!(pstate), &PSTATE_FAULT_BITS_64.to_le_bytes()) .map_err(Error::SetCoreRegister)?; // Other vCPUs are powered off initially awaiting PSCI wakeup. if cpu_id == 0 { // Setting the PC (Processor Counter) to the current program address (kernel address). - #[allow(deref_nullptr)] vcpu.set_one_reg(arm64_core_reg!(pc), &boot_ip.to_le_bytes()) .map_err(Error::SetCoreRegister)?; @@ -141,7 +124,6 @@ pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap // "The device tree blob (dtb) must be placed on an 8-byte boundary and must // not exceed 2 megabytes in size." -> https://www.kernel.org/doc/Documentation/arm64/booting.txt. // We are choosing to place it the end of DRAM. See `get_fdt_addr`. - #[allow(deref_nullptr)] vcpu.set_one_reg(arm64_core_reg!(regs), &get_fdt_addr(mem).to_le_bytes()) .map_err(Error::SetCoreRegister)?; }