vcpu_aarch64.rs0.00%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::os::fd::{FromRawFd, OwnedFd};16
17
use snafu::ResultExt;18
19
use crate::arch::reg::{Reg, SReg};20
use crate::hv::kvm::vcpu::KvmVcpu;21
use crate::hv::kvm::vm::KvmVm;22
use crate::hv::{Result, Vcpu, error};23
use crate::sys::kvm::{24
KvmArmVcpuFeature, KvmCap, KvmOneReg, kvm_arm_preferred_target, kvm_arm_vcpu_init,25
kvm_create_vcpu, kvm_get_one_reg, kvm_set_one_reg,26
};27
28
#[derive(Debug)]29
pub struct VcpuArch {30
mpidr: u64,31
}32
33
impl VcpuArch {34
pub fn new(id: u64) -> Self {35
VcpuArch { mpidr: id }36
}37
}38
39
const fn encode_reg(reg: Reg) -> u64 {40
0x6030_0000_0010_0000 | ((reg as u64) << 1)41
}42
43
const fn encode_system_reg(reg: SReg) -> u64 {44
0x6030_0000_0013_0000 | reg.raw() as u6445
}46
47
impl KvmVcpu {48
pub fn create_vcpu(vm: &KvmVm, index: u16, _: u64) -> Result<OwnedFd> {49
let fd = unsafe { kvm_create_vcpu(&vm.vm.fd, index as u32) }.context(error::CreateVcpu)?;50
Ok(unsafe { OwnedFd::from_raw_fd(fd) })51
}52
53
pub fn kvm_vcpu_init(&mut self, is_bsp: bool) -> Result<()> {54
let mut arm_cpu_init =55
unsafe { kvm_arm_preferred_target(&self.vm.fd) }.context(error::CreateVcpu)?;56
self.vm.check_extension(KvmCap::ARM_PSCI_0_2)?;57
arm_cpu_init.features[0] |= KvmArmVcpuFeature::PSCI_0_2.bits();58
if !is_bsp {59
arm_cpu_init.features[0] |= KvmArmVcpuFeature::POWER_OFF.bits();60
}61
unsafe { kvm_arm_vcpu_init(&self.fd, &arm_cpu_init) }.context(error::CreateVcpu)?;62
self.set_sregs(&[(SReg::MPIDR_EL1, self.arch.mpidr)])63
}64
65
fn get_one_reg(&self, reg: u64) -> Result<u64> {66
let mut val = 0;67
let one_reg = KvmOneReg {68
id: reg,69
addr: &mut val as *mut _ as _,70
};71
unsafe { kvm_get_one_reg(&self.fd, &one_reg) }.context(error::VcpuReg)?;72
Ok(val)73
}74
75
fn set_one_reg(&self, reg: u64, val: u64) -> Result<()> {76
let one_reg = KvmOneReg {77
id: reg,78
addr: &val as *const _ as _,79
};80
unsafe { kvm_set_one_reg(&self.fd, &one_reg) }.context(error::VcpuReg)?;81
Ok(())82
}83
84
pub fn kvm_set_regs(&self, vals: &[(Reg, u64)]) -> Result<()> {85
for (reg, val) in vals {86
self.set_one_reg(encode_reg(*reg), *val)?;87
}88
Ok(())89
}90
91
pub fn kvm_get_reg(&self, reg: Reg) -> Result<u64> {92
self.get_one_reg(encode_reg(reg))93
}94
95
pub fn kvm_set_sregs(&self, vals: &[(SReg, u64)]) -> Result<()> {96
for (reg, val) in vals {97
self.set_one_reg(encode_system_reg(*reg), *val)?;98
}99
Ok(())100
}101
102
pub fn kvm_get_sreg(&self, reg: SReg) -> Result<u64> {103
self.get_one_reg(encode_system_reg(reg))104
}105
}106