Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 3 | #include <stdint.h> |
| 4 | |
| 5 | #if ENV_X86_64 |
Patrick Rudolph | b4283a4 | 2023-12-28 07:44:26 +0100 | [diff] [blame^] | 6 | /* |
| 7 | * Assembly code that drops into protected mode and calls the function |
| 8 | * specified as first argument, which must have been compiled for x86_32. |
| 9 | * After the function returns it enters long mode again. |
| 10 | * The function pointer destination must be below 4GiB in physical memory. |
| 11 | * |
| 12 | * The called function has 0-3 arguments and returns an int. |
| 13 | */ |
| 14 | int protected_mode_call_3arg(uint32_t func_ptr, |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 15 | uint32_t opt_arg1, |
Patrick Rudolph | b4283a4 | 2023-12-28 07:44:26 +0100 | [diff] [blame^] | 16 | uint32_t opt_arg2, |
| 17 | uint32_t opt_arg3); |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 18 | |
| 19 | /* |
| 20 | * Drops into protected mode and calls the function, which must have been compiled for x86_32. |
| 21 | * After the function returns it enters long mode again. |
| 22 | * The function pointer destination must be below 4GiB in physical memory. |
| 23 | * |
| 24 | * The called function doesn't have arguments and returns an int. |
| 25 | */ |
| 26 | static inline int protected_mode_call(void *func) |
| 27 | { |
Patrick Rudolph | b4283a4 | 2023-12-28 07:44:26 +0100 | [diff] [blame^] | 28 | return protected_mode_call_3arg((uintptr_t)func, 0, 0, 0); |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | /* |
| 32 | * Drops into protected mode and calls the function, which must have been compiled for x86_32. |
| 33 | * After the function returns it enters long mode again. |
| 34 | * The function pointer destination must be below 4GiB in physical memory. |
| 35 | * Only the lower 32bits of the argument are passed to the called function. |
| 36 | * |
| 37 | * The called function have one argument and returns an int. |
| 38 | */ |
| 39 | static inline int protected_mode_call_1arg(void *func, uint32_t arg1) |
| 40 | { |
Patrick Rudolph | b4283a4 | 2023-12-28 07:44:26 +0100 | [diff] [blame^] | 41 | return protected_mode_call_3arg((uintptr_t)func, arg1, 0, 0); |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 42 | } |
| 43 | |
| 44 | /* |
| 45 | * Drops into protected mode and calls the function, which must have been compiled for x86_32. |
| 46 | * After the function returns it enters long mode again. |
| 47 | * The function pointer destination must be below 4GiB in physical memory. |
| 48 | * Only the lower 32bits of the argument are passed to the called function. |
| 49 | * |
| 50 | * The called function has two arguments and returns an int. |
| 51 | */ |
| 52 | static inline int protected_mode_call_2arg(void *func, uint32_t arg1, uint32_t arg2) |
| 53 | { |
Patrick Rudolph | b4283a4 | 2023-12-28 07:44:26 +0100 | [diff] [blame^] | 54 | return protected_mode_call_3arg((uintptr_t)func, arg1, arg2, 0); |
Patrick Rudolph | 7a35949 | 2020-11-30 15:56:59 +0100 | [diff] [blame] | 55 | } |
| 56 | #else |
| 57 | static inline int protected_mode_call(void *func) |
| 58 | { |
| 59 | int (*doit)(void) = func; |
| 60 | |
| 61 | return doit(); |
| 62 | } |
| 63 | |
| 64 | static inline int protected_mode_call_1arg(void *func, uint32_t arg1) |
| 65 | { |
| 66 | int (*doit)(uint32_t arg1) = func; |
| 67 | |
| 68 | return doit(arg1); |
| 69 | } |
| 70 | |
| 71 | static inline int protected_mode_call_2arg(void *func, uint32_t arg1, uint32_t arg2) |
| 72 | { |
| 73 | int (*doit)(uint32_t arg1, uint32_t arg2) = func; |
| 74 | |
| 75 | return doit(arg1, arg2); |
| 76 | } |
| 77 | #endif |