xref: /aosp_15_r20/external/crosvm/hypervisor/src/riscv64.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2023 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use anyhow::anyhow;
6 use base::Result;
7 use downcast_rs::impl_downcast;
8 use serde::Deserialize;
9 use serde::Serialize;
10 use vm_memory::GuestAddress;
11 
12 use crate::Hypervisor;
13 use crate::IrqRoute;
14 use crate::IrqSource;
15 use crate::IrqSourceChip;
16 use crate::Vcpu;
17 use crate::Vm;
18 
19 /// A wrapper for using a VM on riscv64 and getting/setting its state.
20 pub trait VmRiscv64: Vm {
21     /// Gets the `Hypervisor` that created this VM.
get_hypervisor(&self) -> &dyn Hypervisor22     fn get_hypervisor(&self) -> &dyn Hypervisor;
23 
24     /// Create a Vcpu with the specified Vcpu ID.
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuRiscv64>>25     fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuRiscv64>>;
26 }
27 
28 /// A wrapper around creating and using a VCPU on riscv64.
29 pub trait VcpuRiscv64: Vcpu {
30     /// Sets the value of a register on this VCPU.
set_one_reg(&self, reg_id: VcpuRegister, data: u64) -> Result<()>31     fn set_one_reg(&self, reg_id: VcpuRegister, data: u64) -> Result<()>;
32 
33     /// Gets the value of a register on this VCPU.
get_one_reg(&self, reg_id: VcpuRegister) -> Result<u64>34     fn get_one_reg(&self, reg_id: VcpuRegister) -> Result<u64>;
35 
36     /// Snapshot VCPU
snapshot(&self) -> anyhow::Result<VcpuSnapshot>37     fn snapshot(&self) -> anyhow::Result<VcpuSnapshot> {
38         Err(anyhow!("not yet implemented"))
39     }
40 
41     /// Restore VCPU
restore(&self, _snapshot: &VcpuSnapshot) -> anyhow::Result<()>42     fn restore(&self, _snapshot: &VcpuSnapshot) -> anyhow::Result<()> {
43         Err(anyhow!("not yet implemented"))
44     }
45 }
46 
47 /// Riscv64 specific vCPU snapshot.
48 ///
49 /// Not implemented yet.
50 #[derive(Clone, Debug, Serialize, Deserialize)]
51 pub struct VcpuSnapshot {
52     pub vcpu_id: usize,
53 }
54 
55 impl_downcast!(VcpuRiscv64);
56 
57 /// Initial state for Riscv64 VCPUs.
58 #[derive(Clone)]
59 pub struct VcpuInitRiscv64 {
60     /// The address of the FDT
61     pub fdt_address: GuestAddress,
62 }
63 
64 impl VcpuInitRiscv64 {
new(fdt_address: GuestAddress) -> Self65     pub fn new(fdt_address: GuestAddress) -> Self {
66         Self { fdt_address }
67     }
68 }
69 
70 /// Hold the CPU feature configurations that are needed to setup a vCPU.
71 #[derive(Clone, Debug, PartialEq, Eq)]
72 pub struct CpuConfigRiscv64 {
73     /// The address of the FDT
74     pub fdt_address: GuestAddress,
75 }
76 
77 impl CpuConfigRiscv64 {
new(fdt_address: GuestAddress) -> Self78     pub fn new(fdt_address: GuestAddress) -> Self {
79         Self { fdt_address }
80     }
81 }
82 
83 /// Config registers exposed by kvm.
84 #[repr(u64)]
85 #[derive(Copy, Clone)]
86 pub enum ConfigRegister {
87     Isa = 0,
88 }
89 
90 /// Timer registers exposed by kvm.
91 #[repr(u64)]
92 #[derive(Copy, Clone)]
93 pub enum TimerRegister {
94     TimebaseFrequency = 0,
95 }
96 
97 /// Core registers exposed by kvm.
98 #[repr(u64)]
99 #[derive(Copy, Clone)]
100 pub enum CoreRegister {
101     Pc = 0x00,   // Program counter
102     Ra = 0x01,   // Return address
103     Sp = 0x02,   // Stack pointer
104     Gp = 0x03,   // Global pointer
105     Tp = 0x04,   // Task pointer
106     T0 = 0x05,   // Caller saved register 0
107     T1 = 0x06,   // Caller saved register 1
108     T2 = 0x07,   // Caller saved register 2
109     S0 = 0x08,   // Callee saved register 0
110     S1 = 0x09,   // Callee saved register 1
111     A0 = 0x0a,   // Function argument (or return value) 0
112     A1 = 0x0b,   // Function argument (or return value) 1
113     A2 = 0x0c,   // Function argument 2
114     A3 = 0x0d,   // Function argument 3
115     A4 = 0x0e,   // Function argument 4
116     A5 = 0x0f,   // Function argument 5
117     A6 = 0x10,   // Function argument 6
118     A7 = 0x11,   // Function argument 7
119     S2 = 0x12,   // Callee saved register 2
120     S3 = 0x13,   // Callee saved register 3
121     S4 = 0x14,   // Callee saved register 4
122     S5 = 0x15,   // Callee saved register 5
123     S6 = 0x16,   // Callee saved register 6
124     S7 = 0x17,   // Callee saved register 7
125     S8 = 0x18,   // Callee saved register 8
126     S9 = 0x19,   // Callee saved register 9
127     S10 = 0x1a,  // Callee saved register 10
128     S11 = 0x1b,  // Callee saved register 11
129     T3 = 0x1c,   // Caller saved register 3
130     T4 = 0x1d,   // Caller saved register 4
131     T5 = 0x1e,   // Caller saved register 5
132     T6 = 0x1f,   // Caller saved register 6
133     Mode = 0x20, // Privilege mode (1 = S-mode or 0 = U-mode)
134 }
135 
136 /// Registers exposed through `KVM_[GET|SET]_ONE_REG` API.
137 #[derive(Copy, Clone)]
138 pub enum VcpuRegister {
139     Config(ConfigRegister),
140     Core(CoreRegister),
141     Timer(TimerRegister),
142 }
143 
144 // Convenience constructors for IrqRoutes
145 impl IrqRoute {
aia_irq_route(irq_num: u32) -> IrqRoute146     pub fn aia_irq_route(irq_num: u32) -> IrqRoute {
147         IrqRoute {
148             gsi: irq_num,
149             source: IrqSource::Irqchip {
150                 chip: IrqSourceChip::Aia,
151                 pin: irq_num,
152             },
153         }
154     }
155 }
156