Skip to main content

aarch64emu/
cpu.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use std::future::Future;
5
6pub trait Cpu: AccessCpuState {
7    /// The error type for IO access failures.
8    type Error;
9
10    /// Performs a memory read of an instruction to execute.
11    fn read_instruction(
12        &mut self,
13        gva: u64,
14        bytes: &mut [u8],
15    ) -> impl Future<Output = Result<(), Self::Error>>;
16
17    /// Performs a memory read of 1, 2, 4, or 8 bytes.
18    fn read_memory(
19        &mut self,
20        gva: u64,
21        bytes: &mut [u8],
22    ) -> impl Future<Output = Result<(), Self::Error>>;
23
24    /// Performs a memory read of 1, 2, 4, or 8 bytes on a guest physical address.
25    /// `exec` indicates whether the read is for execution (true) or data (false).
26    fn read_physical_memory(
27        &mut self,
28        gpa: u64,
29        bytes: &mut [u8],
30        exec: bool,
31    ) -> impl Future<Output = Result<(), Self::Error>>;
32
33    /// Performs a memory write of 1, 2, 4, or 8 bytes.
34    fn write_memory(
35        &mut self,
36        gva: u64,
37        bytes: &[u8],
38    ) -> impl Future<Output = Result<(), Self::Error>>;
39
40    /// Performs a memory write of 1, 2, 4, or 8 bytes on a guest physical address.
41    fn write_physical_memory(
42        &mut self,
43        gpa: u64,
44        bytes: &[u8],
45    ) -> impl Future<Output = Result<(), Self::Error>>;
46
47    /// Performs an atomic, sequentially-consistent compare exchange on a memory
48    /// location.
49    ///
50    /// The caller has already fetched `current` via `read_memory`, so the
51    /// implementor only needs to perform an atomic compare+write if the memory
52    /// could have mutated concurrently and supports atomic operation. This
53    /// includes ordinary RAM, but does not include device registers.
54    ///
55    /// Sets `*success` to `true` if the exchange succeeded, `false` otherwise.
56    ///
57    /// FUTURE: just return `success` when we can directly use async functions
58    /// in traits.
59    fn compare_and_write_memory(
60        &mut self,
61        gva: u64,
62        current: &[u8],
63        new: &[u8],
64        success: &mut bool,
65    ) -> impl Future<Output = Result<(), Self::Error>>;
66}
67
68impl<T: Cpu + ?Sized> Cpu for &mut T {
69    type Error = T::Error;
70
71    fn read_instruction(
72        &mut self,
73        gva: u64,
74        bytes: &mut [u8],
75    ) -> impl Future<Output = Result<(), Self::Error>> {
76        (*self).read_instruction(gva, bytes)
77    }
78
79    fn read_memory(
80        &mut self,
81        gva: u64,
82        bytes: &mut [u8],
83    ) -> impl Future<Output = Result<(), Self::Error>> {
84        (*self).read_memory(gva, bytes)
85    }
86
87    fn read_physical_memory(
88        &mut self,
89        gpa: u64,
90        bytes: &mut [u8],
91        exec: bool,
92    ) -> impl Future<Output = Result<(), Self::Error>> {
93        (*self).read_physical_memory(gpa, bytes, exec)
94    }
95
96    fn write_memory(
97        &mut self,
98        gva: u64,
99        bytes: &[u8],
100    ) -> impl Future<Output = Result<(), Self::Error>> {
101        (*self).write_memory(gva, bytes)
102    }
103
104    fn write_physical_memory(
105        &mut self,
106        gpa: u64,
107        bytes: &[u8],
108    ) -> impl Future<Output = Result<(), Self::Error>> {
109        (*self).write_physical_memory(gpa, bytes)
110    }
111
112    fn compare_and_write_memory(
113        &mut self,
114        gva: u64,
115        current: &[u8],
116        new: &[u8],
117        success: &mut bool,
118    ) -> impl Future<Output = Result<(), Self::Error>> {
119        (*self).compare_and_write_memory(gva, current, new, success)
120    }
121}
122
123pub trait AccessCpuState {
124    /// Commit any outstanding register updates to the CPU.
125    fn commit(&mut self);
126
127    /// Access general purpose x register and index (e.g. X0).
128    fn x(&mut self, index: u8) -> u64;
129
130    /// Update general purpose x register at index with value (e.g. X0 = 1).
131    fn update_x(&mut self, index: u8, data: u64);
132
133    /// Access floating point 128-bit register at index (e.g. Q0).
134    fn q(&self, index: u8) -> u128;
135
136    /// Update floating point 128-bit register at index (e.g. Q0 = 1.0).
137    fn update_q(&mut self, index: u8, data: u128);
138
139    /// Access floating point 64-bit register at index (e.g. D0).
140    fn d(&self, index: u8) -> u64;
141
142    /// Update floating point 64-bit register at index (e.g. D0 = 1.0).
143    fn update_d(&mut self, index: u8, data: u64);
144
145    /// Access floating point 32-bit register at index (e.g. H0).
146    fn h(&self, index: u8) -> u32;
147
148    /// Update floating point 32-bit register at index (e.g. H0 = 1.0).
149    fn update_h(&mut self, index: u8, data: u32);
150
151    /// Access floating point 16-bit register at index (e.g. S0).
152    fn s(&self, index: u8) -> u16;
153
154    /// Update floating point 16-bit register at index (e.g. S0 = 1.0).
155    fn update_s(&mut self, index: u8, data: u16);
156
157    /// Access floating point 16-bit register at index (e.g. B0).
158    fn b(&self, index: u8) -> u8;
159
160    /// Update floating point 8-bit register at index (e.g. B0 = 1.0).
161    fn update_b(&mut self, index: u8, data: u8);
162
163    /// Access stack pointer register.
164    fn sp(&mut self) -> u64;
165
166    /// Update stack pointer register.
167    fn update_sp(&mut self, data: u64);
168
169    /// Access frame pointer register (alias for X29).
170    fn fp(&mut self) -> u64;
171
172    /// Update frame pointer register (alias for X29).
173    fn update_fp(&mut self, data: u64);
174
175    /// Access link register / return address (alias for X30).
176    fn lr(&mut self) -> u64;
177
178    /// Update link register / return address (alias for X30).
179    fn update_lr(&mut self, data: u64);
180
181    /// Access program counter register / instruction pointer.
182    fn pc(&mut self) -> u64;
183
184    /// Update program counter register / instruction pointer.
185    fn update_pc(&mut self, data: u64);
186
187    /// Access the CSPR register
188    fn cpsr(&mut self) -> aarch64defs::Cpsr64;
189}
190
191impl<T: AccessCpuState + ?Sized> AccessCpuState for &mut T {
192    fn commit(&mut self) {
193        (*self).commit()
194    }
195    fn x(&mut self, index: u8) -> u64 {
196        (*self).x(index)
197    }
198    fn update_x(&mut self, index: u8, data: u64) {
199        (*self).update_x(index, data)
200    }
201    fn q(&self, index: u8) -> u128 {
202        (**self).q(index)
203    }
204    fn update_q(&mut self, index: u8, data: u128) {
205        (*self).update_q(index, data)
206    }
207    fn d(&self, index: u8) -> u64 {
208        (**self).d(index)
209    }
210    fn update_d(&mut self, index: u8, data: u64) {
211        (*self).update_d(index, data)
212    }
213    fn h(&self, index: u8) -> u32 {
214        (**self).h(index)
215    }
216    fn update_h(&mut self, index: u8, data: u32) {
217        (*self).update_h(index, data)
218    }
219    fn s(&self, index: u8) -> u16 {
220        (**self).s(index)
221    }
222    fn update_s(&mut self, index: u8, data: u16) {
223        (*self).update_s(index, data)
224    }
225    fn b(&self, index: u8) -> u8 {
226        (**self).b(index)
227    }
228    fn update_b(&mut self, index: u8, data: u8) {
229        (*self).update_b(index, data)
230    }
231    fn sp(&mut self) -> u64 {
232        (*self).sp()
233    }
234    fn update_sp(&mut self, data: u64) {
235        (*self).update_sp(data)
236    }
237    fn fp(&mut self) -> u64 {
238        (*self).fp()
239    }
240    fn update_fp(&mut self, data: u64) {
241        (*self).update_fp(data)
242    }
243    fn lr(&mut self) -> u64 {
244        (*self).lr()
245    }
246    fn update_lr(&mut self, data: u64) {
247        (*self).update_lr(data)
248    }
249    fn pc(&mut self) -> u64 {
250        (*self).pc()
251    }
252    fn update_pc(&mut self, data: u64) {
253        (*self).update_pc(data)
254    }
255    fn cpsr(&mut self) -> aarch64defs::Cpsr64 {
256        (*self).cpsr()
257    }
258}