diff options
author | Patrick Rudolph <patrick.rudolph@9elements.com> | 2023-12-28 07:45:19 +0100 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-01-05 14:33:22 +0000 |
commit | 3052e9e6421cd5926b2b668c96a4d9cc040fcbf9 (patch) | |
tree | 6332ebd4f20f7ce0c36fd7d0267a019dbb0e799f /src/cpu/x86 | |
parent | 8e7251c6257aa59fc73ae1f64c278341bfde4c95 (diff) |
cpu/x86/64bit/mode_switch2: The reverse function to mode_switch
Add another mode_switch assembly function to call x86_64 code from
x86_32 code. This is particullary useful for BLOBs like mrc.bin or
FSP that calls back into coreboot.
The user must first wrap all functions that are to be called from
x86_32 using the macro prot2lm_wrapper. Instead of using the original
function the wrapped functions must be passed to the x86_32 BLOBs.
The assembly code assume that 0-3 32bit arguments are passed to
the wrapped function.
Tested:
- Called x86_64 code from x86_32 code in qemu.
- Booted Lenovo X220 using x86_32 MRC using x86_64 console.
Change-Id: Ib625233e5f673eae9f3dcb2d03004c06bb07b149
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/79753
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src/cpu/x86')
-rw-r--r-- | src/cpu/x86/64bit/Makefile.inc | 1 | ||||
-rw-r--r-- | src/cpu/x86/64bit/mode_switch2.S | 48 | ||||
-rw-r--r-- | src/cpu/x86/64bit/prot2long.inc | 27 |
3 files changed, 76 insertions, 0 deletions
diff --git a/src/cpu/x86/64bit/Makefile.inc b/src/cpu/x86/64bit/Makefile.inc index e1cf743f6c..24a5a966fb 100644 --- a/src/cpu/x86/64bit/Makefile.inc +++ b/src/cpu/x86/64bit/Makefile.inc @@ -1,6 +1,7 @@ ## SPDX-License-Identifier: GPL-2.0-only all_x86-y += mode_switch.S +all_x86-y += mode_switch2.S # Add --defsym=_start=0 to suppress a linker warning. $(objcbfs)/pt: $(dir)/pt.S $(obj)/config.h diff --git a/src/cpu/x86/64bit/mode_switch2.S b/src/cpu/x86/64bit/mode_switch2.S new file mode 100644 index 0000000000..65e9d94a98 --- /dev/null +++ b/src/cpu/x86/64bit/mode_switch2.S @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Calls a x86_64 function from x86_32 context. + * Must not be directly invoked from C code! + */ + +.text +.code32 + .section ".text.long_mode_call_3arg", "ax", @progbits + .global long_mode_call_3arg +long_mode_call_3arg: + + /* Function to call is passed in EAX. */ + + /* Backup registers */ + pushal + + /* Backup stack pointer */ + mov %esp, %ebp + + /* Enter long mode, preserves ebx */ + #include <cpu/x86/64bit/entry64.inc> + + /* Align stack */ + movabs $0xfffffffffffffff0, %rax + andq %rax, %rsp + + movl 28(%rbp), %ebx /* Function to call */ + movl 36(%rbp), %edi /* 1st arg */ + movl 40(%rbp), %esi /* 2nd arg */ + movl 44(%rbp), %edx /* 3rd arg */ + + call *%rbx + + /* Store return value on stack. popal will fetch it. */ + mov %eax, 28(%rbp) + shr $32, %rax + movl %eax, 24(%rbp) + + #include <cpu/x86/64bit/exit32.inc> + + /* Restore stack pointer */ + mov %ebp, %esp + + /* Restore registers */ + popal + + ret diff --git a/src/cpu/x86/64bit/prot2long.inc b/src/cpu/x86/64bit/prot2long.inc new file mode 100644 index 0000000000..96c44a86f5 --- /dev/null +++ b/src/cpu/x86/64bit/prot2long.inc @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +.text +.code32 +/* + * Macro to wrap a x86_64 function to be called from x86_32 code. + * This assumes that 0-3 32bit arguments are passed to the + * calling function. + * + * In order to preserve ESP without setting up a stack frame + * pass the function to call in EAX. The macro prepends "__prot2lm_" + * to the wrapped function name. + */ +.macro prot2lm_wrapper func2call:req + .global __prot2lm_\func2call +__prot2lm_\func2call : + /* Get function to call */ + mov $\func2call, %eax + + /* + * Jump to function instead of call. + * It will return directly to caller. + */ + jmp long_mode_call_3arg + + /* Not reachable */ +.endm |