summaryrefslogtreecommitdiffstats
path: root/third_party/rust/crash-context/src/linux/getcontext/aarch64.rs
diff options
context:
space:
mode:
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.rs86
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",
+}