]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/syscall_shim/arch/arm64: Store caller's link register
authorSergiu Moga <sergiu@unikraft.io>
Mon, 24 Mar 2025 16:42:17 +0000 (18:42 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Thu, 17 Apr 2025 12:33:46 +0000 (12:33 +0000)
So far for storing LR and ELR_EL1 we have been using the current
link register for both instead. This does not reflect reality when
it comes to LR as we should instead store the LR that the caller
would know. To achieve this, do a brief level 1 stack unwinding and
fetch caller's LR from the top of its frame.

Signed-off-by: Sergiu Moga <sergiu@unikraft.io>
Approved-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Andrei Tatar <andrei@unikraft.io>
GitHub-Closes: #1618

lib/syscall_shim/arch/arm64/include/arch/syscall_prologue.h

index c04659bf124f873b09abc0b4ef1bb9e998ea834a..e1103815c7068bde6af1fe4996ae444bd06ab303 100644 (file)
                "stp    x24, x25, [sp, #16 * 12]\n\t"                   \
                "stp    x26, x27, [sp, #16 * 13]\n\t"                   \
                "stp    x28, x29, [sp, #16 * 14]\n\t"                   \
-               "/* Here we should push lr and elr_el1, however\n\t"    \
+               "/* Here we should push elr_el1, however\n\t"           \
                " * we are not in an actual exception, but instead\n\t" \
                " * we are trying to emulate a SVC with a function\n\t" \
                " * call which makes elr_el1 invalid and we instead\n\t"\
-               " * double push lr (x30).\n\t"                          \
+               " * push lr (x30).\n\t"                                 \
                " */\n\t"                                               \
-               "stp    x30, x30, [sp, #16 * 15]\n\t"                   \
+               "str    x30, [sp, #16 * 15 + 8]\n\t"                    \
+               "/* Here we should push lr, however\n\t"                \
+               " * our lr has been overwritten with the return\n\t"    \
+               " * address back to the caller itself, so we will\n\t"  \
+               " * have to do a little bit of a level 1 stack\n\t"     \
+               " * stack unwinding. In the process we\n\t"             \
+               " * are dirtying lr but this is fine because we are\n\t"\
+               " * restoring it at the end anyway.\n\t"                \
+               " */\n\t"                                               \
+               "/* Get previous frame address */\n\t"                  \
+               "ldr    x30, [x29]\n\t"                                 \
+               "/* lr is typically saved at offset 8 from new\n\t"     \
+               " * frame\n\t"                                          \
+               " */\n\t"                                               \
+               "ldr    x30, [x29, #8]\n\t"                             \
+               "str    x30, [sp, #16 * 15]\n\t"                        \
                "/* Just like above for elr_el1, spsr_el1 is also\n\t"  \
                " * invalid. Therefore we use a sane default value\n\t" \
                " * which one would normally see in spsr_el1\n\t"       \
                "ldp    x22, x23, [sp, #16 * 11]\t\n"                   \
                "ldp    x20, x21, [sp, #16 * 10]\t\n"                   \
                "ldp    x18, x19, [sp, #16 * 9]\t\n"                    \
-               "/* Restore rsp from where it was stored */\n\t"        \
+               "/* Restore sp from where it was stored */\n\t"         \
                "ldr    x9, [sp, #" STRINGIFY(__SP_OFFSET) "]\n\t"      \
                "mov    sp, x9\n\t"                                     \
                "ret\n\t"                                               \