Alioth Code Coverage

vcpu_aarch64.rs0.00%

1// Copyright 2024 Google LLC
2//
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 at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// 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 and
13// limitations under the License.
14
15use std::os::fd::{FromRawFd, OwnedFd};
16
17use snafu::ResultExt;
18
19use crate::arch::reg::{Reg, SReg};
20use crate::hv::kvm::vcpu::KvmVcpu;
21use crate::hv::kvm::vm::KvmVm;
22use crate::hv::{Result, Vcpu, error};
23use 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)]
29pub struct VcpuArch {
30 mpidr: u64,
31}
32
33impl VcpuArch {
34 pub fn new(id: u64) -> Self {
35 VcpuArch { mpidr: id }
36 }
37}
38
39const fn encode_reg(reg: Reg) -> u64 {
40 0x6030_0000_0010_0000 | ((reg as u64) << 1)
41}
42
43const fn encode_system_reg(reg: SReg) -> u64 {
44 0x6030_0000_0013_0000 | reg.raw() as u64
45}
46
47impl 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