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