vminer_core/arch/
aarch64.rs1use bytemuck::{Pod, Zeroable};
2
3use super::runtime;
4use crate::{endian::LittleEndian, PhysicalAddress, VcpuResult, VirtualAddress};
5
6#[derive(Debug, Clone, Copy)]
7pub struct Aarch64;
8
9#[derive(Debug, Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
10#[repr(C)]
11pub struct Vcpu {
12 pub registers: Registers,
13 pub special_registers: SpecialRegisters,
14 pub other_registers: OtherRegisters,
15}
16
17struct MmuDesc;
18
19impl super::MmuDesc for MmuDesc {
20 #[inline]
21 fn is_valid(mmu_entry: crate::addr::MmuEntry) -> bool {
22 mmu_entry.0 & 1 != 0
23 }
24
25 #[inline]
26 fn is_large(mmu_entry: crate::addr::MmuEntry) -> bool {
27 mmu_entry.0 & 0b10 == 0
28 }
29}
30
31impl super::Architecture for Aarch64 {
32 type Endian = LittleEndian;
33
34 type Registers = Registers;
35 type SpecialRegisters = SpecialRegisters;
36 type OtherRegisters = OtherRegisters;
37
38 #[inline]
39 fn into_runtime(self) -> runtime::Architecture {
40 runtime::Architecture::Aarch64(self)
41 }
42
43 #[inline]
44 fn endianness(&self) -> LittleEndian {
45 LittleEndian
46 }
47
48 fn virtual_to_physical<M: crate::Memory + ?Sized>(
49 &self,
50 memory: &M,
51 mmu_addr: PhysicalAddress,
52 addr: VirtualAddress,
53 ) -> crate::TranslationResult<PhysicalAddress> {
54 super::virtual_to_physical::<MmuDesc, M>(memory, mmu_addr, addr)
55 }
56
57 fn find_kernel_pgd<M: crate::Memory + ?Sized>(
58 &self,
59 memory: &M,
60 vcpus: &(impl super::HasVcpus<Arch = Self> + ?Sized),
61 use_per_cpu: bool,
62 additional: &[VirtualAddress],
63 ) -> crate::VmResult<Option<PhysicalAddress>> {
64 for vcpu in vcpus.iter_vcpus() {
65 if vcpus.instruction_pointer(vcpu)?.is_kernel() {
66 return Ok(Some(vcpus.pgd(vcpu)?));
67 }
68 }
69
70 let addresses = &[additional];
72 let test = super::make_address_test(vcpus, memory, use_per_cpu, addresses);
73
74 Ok(super::try_all_addresses(test))
88 }
89
90 fn find_in_kernel_memory_raw<M: crate::Memory + ?Sized>(
91 &self,
92 memory: &M,
93 mmu_addr: PhysicalAddress,
94 base_search_addr: VirtualAddress,
95 finder: &memchr::memmem::Finder,
96 buf: &mut [u8],
97 ) -> crate::MemoryAccessResult<Option<VirtualAddress>> {
98 super::find_in_kernel_memory_raw::<MmuDesc, M>(
99 memory,
100 mmu_addr,
101 base_search_addr,
102 finder,
103 buf,
104 )
105 }
106
107 fn find_in_kernel_memory<M: crate::Memory + ?Sized>(
108 &self,
109 memory: &M,
110 mmu_addr: PhysicalAddress,
111 needle: &[u8],
112 ) -> crate::MemoryAccessResult<Option<VirtualAddress>> {
113 super::find_in_kernel_memory::<MmuDesc, M>(memory, mmu_addr, needle, self.kernel_base())
114 }
115
116 #[inline]
117 fn kernel_base(&self) -> VirtualAddress {
118 VirtualAddress(0xffff_a000_0000_0000)
119 }
120
121 fn instruction_pointer<Vcpus: super::HasVcpus<Arch = Self> + ?Sized>(
122 &self,
123 vcpus: &Vcpus,
124 vcpu: crate::VcpuId,
125 ) -> VcpuResult<VirtualAddress> {
126 let registers = vcpus.registers(vcpu)?;
127 Ok(VirtualAddress(registers.pc))
128 }
129
130 fn stack_pointer<Vcpus: super::HasVcpus<Arch = Self> + ?Sized>(
131 &self,
132 vcpus: &Vcpus,
133 vcpu: crate::VcpuId,
134 ) -> VcpuResult<VirtualAddress> {
135 let sp = if self.instruction_pointer(vcpus, vcpu)?.is_kernel() {
136 vcpus.special_registers(vcpu)?.sp_el1
137 } else {
138 vcpus.registers(vcpu)?.sp
139 };
140 Ok(VirtualAddress(sp))
141 }
142
143 fn base_pointer<Vcpus: super::HasVcpus<Arch = Self> + ?Sized>(
144 &self,
145 vcpus: &Vcpus,
146 vcpu: crate::VcpuId,
147 ) -> VcpuResult<Option<VirtualAddress>> {
148 let registers = vcpus.registers(vcpu)?;
149 Ok(Some(VirtualAddress(registers.regs[29])))
150 }
151
152 fn pgd<Vcpus: super::HasVcpus<Arch = Self> + ?Sized>(
153 &self,
154 vcpus: &Vcpus,
155 vcpu: crate::VcpuId,
156 ) -> VcpuResult<PhysicalAddress> {
157 use super::MmuDesc as _;
158
159 let s_registers = vcpus.special_registers(vcpu)?;
160
161 let ttbr = if self.instruction_pointer(vcpus, vcpu)?.is_kernel() {
162 s_registers.ttbr1_el1
163 } else {
164 s_registers.ttbr0_el1
165 };
166 Ok(PhysicalAddress(ttbr & crate::mask(MmuDesc::ADDR_BITS)))
167 }
168
169 fn kernel_per_cpu<Vcpus: super::HasVcpus<Arch = Self> + ?Sized>(
170 &self,
171 _vcpus: &Vcpus,
172 _vcpu: crate::VcpuId,
173 ) -> VcpuResult<Option<VirtualAddress>> {
174 Ok(None)
175 }
176}
177
178#[repr(C)]
179#[derive(Debug, Clone, Copy, Pod, Zeroable)]
180pub struct Registers {
181 pub regs: [u64; 31],
182 pub sp: u64,
183 pub pc: u64,
184 pub pstate: u64,
185}
186
187#[repr(C)]
189#[derive(Debug, Clone, Copy, Pod, Zeroable)]
190pub struct SpecialRegisters {
191 pub sp_el1: u64,
192 pub ttbr0_el1: u64,
193 pub ttbr1_el1: u64,
194 pub vbar_el1: u64,
195}
196
197#[repr(C)]
198#[derive(Debug, Clone, Copy, Pod, Zeroable)]
199pub struct OtherRegisters;
200
201impl From<Registers> for super::runtime::Registers {
202 #[inline]
203 fn from(regs: Registers) -> Self {
204 Self::Aarch64(regs)
205 }
206}
207
208impl From<SpecialRegisters> for super::runtime::SpecialRegisters {
209 #[inline]
210 fn from(regs: SpecialRegisters) -> Self {
211 Self::Aarch64(regs)
212 }
213}
214
215impl From<OtherRegisters> for super::runtime::OtherRegisters {
216 #[inline]
217 fn from(regs: OtherRegisters) -> Self {
218 Self::Aarch64(regs)
219 }
220}