From a5d4ccba57886a4097310397bf4cf533abf7c4c2 Mon Sep 17 00:00:00 2001
From: uuuvn <uuuvn@uuuvn.space>
Date: Tue, 13 Jun 2023 10:15:47 +0000
Subject: [PATCH] More aarch64 stuff

---
 src/arch/aarch64/vectors.rs |  2 ++
 src/context/arch/aarch64.rs | 29 ++++++++++++++++++-----------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/src/arch/aarch64/vectors.rs b/src/arch/aarch64/vectors.rs
index 340cbdf8..49aede02 100644
--- a/src/arch/aarch64/vectors.rs
+++ b/src/arch/aarch64/vectors.rs
@@ -42,6 +42,8 @@ __vec_03:
     // Synchronous
     .align 7
 __vec_04:
+    mov x18, sp
+    and sp, x18, #0xfffffffffffffff0   // Align sp.
     mov     x18, #0xb0b4
     b       synchronous_exception_at_el1_with_spx
     b       __vec_04
diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs
index beceba52..d5804789 100644
--- a/src/context/arch/aarch64.rs
+++ b/src/context/arch/aarch64.rs
@@ -95,21 +95,29 @@ impl Context {
 
     pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) {
         let lr = self.lr.clone();
-        self.push_stack(lr);
-        self.push_stack(sig as usize);
-        self.push_stack(handler as usize);
+        self.push_pair((sig as usize, lr));
+        self.push_pair((0 as usize, handler as usize));
         self.set_lr(signal_handler_wrapper as usize);
     }
 
-    pub unsafe fn push_stack(&mut self, value: usize) {
+    // It isn't possible to implement "just push one value to stack" on aarch64
+    // https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/using-the-stack-in-aarch32-and-aarch64
+    // Looks like QEMU TCG doesn't care about it, so it works in it, but not on bare metal or kvm
+    // Reverese to be compatible with ldp and stp instructions
+    // TODO: optimize?
+    pub unsafe fn push_pair(&mut self, pair: (usize, usize)) {
         self.sp -= 1 * mem::size_of::<usize>();
-        *(self.sp as *mut usize) = value;
+        *(self.sp as *mut usize) = pair.1;
+        self.sp -= 1 * mem::size_of::<usize>();
+        *(self.sp as *mut usize) = pair.0;
     }
 
-    pub unsafe fn pop_stack(&mut self) -> usize {
-        let value = *(self.sp as *const usize);
+    pub unsafe fn pop_pair(&mut self) -> (usize, usize) {
+        let a = *(self.sp as *const usize);
+        self.sp += 1 * mem::size_of::<usize>();
+        let b = *(self.sp as *const usize);
         self.sp += 1 * mem::size_of::<usize>();
-        value
+        (a, b)
     }
 
     pub fn dump(&self) {
@@ -365,7 +373,6 @@ unsafe extern fn signal_handler_wrapper() {
     // Push scratch registers
     core::arch::asm!(
         concat!(
-            "sub sp, sp, 8",
             push_scratch!(),
             "
             mov x0, sp
@@ -373,8 +380,8 @@ unsafe extern fn signal_handler_wrapper() {
             ",
             pop_scratch!(),
             "
-            add sp, sp, 24
-            ldr x30, [sp], #8
+            add sp, sp, 32
+            ldr x30, [sp, #-8]
             ret
             "
         ),
-- 
GitLab