mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
aarch64: Move setup_regs
to hypervisor
`setup_regs` of AArch64 calls KVM sepecific code. Now move it to `hypervisor` crate. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
65dc1c83a9
commit
a7a15d56dd
@ -6,8 +6,6 @@
|
|||||||
pub mod fdt;
|
pub mod fdt;
|
||||||
/// Layout for this aarch64 system.
|
/// Layout for this aarch64 system.
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
/// Logic for configuring aarch64 registers.
|
|
||||||
pub mod regs;
|
|
||||||
/// Module for loading UEFI binary.
|
/// Module for loading UEFI binary.
|
||||||
pub mod uefi;
|
pub mod uefi;
|
||||||
|
|
||||||
@ -37,7 +35,7 @@ pub enum Error {
|
|||||||
InitramfsAddress,
|
InitramfsAddress,
|
||||||
|
|
||||||
/// Error configuring the general purpose registers
|
/// Error configuring the general purpose registers
|
||||||
RegsConfiguration(regs::Error),
|
RegsConfiguration(hypervisor::HypervisorCpuError),
|
||||||
|
|
||||||
/// Error configuring the MPIDR register
|
/// Error configuring the MPIDR register
|
||||||
VcpuRegMpidr(hypervisor::HypervisorCpuError),
|
VcpuRegMpidr(hypervisor::HypervisorCpuError),
|
||||||
@ -67,7 +65,11 @@ pub fn configure_vcpu(
|
|||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
) -> super::Result<u64> {
|
) -> super::Result<u64> {
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
regs::setup_regs(vcpu, id, kernel_entry_point.entry_addr.raw_value())
|
vcpu.setup_regs(
|
||||||
|
id,
|
||||||
|
kernel_entry_point.entry_addr.raw_value(),
|
||||||
|
super::layout::FDT_START.raw_value(),
|
||||||
|
)
|
||||||
.map_err(Error::RegsConfiguration)?;
|
.map_err(Error::RegsConfiguration)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
//
|
|
||||||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the THIRD-PARTY file.
|
|
||||||
|
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
|
||||||
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
|
||||||
};
|
|
||||||
use hypervisor::{arm64_core_reg_id, offset__of};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::{mem, result};
|
|
||||||
use vm_memory::Address;
|
|
||||||
|
|
||||||
/// Errors thrown while setting aarch64 registers.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
/// Failed to set core register (PC, PSTATE or general purpose ones).
|
|
||||||
SetCoreRegister(hypervisor::HypervisorCpuError),
|
|
||||||
/// Failed to get a system register.
|
|
||||||
GetSysRegister(hypervisor::HypervisorCpuError),
|
|
||||||
}
|
|
||||||
type Result<T> = result::Result<T, Error>;
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
// PSR (Processor State Register) bits.
|
|
||||||
// Taken from arch/arm64/include/uapi/asm/ptrace.h.
|
|
||||||
const PSR_MODE_EL1h: u64 = 0x0000_0005;
|
|
||||||
const PSR_F_BIT: u64 = 0x0000_0040;
|
|
||||||
const PSR_I_BIT: u64 = 0x0000_0080;
|
|
||||||
const PSR_A_BIT: u64 = 0x0000_0100;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// Configure core registers for a given CPU.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
|
||||||
/// * `cpu_id` - Index of current vcpu.
|
|
||||||
/// * `boot_ip` - Starting instruction pointer.
|
|
||||||
/// * `mem` - Reserved DRAM for current VM.
|
|
||||||
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, cpu_id: u8, boot_ip: u64) -> Result<()> {
|
|
||||||
let kreg_off = offset__of!(kvm_regs, regs);
|
|
||||||
|
|
||||||
// Get the register index of the PSTATE (Processor State) register.
|
|
||||||
let pstate = offset__of!(user_pt_regs, pstate) + kreg_off;
|
|
||||||
vcpu.set_reg(
|
|
||||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
|
|
||||||
PSTATE_FAULT_BITS_64,
|
|
||||||
)
|
|
||||||
.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).
|
|
||||||
let pc = offset__of!(user_pt_regs, pc) + kreg_off;
|
|
||||||
vcpu.set_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, pc), boot_ip as u64)
|
|
||||||
.map_err(Error::SetCoreRegister)?;
|
|
||||||
|
|
||||||
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
|
|
||||||
// "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`.
|
|
||||||
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
|
||||||
vcpu.set_reg(
|
|
||||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
|
||||||
super::layout::FDT_START.raw_value(),
|
|
||||||
)
|
|
||||||
.map_err(Error::SetCoreRegister)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -453,6 +453,11 @@ pub trait Vcpu: Send + Sync {
|
|||||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
fn read_mpidr(&self) -> Result<u64>;
|
fn read_mpidr(&self) -> Result<u64>;
|
||||||
///
|
///
|
||||||
|
/// Configure core registers for a given CPU.
|
||||||
|
///
|
||||||
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
|
fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>;
|
||||||
|
///
|
||||||
/// Retrieve the vCPU state.
|
/// Retrieve the vCPU state.
|
||||||
/// This function is necessary to snapshot the VM
|
/// This function is necessary to snapshot the VM
|
||||||
///
|
///
|
||||||
|
@ -1566,6 +1566,51 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
.get_one_reg(MPIDR_EL1)
|
.get_one_reg(MPIDR_EL1)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))
|
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))
|
||||||
}
|
}
|
||||||
|
///
|
||||||
|
/// Configure core registers for a given CPU.
|
||||||
|
///
|
||||||
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
|
fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> {
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
// PSR (Processor State Register) bits.
|
||||||
|
// Taken from arch/arm64/include/uapi/asm/ptrace.h.
|
||||||
|
const PSR_MODE_EL1h: u64 = 0x0000_0005;
|
||||||
|
const PSR_F_BIT: u64 = 0x0000_0040;
|
||||||
|
const PSR_I_BIT: u64 = 0x0000_0080;
|
||||||
|
const PSR_A_BIT: u64 = 0x0000_0100;
|
||||||
|
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;
|
||||||
|
|
||||||
|
let kreg_off = offset__of!(kvm_regs, regs);
|
||||||
|
|
||||||
|
// Get the register index of the PSTATE (Processor State) register.
|
||||||
|
let pstate = offset__of!(user_pt_regs, pstate) + kreg_off;
|
||||||
|
self.set_reg(
|
||||||
|
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
|
||||||
|
PSTATE_FAULT_BITS_64,
|
||||||
|
)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
|
||||||
|
|
||||||
|
// 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).
|
||||||
|
let pc = offset__of!(user_pt_regs, pc) + kreg_off;
|
||||||
|
self.set_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, pc), boot_ip as u64)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
|
||||||
|
|
||||||
|
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
|
||||||
|
// "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`.
|
||||||
|
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
||||||
|
self.set_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0), fdt_start)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Get the current CPU state
|
/// Get the current CPU state
|
||||||
|
@ -2436,7 +2436,7 @@ mod tests {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use arch::aarch64::regs::*;
|
use arch::layout;
|
||||||
use hypervisor::kvm::aarch64::{is_system_register, MPIDR_EL1};
|
use hypervisor::kvm::aarch64::{is_system_register, MPIDR_EL1};
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
use hypervisor::kvm::kvm_bindings::{
|
||||||
kvm_one_reg, kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
|
kvm_one_reg, kvm_regs, kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
|
||||||
@ -2451,7 +2451,7 @@ mod tests {
|
|||||||
let vm = hv.create_vm().unwrap();
|
let vm = hv.create_vm().unwrap();
|
||||||
let vcpu = vm.create_vcpu(0, None).unwrap();
|
let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||||
|
|
||||||
let res = setup_regs(&vcpu, 0, 0x0);
|
let res = vcpu.setup_regs(0, 0x0, layout::FDT_START.0);
|
||||||
// Must fail when vcpu is not initialized yet.
|
// Must fail when vcpu is not initialized yet.
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
|
|
||||||
@ -2459,7 +2459,7 @@ mod tests {
|
|||||||
vm.get_preferred_target(&mut kvi).unwrap();
|
vm.get_preferred_target(&mut kvi).unwrap();
|
||||||
vcpu.vcpu_init(&kvi).unwrap();
|
vcpu.vcpu_init(&kvi).unwrap();
|
||||||
|
|
||||||
assert!(setup_regs(&vcpu, 0, 0x0).is_ok());
|
assert!(vcpu.setup_regs(0, 0x0, layout::FDT_START.0).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user