diff options
Diffstat (limited to 'third_party/rust/crash-context/src/linux/getcontext/aarch64.rs')
-rw-r--r-- | third_party/rust/crash-context/src/linux/getcontext/aarch64.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/third_party/rust/crash-context/src/linux/getcontext/aarch64.rs b/third_party/rust/crash-context/src/linux/getcontext/aarch64.rs new file mode 100644 index 0000000000..3cc7e66c97 --- /dev/null +++ b/third_party/rust/crash-context/src/linux/getcontext/aarch64.rs @@ -0,0 +1,86 @@ +// GREGS_OFFSET = 184 +// REGISTER_SIZE = 8 +// SIMD_REGISTER_SIZE = 16 + +std::arch::global_asm! { + ".text", + ".global crash_context_getcontext", + ".hidden crash_context_getcontext", + ".type crash_context_getcontext, #function", + ".align 4", + ".cfi_startproc", +"crash_context_getcontext:", + + // The saved context will return to the getcontext() call point + // with a return value of 0 + "str xzr, [x0, 184]", // GREGS_OFFSET + + "stp x18, x19, [x0, 328]", // GREGS_OFFSET + 18 * REGISTER_SIZE + "stp x20, x21, [x0, 344]", // GREGS_OFFSET + 20 * REGISTER_SIZE + "stp x22, x23, [x0, 360]", // GREGS_OFFSET + 22 * REGISTER_SIZE + "stp x24, x25, [x0, 376]", // GREGS_OFFSET + 24 * REGISTER_SIZE + "stp x26, x27, [x0, 392]", // GREGS_OFFSET + 26 * REGISTER_SIZE + "stp x28, x29, [x0, 408]", // GREGS_OFFSET + 28 * REGISTER_SIZE + "str x30, [x0, 424]", // GREGS_OFFSET + 30 * REGISTER_SIZE + + // Place LR into the saved PC, this will ensure that when switching to this + // saved context with setcontext() control will pass back to the caller of + // getcontext(), we have already arranged to return the appropriate return + // value in x0 above. + "str x30, [x0, 440]", + + // Save the current SP + "mov x2, sp", + "str x2, [x0, 432]", + + // Initialize the pstate. + "str xzr, [x0, 448]", + + // Figure out where to place the first context extension block. + "add x2, x0, #464", + + // Write the context extension fpsimd header. + // FPSIMD_MAGIC = 0x46508001 + "mov w3, #(0x46508001 & 0xffff)", + "movk w3, #(0x46508001 >> 16), lsl #16", + "str w3, [x2, #0]", // FPSIMD_CONTEXT_MAGIC_OFFSET + "mov w3, #528", // FPSIMD_CONTEXT_SIZE + "str w3, [x2, #4]", // FPSIMD_CONTEXT_SIZE_OFFSET + + // Fill in the FP SIMD context. + "add x3, x2, #144", // VREGS_OFFSET + 8 * SIMD_REGISTER_SIZE + "stp d8, d9, [x3], #32", + "stp d10, d11, [x3], #32", + "stp d12, d13, [x3], #32", + "stp d14, d15, [x3], #32", + + "add x3, x2, 8", // FPSR_OFFSET + + "mrs x4, fpsr", + "str w4, [x3]", + + "mrs x4, fpcr", + "str w4, [x3, 4]", // FPCR_OFFSET - FPSR_OFFSET + + // Write the termination context extension header. + "add x2, x2, #528", // FPSIMD_CONTEXT_SIZE + + "str xzr, [x2, #0]", // FPSIMD_CONTEXT_MAGIC_OFFSET + "str xzr, [x2, #4]", // FPSIMD_CONTEXT_SIZE_OFFSET + + // Grab the signal mask + // rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) + "add x2, x0, #40", // UCONTEXT_SIGMASK_OFFSET + "mov x0, #0", // SIG_BLOCK + "mov x1, #0", // NULL + "mov x3, #(64 / 8)", // _NSIG / 8 + "mov x8, #135", // __NR_rt_sigprocmask + "svc 0", + + // Return x0 for success + "mov x0, 0", + "ret", + + ".cfi_endproc", + ".size crash_context_getcontext, . - crash_context_getcontext", +} |