|
11 | 11 | //! This is also where FP/SIMD state is normalized across Darwin and Linux, including |
12 | 12 | //! Linux x86_64 AVX high halves and Linux AArch64 FPSIMD extension records. |
13 | 13 |
|
| 14 | +#[cfg(target_arch = "aarch64")] |
| 15 | +use std::ops::{Deref, DerefMut}; |
| 16 | + |
14 | 17 | #[cfg(target_arch = "aarch64")] |
15 | 18 | #[repr(C)] |
16 | 19 | #[derive(Copy, Clone)] |
@@ -59,12 +62,74 @@ pub union XRegisters { |
59 | 62 | #[cfg(target_arch = "aarch64")] |
60 | 63 | #[repr(C)] |
61 | 64 | #[derive(Copy, Clone)] |
62 | | -pub struct FpRegisters { |
| 65 | +pub struct VRegistersNamed { |
| 66 | + pub v0: u128, |
| 67 | + pub v1: u128, |
| 68 | + pub v2: u128, |
| 69 | + pub v3: u128, |
| 70 | + pub v4: u128, |
| 71 | + pub v5: u128, |
| 72 | + pub v6: u128, |
| 73 | + pub v7: u128, |
| 74 | + pub v8: u128, |
| 75 | + pub v9: u128, |
| 76 | + pub v10: u128, |
| 77 | + pub v11: u128, |
| 78 | + pub v12: u128, |
| 79 | + pub v13: u128, |
| 80 | + pub v14: u128, |
| 81 | + pub v15: u128, |
| 82 | + pub v16: u128, |
| 83 | + pub v17: u128, |
| 84 | + pub v18: u128, |
| 85 | + pub v19: u128, |
| 86 | + pub v20: u128, |
| 87 | + pub v21: u128, |
| 88 | + pub v22: u128, |
| 89 | + pub v23: u128, |
| 90 | + pub v24: u128, |
| 91 | + pub v25: u128, |
| 92 | + pub v26: u128, |
| 93 | + pub v27: u128, |
| 94 | + pub v28: u128, |
| 95 | + pub v29: u128, |
| 96 | + pub v30: u128, |
| 97 | + pub v31: u128, |
| 98 | +} |
| 99 | + |
| 100 | +#[cfg(target_arch = "aarch64")] |
| 101 | +#[repr(C)] |
| 102 | +#[derive(Copy, Clone)] |
| 103 | +pub union VRegisters { |
63 | 104 | pub v: [u128; 32], |
| 105 | + pub named: VRegistersNamed, |
| 106 | +} |
| 107 | + |
| 108 | +#[cfg(target_arch = "aarch64")] |
| 109 | +#[repr(C)] |
| 110 | +#[derive(Copy, Clone)] |
| 111 | +pub struct FpRegisters { |
| 112 | + pub regs: VRegisters, |
64 | 113 | pub fpsr: u32, |
65 | 114 | pub fpcr: u32, |
66 | 115 | } |
67 | 116 |
|
| 117 | +#[cfg(target_arch = "aarch64")] |
| 118 | +impl Deref for FpRegisters { |
| 119 | + type Target = VRegisters; |
| 120 | + |
| 121 | + fn deref(&self) -> &Self::Target { |
| 122 | + &self.regs |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +#[cfg(target_arch = "aarch64")] |
| 127 | +impl DerefMut for FpRegisters { |
| 128 | + fn deref_mut(&mut self) -> &mut Self::Target { |
| 129 | + &mut self.regs |
| 130 | + } |
| 131 | +} |
| 132 | + |
68 | 133 | #[cfg(target_arch = "aarch64")] |
69 | 134 | #[repr(C)] |
70 | 135 | #[derive(Copy, Clone)] |
@@ -169,7 +234,11 @@ pub unsafe fn remap_ctx(uc: *mut libc::ucontext_t) -> *mut HookContext { |
169 | 234 | // registers directly into `HookContext`. |
170 | 235 | let mut fpregs = zeroed_fpregs(); |
171 | 236 | unsafe { |
172 | | - std::ptr::copy_nonoverlapping(ns.__v.as_ptr().cast::<u128>(), fpregs.v.as_mut_ptr(), 32); |
| 237 | + std::ptr::copy_nonoverlapping( |
| 238 | + ns.__v.as_ptr().cast::<u128>(), |
| 239 | + fpregs.regs.v.as_mut_ptr(), |
| 240 | + 32, |
| 241 | + ); |
173 | 242 | } |
174 | 243 | fpregs.fpsr = ns.__fpsr; |
175 | 244 | fpregs.fpcr = ns.__fpcr; |
@@ -212,7 +281,7 @@ pub unsafe fn write_back_ctx(uc: *mut libc::ucontext_t, ctx: *mut HookContext) { |
212 | 281 |
|
213 | 282 | unsafe { |
214 | 283 | std::ptr::copy_nonoverlapping( |
215 | | - ctx.fpregs.v.as_ptr(), |
| 284 | + ctx.fpregs.regs.v.as_ptr(), |
216 | 285 | ns.__v.as_mut_ptr().cast::<u128>(), |
217 | 286 | 32, |
218 | 287 | ); |
@@ -349,7 +418,7 @@ pub unsafe fn remap_ctx(uc: *mut libc::ucontext_t) -> *mut HookContext { |
349 | 418 | // `HookContext`; FP/SIMD state simply remains zero-initialized in that case. |
350 | 419 | if let Some(fpsimd) = unsafe { linux_aarch64_fpsimd_context(mcontext) } { |
351 | 420 | let fpsimd = unsafe { &*fpsimd }; |
352 | | - fpregs.v = fpsimd.vregs; |
| 421 | + fpregs.regs.v = fpsimd.vregs; |
353 | 422 | fpregs.fpsr = fpsimd.fpsr; |
354 | 423 | fpregs.fpcr = fpsimd.fpcr; |
355 | 424 | } |
@@ -389,7 +458,7 @@ pub unsafe fn write_back_ctx(uc: *mut libc::ucontext_t, ctx: *mut HookContext) { |
389 | 458 |
|
390 | 459 | if let Some(fpsimd) = unsafe { linux_aarch64_fpsimd_context(mcontext) } { |
391 | 460 | let fpsimd = unsafe { &mut *fpsimd }; |
392 | | - fpsimd.vregs = ctx.fpregs.v; |
| 461 | + fpsimd.vregs = ctx.fpregs.regs.v; |
393 | 462 | fpsimd.fpsr = ctx.fpregs.fpsr; |
394 | 463 | fpsimd.fpcr = ctx.fpregs.fpcr; |
395 | 464 | } |
@@ -812,3 +881,27 @@ pub unsafe fn free_ctx(ctx: *mut HookContext) { |
812 | 881 | let _ = unsafe { Box::from_raw(ctx) }; |
813 | 882 | } |
814 | 883 | } |
| 884 | + |
| 885 | +#[cfg(all(test, target_arch = "aarch64"))] |
| 886 | +mod tests { |
| 887 | + use super::{FpRegisters, VRegisters}; |
| 888 | + |
| 889 | + #[test] |
| 890 | + fn aarch64_fpreg_named_and_array_views_alias() { |
| 891 | + let mut fpregs = FpRegisters { |
| 892 | + regs: VRegisters { v: [0; 32] }, |
| 893 | + fpsr: 0, |
| 894 | + fpcr: 0, |
| 895 | + }; |
| 896 | + |
| 897 | + unsafe { |
| 898 | + fpregs.named.v0 = 0x11; |
| 899 | + fpregs.named.v31 = 0x22; |
| 900 | + assert_eq!(fpregs.v[0], 0x11); |
| 901 | + assert_eq!(fpregs.v[31], 0x22); |
| 902 | + |
| 903 | + fpregs.v[1] = 0x33; |
| 904 | + assert_eq!(fpregs.named.v1, 0x33); |
| 905 | + } |
| 906 | + } |
| 907 | +} |
0 commit comments