From ef97219463c1d4d6061adb1bf93e234674da3f5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Mar 2024 11:35:24 +0100 Subject: [PATCH] 6.1-stable patches added patches: decompress-use-8-byte-alignment.patch efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch efi-verify-that-variable-services-are-supported.patch x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch x86-decompressor-assign-paging-related-global-variables-earlier.patch x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch x86-decompressor-call-trampoline-as-a-normal-function.patch x86-decompressor-call-trampoline-directly-from-c-code.patch x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch x86-decompressor-move-global-symbol-references-to-c-code.patch x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch x86-decompressor-use-standard-calling-convention-for-trampoline.patch x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch --- .../decompress-use-8-byte-alignment.patch | 31 ++ ...ion-when-moving-the-kernel-in-memory.patch | 126 +++++ ...that-variable-services-are-supported.patch | 71 +++ queue-6.1/series | 32 ++ ...convention-in-get_sev_encryption_bit.patch | 69 +++ ...ching-ecx-in-startup32_set_idt_entry.patch | 55 +++ ...definitions-of-image_offset-into-one.patch | 72 +++ ...t-entrypoint-code-into-.text-section.patch | 98 ++++ ...s-parsing-out-of-32-bit-startup-code.patch | 115 +++++ ...ed-move-efi32_entry-out-of-head_64.s.patch | 163 +++++++ ...ve-efi32_pe_entry-into-.text-section.patch | 63 +++ ...move-efi32_pe_entry-out-of-head_64.s.patch | 216 +++++++++ ...-startup32_check_sev_cbit-into-.text.patch | 113 +++++ ...up32_check_sev_cbit-out-of-head_64.s.patch | 179 +++++++ ...tartup32_load_idt-into-.text-section.patch | 99 ++++ ...-startup32_load_idt-out-of-head_64.s.patch | 202 ++++++++ ...d-mem_encrypt.s-if-amd_mem_encrypt-y.patch | 47 ++ ...le-reference-into-startup32_load_idt.patch | 77 +++ ...rename-efi_thunk_64.s-to-efi-mixed.s.patch | 441 ++++++++++++++++++ ...dt-preserve-restore-in-the-efi-thunk.patch | 64 +++ ...up_-32-64-from-the-decompressor-code.patch | 141 ++++++ ...ing-related-global-variables-earlier.patch | 63 +++ ...for-a-stack-in-the-32-bit-trampoline.patch | 185 ++++++++ ...call-trampoline-as-a-normal-function.patch | 166 +++++++ ...call-trampoline-directly-from-c-code.patch | 189 ++++++++ ...ampoline-cleanup-with-switching-code.patch | 87 ++++ ...e-global-symbol-references-to-c-code.patch | 132 ++++++ ...ampoline-when-changing-paging-levels.patch | 166 +++++++ ...table-address-to-trampoline-directly.patch | 101 ++++ ...rams-pointer-in-callee-save-register.patch | 160 +++++++ ...rd-calling-convention-for-trampoline.patch | 109 +++++ ...cated-efi-handover-protocol-optional.patch | 136 ++++++ ...ht-to-kernel-entry-point-from-c-code.patch | 69 +++ 33 files changed, 4037 insertions(+) create mode 100644 queue-6.1/decompress-use-8-byte-alignment.patch create mode 100644 queue-6.1/efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch create mode 100644 queue-6.1/efi-verify-that-variable-services-are-supported.patch create mode 100644 queue-6.1/x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch create mode 100644 queue-6.1/x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch create mode 100644 queue-6.1/x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch create mode 100644 queue-6.1/x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch create mode 100644 queue-6.1/x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch create mode 100644 queue-6.1/x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch create mode 100644 queue-6.1/x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch create mode 100644 queue-6.1/x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch create mode 100644 queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch create mode 100644 queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch create mode 100644 queue-6.1/x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch create mode 100644 queue-6.1/x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch create mode 100644 queue-6.1/x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch create mode 100644 queue-6.1/x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch create mode 100644 queue-6.1/x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch create mode 100644 queue-6.1/x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch create mode 100644 queue-6.1/x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch create mode 100644 queue-6.1/x86-decompressor-assign-paging-related-global-variables-earlier.patch create mode 100644 queue-6.1/x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch create mode 100644 queue-6.1/x86-decompressor-call-trampoline-as-a-normal-function.patch create mode 100644 queue-6.1/x86-decompressor-call-trampoline-directly-from-c-code.patch create mode 100644 queue-6.1/x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch create mode 100644 queue-6.1/x86-decompressor-move-global-symbol-references-to-c-code.patch create mode 100644 queue-6.1/x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch create mode 100644 queue-6.1/x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch create mode 100644 queue-6.1/x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch create mode 100644 queue-6.1/x86-decompressor-use-standard-calling-convention-for-trampoline.patch create mode 100644 queue-6.1/x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch create mode 100644 queue-6.1/x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch diff --git a/queue-6.1/decompress-use-8-byte-alignment.patch b/queue-6.1/decompress-use-8-byte-alignment.patch new file mode 100644 index 00000000000..b108d74a11a --- /dev/null +++ b/queue-6.1/decompress-use-8-byte-alignment.patch @@ -0,0 +1,31 @@ +From 8217ad0a435ff06d651d7298ea8ae8d72388179e Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:15 +0200 +Subject: decompress: Use 8 byte alignment + +From: Ard Biesheuvel + +commit 8217ad0a435ff06d651d7298ea8ae8d72388179e upstream. + +The ZSTD decompressor requires malloc() allocations to be 8 byte +aligned, so ensure that this the case. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-19-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/decompress/mm.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/decompress/mm.h ++++ b/include/linux/decompress/mm.h +@@ -48,7 +48,7 @@ MALLOC_VISIBLE void *malloc(int size) + if (!malloc_ptr) + malloc_ptr = free_mem_ptr; + +- malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ ++ malloc_ptr = (malloc_ptr + 7) & ~7; /* Align */ + + p = (void *)malloc_ptr; + malloc_ptr += size; diff --git a/queue-6.1/efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch b/queue-6.1/efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch new file mode 100644 index 00000000000..2000334c199 --- /dev/null +++ b/queue-6.1/efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch @@ -0,0 +1,126 @@ +From 9cf42bca30e98a1c6c9e8abf876940a551eaa3d1 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 2 Aug 2022 11:00:16 +0200 +Subject: efi: libstub: use EFI_LOADER_CODE region when moving the kernel in memory + +From: Ard Biesheuvel + +commit 9cf42bca30e98a1c6c9e8abf876940a551eaa3d1 upstream. + +The EFI spec is not very clear about which permissions are being given +when allocating pages of a certain type. However, it is quite obvious +that EFI_LOADER_CODE is more likely to permit execution than +EFI_LOADER_DATA, which becomes relevant once we permit booting the +kernel proper with the firmware's 1:1 mapping still active. + +Ostensibly, recent systems such as the Surface Pro X grant executable +permissions to EFI_LOADER_CODE regions but not EFI_LOADER_DATA regions. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/efi/libstub/alignedmem.c | 5 +++-- + drivers/firmware/efi/libstub/arm64-stub.c | 6 ++++-- + drivers/firmware/efi/libstub/efistub.h | 6 ++++-- + drivers/firmware/efi/libstub/mem.c | 3 ++- + drivers/firmware/efi/libstub/randomalloc.c | 5 +++-- + 5 files changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/firmware/efi/libstub/alignedmem.c ++++ b/drivers/firmware/efi/libstub/alignedmem.c +@@ -22,7 +22,8 @@ + * Return: status code + */ + efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, +- unsigned long max, unsigned long align) ++ unsigned long max, unsigned long align, ++ int memory_type) + { + efi_physical_addr_t alloc_addr; + efi_status_t status; +@@ -36,7 +37,7 @@ efi_status_t efi_allocate_pages_aligned( + slack = align / EFI_PAGE_SIZE - 1; + + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, +- EFI_LOADER_DATA, size / EFI_PAGE_SIZE + slack, ++ memory_type, size / EFI_PAGE_SIZE + slack, + &alloc_addr); + if (status != EFI_SUCCESS) + return status; +--- a/drivers/firmware/efi/libstub/arm64-stub.c ++++ b/drivers/firmware/efi/libstub/arm64-stub.c +@@ -180,7 +180,8 @@ efi_status_t handle_kernel_image(unsigne + * locate the kernel at a randomized offset in physical memory. + */ + status = efi_random_alloc(*reserve_size, min_kimg_align, +- reserve_addr, phys_seed); ++ reserve_addr, phys_seed, ++ EFI_LOADER_CODE); + if (status != EFI_SUCCESS) + efi_warn("efi_random_alloc() failed: 0x%lx\n", status); + } else { +@@ -201,7 +202,8 @@ efi_status_t handle_kernel_image(unsigne + } + + status = efi_allocate_pages_aligned(*reserve_size, reserve_addr, +- ULONG_MAX, min_kimg_align); ++ ULONG_MAX, min_kimg_align, ++ EFI_LOADER_CODE); + + if (status != EFI_SUCCESS) { + efi_err("Failed to relocate kernel\n"); +--- a/drivers/firmware/efi/libstub/efistub.h ++++ b/drivers/firmware/efi/libstub/efistub.h +@@ -880,7 +880,8 @@ void efi_get_virtmap(efi_memory_desc_t * + efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); + + efi_status_t efi_random_alloc(unsigned long size, unsigned long align, +- unsigned long *addr, unsigned long random_seed); ++ unsigned long *addr, unsigned long random_seed, ++ int memory_type); + + efi_status_t efi_random_get_seed(void); + +@@ -907,7 +908,8 @@ efi_status_t efi_allocate_pages(unsigned + unsigned long max); + + efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, +- unsigned long max, unsigned long align); ++ unsigned long max, unsigned long align, ++ int memory_type); + + efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, + unsigned long *addr, unsigned long min); +--- a/drivers/firmware/efi/libstub/mem.c ++++ b/drivers/firmware/efi/libstub/mem.c +@@ -91,7 +91,8 @@ efi_status_t efi_allocate_pages(unsigned + + if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE) + return efi_allocate_pages_aligned(size, addr, max, +- EFI_ALLOC_ALIGN); ++ EFI_ALLOC_ALIGN, ++ EFI_LOADER_DATA); + + alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1; + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, +--- a/drivers/firmware/efi/libstub/randomalloc.c ++++ b/drivers/firmware/efi/libstub/randomalloc.c +@@ -53,7 +53,8 @@ static unsigned long get_entry_num_slots + efi_status_t efi_random_alloc(unsigned long size, + unsigned long align, + unsigned long *addr, +- unsigned long random_seed) ++ unsigned long random_seed, ++ int memory_type) + { + unsigned long total_slots = 0, target_slot; + unsigned long total_mirrored_slots = 0; +@@ -118,7 +119,7 @@ efi_status_t efi_random_alloc(unsigned l + pages = size / EFI_PAGE_SIZE; + + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, +- EFI_LOADER_DATA, pages, &target); ++ memory_type, pages, &target); + if (status == EFI_SUCCESS) + *addr = target; + break; diff --git a/queue-6.1/efi-verify-that-variable-services-are-supported.patch b/queue-6.1/efi-verify-that-variable-services-are-supported.patch new file mode 100644 index 00000000000..49892451ff5 --- /dev/null +++ b/queue-6.1/efi-verify-that-variable-services-are-supported.patch @@ -0,0 +1,71 @@ +From bad267f9e18f8e9e628abd1811d2899b1735a4e1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 19 Jan 2023 17:42:54 +0100 +Subject: efi: verify that variable services are supported + +From: Johan Hovold + +commit bad267f9e18f8e9e628abd1811d2899b1735a4e1 upstream. + +Current Qualcomm UEFI firmware does not implement the variable services +but not all revisions clear the corresponding bits in the RT_PROP table +services mask and instead the corresponding calls return +EFI_UNSUPPORTED. + +This leads to efi core registering the generic efivar ops even when the +variable services are not supported or when they are accessed through +some other interface (e.g. Google SMI or the upcoming Qualcomm SCM +implementation). + +Instead of playing games with init call levels to make sure that the +custom implementations are registered after the generic one, make sure +that get_next_variable() is actually supported before registering the +generic ops. + +Signed-off-by: Johan Hovold +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/efi/efi.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -185,8 +185,27 @@ static const struct attribute_group efi_ + static struct efivars generic_efivars; + static struct efivar_operations generic_ops; + ++static bool generic_ops_supported(void) ++{ ++ unsigned long name_size; ++ efi_status_t status; ++ efi_char16_t name; ++ efi_guid_t guid; ++ ++ name_size = sizeof(name); ++ ++ status = efi.get_next_variable(&name_size, &name, &guid); ++ if (status == EFI_UNSUPPORTED) ++ return false; ++ ++ return true; ++} ++ + static int generic_ops_register(void) + { ++ if (!generic_ops_supported()) ++ return 0; ++ + generic_ops.get_variable = efi.get_variable; + generic_ops.get_next_variable = efi.get_next_variable; + generic_ops.query_variable_store = efi_query_variable_store; +@@ -200,6 +219,9 @@ static int generic_ops_register(void) + + static void generic_ops_unregister(void) + { ++ if (!generic_ops.get_variable) ++ return; ++ + efivars_unregister(&generic_efivars); + } + diff --git a/queue-6.1/series b/queue-6.1/series index 50ad2f186ad..daa18aaf2aa 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -107,3 +107,35 @@ mptcp-fix-double-free-on-socket-dismantle.patch mptcp-fix-possible-deadlock-in-subflow-diag.patch rdma-core-refactor-rdma_bind_addr.patch rdma-core-update-cma-destination-address-on-rdma_resolve_addr.patch +efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch +x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch +x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch +x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch +x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch +x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch +x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch +x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch +x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch +x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch +x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch +x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch +x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch +x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch +x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch +x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch +x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch +efi-verify-that-variable-services-are-supported.patch +x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch +x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch +x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch +x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch +x86-decompressor-assign-paging-related-global-variables-earlier.patch +x86-decompressor-call-trampoline-as-a-normal-function.patch +x86-decompressor-use-standard-calling-convention-for-trampoline.patch +x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch +x86-decompressor-call-trampoline-directly-from-c-code.patch +x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch +x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch +x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch +x86-decompressor-move-global-symbol-references-to-c-code.patch +decompress-use-8-byte-alignment.patch diff --git a/queue-6.1/x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch b/queue-6.1/x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch new file mode 100644 index 00000000000..3cffd86b77b --- /dev/null +++ b/queue-6.1/x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch @@ -0,0 +1,69 @@ +From 30c9ca16a5271ba6f8ad9c86507ff1c789c94677 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:15 +0100 +Subject: x86/boot/compressed: Adhere to calling convention in get_sev_encryption_bit() + +From: Ard Biesheuvel + +commit 30c9ca16a5271ba6f8ad9c86507ff1c789c94677 upstream. + +Make get_sev_encryption_bit() follow the ordinary i386 calling +convention, and only call it if CONFIG_AMD_MEM_ENCRYPT is actually +enabled. This clarifies the calling code, and makes it more +maintainable. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-16-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 5 +++-- + arch/x86/boot/compressed/mem_encrypt.S | 10 ---------- + 2 files changed, 3 insertions(+), 12 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -180,12 +180,13 @@ SYM_FUNC_START(startup_32) + */ + /* + * If SEV is active then set the encryption mask in the page tables. +- * This will insure that when the kernel is copied and decompressed ++ * This will ensure that when the kernel is copied and decompressed + * it will be done so encrypted. + */ +- call get_sev_encryption_bit + xorl %edx, %edx + #ifdef CONFIG_AMD_MEM_ENCRYPT ++ call get_sev_encryption_bit ++ xorl %edx, %edx + testl %eax, %eax + jz 1f + subl $32, %eax /* Encryption bit is always above bit 31 */ +--- a/arch/x86/boot/compressed/mem_encrypt.S ++++ b/arch/x86/boot/compressed/mem_encrypt.S +@@ -18,12 +18,7 @@ + .text + .code32 + SYM_FUNC_START(get_sev_encryption_bit) +- xor %eax, %eax +- +-#ifdef CONFIG_AMD_MEM_ENCRYPT + push %ebx +- push %ecx +- push %edx + + movl $0x80000000, %eax /* CPUID to check the highest leaf */ + cpuid +@@ -54,12 +49,7 @@ SYM_FUNC_START(get_sev_encryption_bit) + xor %eax, %eax + + .Lsev_exit: +- pop %edx +- pop %ecx + pop %ebx +- +-#endif /* CONFIG_AMD_MEM_ENCRYPT */ +- + RET + SYM_FUNC_END(get_sev_encryption_bit) + diff --git a/queue-6.1/x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch b/queue-6.1/x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch new file mode 100644 index 00000000000..5d56173c213 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch @@ -0,0 +1,55 @@ +From 6aac80a8da46d70f2ae7ff97c9f45a15c7c9b3ef Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:09 +0100 +Subject: x86/boot/compressed: Avoid touching ECX in startup32_set_idt_entry() + +From: Ard Biesheuvel + +commit 6aac80a8da46d70f2ae7ff97c9f45a15c7c9b3ef upstream. + +Avoid touching register %ecx in startup32_set_idt_entry(), by folding +the MOV, SHL and ORL instructions into a single ORL which no longer +requires a temp register. + +This permits ECX to be used as a function argument in a subsequent +patch. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-10-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -749,7 +749,6 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLO + */ + SYM_FUNC_START(startup32_set_idt_entry) + push %ebx +- push %ecx + + /* IDT entry address to %ebx */ + leal rva(boot32_idt)(%ebp), %ebx +@@ -758,10 +757,8 @@ SYM_FUNC_START(startup32_set_idt_entry) + + /* Build IDT entry, lower 4 bytes */ + movl %eax, %edx +- andl $0x0000ffff, %edx # Target code segment offset [15:0] +- movl $__KERNEL32_CS, %ecx # Target code segment selector +- shl $16, %ecx +- orl %ecx, %edx ++ andl $0x0000ffff, %edx # Target code segment offset [15:0] ++ orl $(__KERNEL32_CS << 16), %edx # Target code segment selector + + /* Store lower 4 bytes to IDT */ + movl %edx, (%ebx) +@@ -774,7 +771,6 @@ SYM_FUNC_START(startup32_set_idt_entry) + /* Store upper 4 bytes to IDT */ + movl %edx, 4(%ebx) + +- pop %ecx + pop %ebx + RET + SYM_FUNC_END(startup32_set_idt_entry) diff --git a/queue-6.1/x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch b/queue-6.1/x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch new file mode 100644 index 00000000000..9b54a3e6ea6 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch @@ -0,0 +1,72 @@ +From 4b52016247aeaa55ca3e3bc2e03cd91114c145c2 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:07 +0100 +Subject: x86/boot/compressed, efi: Merge multiple definitions of image_offset into one + +From: Ard Biesheuvel + +commit 4b52016247aeaa55ca3e3bc2e03cd91114c145c2 upstream. + +There is no need for head_32.S and head_64.S both declaring a copy of +the global 'image_offset' variable, so drop those and make the extern C +declaration the definition. + +When image_offset is moved to the .c file, it needs to be placed +particularly in the .data section because it lands by default in the +.bss section which is cleared too late, in .Lrelocated, before the first +access to it and thus garbage gets read, leading to SEV guests exploding +in early boot. + +This happens only when the SEV guest kernel is loaded through grub. If +supplied with qemu's -kernel command line option, that memory is always +cleared upfront by qemu and all is fine there. + + [ bp: Expand commit message with SEV aspect. ] + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-8-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_32.S | 4 ---- + arch/x86/boot/compressed/head_64.S | 4 ---- + drivers/firmware/efi/libstub/x86-stub.c | 2 +- + 3 files changed, 1 insertion(+), 9 deletions(-) + +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -208,10 +208,6 @@ SYM_DATA_START_LOCAL(gdt) + .quad 0x00cf92000000ffff /* __KERNEL_DS */ + SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end) + +-#ifdef CONFIG_EFI_STUB +-SYM_DATA(image_offset, .long 0) +-#endif +- + /* + * Stack and heap for uncompression + */ +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -734,10 +734,6 @@ SYM_DATA_START(boot32_idt) + SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLOBAL, boot32_idt_end) + #endif + +-#ifdef CONFIG_EFI_STUB +-SYM_DATA(image_offset, .long 0) +-#endif +- + #ifdef CONFIG_AMD_MEM_ENCRYPT + __HEAD + .code32 +--- a/drivers/firmware/efi/libstub/x86-stub.c ++++ b/drivers/firmware/efi/libstub/x86-stub.c +@@ -23,7 +23,7 @@ + + const efi_system_table_t *efi_system_table; + const efi_dxe_services_table_t *efi_dxe_table; +-extern u32 image_offset; ++u32 image_offset __section(".data"); + static efi_loaded_image_t *image = NULL; + + static efi_status_t diff --git a/queue-6.1/x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch b/queue-6.1/x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch new file mode 100644 index 00000000000..9a9c7be7560 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch @@ -0,0 +1,98 @@ +From e2ab9eab324cdf240de89741e4a1aa79919f0196 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:02 +0100 +Subject: x86/boot/compressed: Move 32-bit entrypoint code into .text section + +From: Ard Biesheuvel + +commit e2ab9eab324cdf240de89741e4a1aa79919f0196 upstream. + +Move the code that stores the arguments passed to the EFI entrypoint +into the .text section, so that it can be moved into a separate +compilation unit in a subsequent patch. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-3-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 48 ++++++++++++++++++++++++++----------- + 1 file changed, 34 insertions(+), 14 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -303,24 +303,41 @@ SYM_FUNC_START(efi32_stub_entry) + popl %ecx + popl %edx + popl %esi ++ jmp efi32_entry ++SYM_FUNC_END(efi32_stub_entry) + ++ .text ++/* ++ * This is the common EFI stub entry point for mixed mode. ++ * ++ * Arguments: %ecx image handle ++ * %edx EFI system table pointer ++ * %esi struct bootparams pointer (or NULL when not using ++ * the EFI handover protocol) ++ * ++ * Since this is the point of no return for ordinary execution, no registers ++ * are considered live except for the function parameters. [Note that the EFI ++ * stub may still exit and return to the firmware using the Exit() EFI boot ++ * service.] ++ */ ++SYM_FUNC_START_LOCAL(efi32_entry) + call 1f +-1: pop %ebp +- subl $ rva(1b), %ebp +- +- movl %esi, rva(efi32_boot_args+8)(%ebp) +-SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL) +- movl %ecx, rva(efi32_boot_args)(%ebp) +- movl %edx, rva(efi32_boot_args+4)(%ebp) +- movb $0, rva(efi_is64)(%ebp) ++1: pop %ebx + + /* Save firmware GDTR and code/data selectors */ +- sgdtl rva(efi32_boot_gdt)(%ebp) +- movw %cs, rva(efi32_boot_cs)(%ebp) +- movw %ds, rva(efi32_boot_ds)(%ebp) ++ sgdtl (efi32_boot_gdt - 1b)(%ebx) ++ movw %cs, (efi32_boot_cs - 1b)(%ebx) ++ movw %ds, (efi32_boot_ds - 1b)(%ebx) + + /* Store firmware IDT descriptor */ +- sidtl rva(efi32_boot_idt)(%ebp) ++ sidtl (efi32_boot_idt - 1b)(%ebx) ++ ++ /* Store boot arguments */ ++ leal (efi32_boot_args - 1b)(%ebx), %ebx ++ movl %ecx, 0(%ebx) ++ movl %edx, 4(%ebx) ++ movl %esi, 8(%ebx) ++ movb $0x0, 12(%ebx) // efi_is64 + + /* Disable paging */ + movl %cr0, %eax +@@ -328,7 +345,8 @@ SYM_INNER_LABEL(efi32_pe_stub_entry, SYM + movl %eax, %cr0 + + jmp startup_32 +-SYM_FUNC_END(efi32_stub_entry) ++SYM_FUNC_END(efi32_entry) ++ __HEAD + #endif + + .code64 +@@ -847,7 +865,9 @@ SYM_FUNC_START(efi32_pe_entry) + */ + subl %esi, %ebx + movl %ebx, rva(image_offset)(%ebp) // save image_offset +- jmp efi32_pe_stub_entry ++ xorl %esi, %esi ++ jmp efi32_entry // pass %ecx, %edx, %esi ++ // no other registers remain live + + 2: popl %edi // restore callee-save registers + popl %ebx diff --git a/queue-6.1/x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch b/queue-6.1/x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch new file mode 100644 index 00000000000..13c9792ef24 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch @@ -0,0 +1,115 @@ +From 5c3a85f35b583259cf5ca0344cd79c8899ba1bb7 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:03 +0100 +Subject: x86/boot/compressed: Move bootargs parsing out of 32-bit startup code + +From: Ard Biesheuvel + +commit 5c3a85f35b583259cf5ca0344cd79c8899ba1bb7 upstream. + +Move the logic that chooses between the different EFI entrypoints out of +the 32-bit boot path, and into a 64-bit helper that can perform the same +task much more cleanly. While at it, document the mixed mode boot flow +in a code comment. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-4-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/efi_mixed.S | 43 +++++++++++++++++++++++++++++++++++ + arch/x86/boot/compressed/head_64.S | 24 +++---------------- + 2 files changed, 47 insertions(+), 20 deletions(-) + +--- a/arch/x86/boot/compressed/efi_mixed.S ++++ b/arch/x86/boot/compressed/efi_mixed.S +@@ -22,6 +22,49 @@ + + .code64 + .text ++/* ++ * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode() ++ * is the first thing that runs after switching to long mode. Depending on ++ * whether the EFI handover protocol or the compat entry point was used to ++ * enter the kernel, it will either branch to the 64-bit EFI handover ++ * entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF ++ * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a ++ * struct bootparams pointer as the third argument, so the presence of such a ++ * pointer is used to disambiguate. ++ * ++ * +--------------+ ++ * +------------------+ +------------+ +------>| efi_pe_entry | ++ * | efi32_pe_entry |---->| | | +-----------+--+ ++ * +------------------+ | | +------+----------------+ | ++ * | startup_32 |---->| startup_64_mixed_mode | | ++ * +------------------+ | | +------+----------------+ V ++ * | efi32_stub_entry |---->| | | +------------------+ ++ * +------------------+ +------------+ +---->| efi64_stub_entry | ++ * +-------------+----+ ++ * +------------+ +----------+ | ++ * | startup_64 |<----| efi_main |<--------------+ ++ * +------------+ +----------+ ++ */ ++SYM_FUNC_START(startup_64_mixed_mode) ++ lea efi32_boot_args(%rip), %rdx ++ mov 0(%rdx), %edi ++ mov 4(%rdx), %esi ++ mov 8(%rdx), %edx // saved bootparams pointer ++ test %edx, %edx ++ jnz efi64_stub_entry ++ /* ++ * efi_pe_entry uses MS calling convention, which requires 32 bytes of ++ * shadow space on the stack even if all arguments are passed in ++ * registers. We also need an additional 8 bytes for the space that ++ * would be occupied by the return address, and this also results in ++ * the correct stack alignment for entry. ++ */ ++ sub $40, %rsp ++ mov %rdi, %rcx // MS calling convention ++ mov %rsi, %rdx ++ jmp efi_pe_entry ++SYM_FUNC_END(startup_64_mixed_mode) ++ + SYM_FUNC_START(__efi64_thunk) + push %rbp + push %rbx +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -261,25 +261,9 @@ SYM_FUNC_START(startup_32) + */ + leal rva(startup_64)(%ebp), %eax + #ifdef CONFIG_EFI_MIXED +- movl rva(efi32_boot_args)(%ebp), %edi +- testl %edi, %edi +- jz 1f +- leal rva(efi64_stub_entry)(%ebp), %eax +- movl rva(efi32_boot_args+4)(%ebp), %esi +- movl rva(efi32_boot_args+8)(%ebp), %edx // saved bootparams pointer +- testl %edx, %edx +- jnz 1f +- /* +- * efi_pe_entry uses MS calling convention, which requires 32 bytes of +- * shadow space on the stack even if all arguments are passed in +- * registers. We also need an additional 8 bytes for the space that +- * would be occupied by the return address, and this also results in +- * the correct stack alignment for entry. +- */ +- subl $40, %esp +- leal rva(efi_pe_entry)(%ebp), %eax +- movl %edi, %ecx // MS calling convention +- movl %esi, %edx ++ cmpb $1, rva(efi_is64)(%ebp) ++ je 1f ++ leal rva(startup_64_mixed_mode)(%ebp), %eax + 1: + #endif + /* Check if the C-bit position is correct when SEV is active */ +@@ -795,7 +779,7 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLO + SYM_DATA(image_offset, .long 0) + #endif + #ifdef CONFIG_EFI_MIXED +-SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0) ++SYM_DATA(efi32_boot_args, .long 0, 0, 0) + SYM_DATA(efi_is64, .byte 1) + + #define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) diff --git a/queue-6.1/x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch b/queue-6.1/x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch new file mode 100644 index 00000000000..cfc1832a9cc --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch @@ -0,0 +1,163 @@ +From 73a6dec80e2acedaef3ca603d4b5799049f6e9f8 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:05 +0100 +Subject: x86/boot/compressed: Move efi32_entry out of head_64.S + +From: Ard Biesheuvel + +commit 73a6dec80e2acedaef3ca603d4b5799049f6e9f8 upstream. + +Move the efi32_entry() routine out of head_64.S and into efi-mixed.S, +which reduces clutter in the complicated startup routines. It also +permits linkage of some symbols used by code to be made local. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-6-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/efi_mixed.S | 57 ++++++++++++++++++++++++++++------- + arch/x86/boot/compressed/head_64.S | 45 --------------------------- + 2 files changed, 47 insertions(+), 55 deletions(-) + +--- a/arch/x86/boot/compressed/efi_mixed.S ++++ b/arch/x86/boot/compressed/efi_mixed.S +@@ -105,7 +105,7 @@ SYM_FUNC_START(__efi64_thunk) + /* + * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT + * and IDT that was installed when the kernel started executing. The +- * pointers were saved at the EFI stub entry point in head_64.S. ++ * pointers were saved by the efi32_entry() routine below. + * + * Pass the saved DS selector to the 32-bit code, and use far return to + * restore the saved CS selector. +@@ -217,22 +217,59 @@ SYM_FUNC_START_LOCAL(efi_enter32) + lret + SYM_FUNC_END(efi_enter32) + ++/* ++ * This is the common EFI stub entry point for mixed mode. ++ * ++ * Arguments: %ecx image handle ++ * %edx EFI system table pointer ++ * %esi struct bootparams pointer (or NULL when not using ++ * the EFI handover protocol) ++ * ++ * Since this is the point of no return for ordinary execution, no registers ++ * are considered live except for the function parameters. [Note that the EFI ++ * stub may still exit and return to the firmware using the Exit() EFI boot ++ * service.] ++ */ ++SYM_FUNC_START(efi32_entry) ++ call 1f ++1: pop %ebx ++ ++ /* Save firmware GDTR and code/data selectors */ ++ sgdtl (efi32_boot_gdt - 1b)(%ebx) ++ movw %cs, (efi32_boot_cs - 1b)(%ebx) ++ movw %ds, (efi32_boot_ds - 1b)(%ebx) ++ ++ /* Store firmware IDT descriptor */ ++ sidtl (efi32_boot_idt - 1b)(%ebx) ++ ++ /* Store boot arguments */ ++ leal (efi32_boot_args - 1b)(%ebx), %ebx ++ movl %ecx, 0(%ebx) ++ movl %edx, 4(%ebx) ++ movl %esi, 8(%ebx) ++ movb $0x0, 12(%ebx) // efi_is64 ++ ++ /* Disable paging */ ++ movl %cr0, %eax ++ btrl $X86_CR0_PG_BIT, %eax ++ movl %eax, %cr0 ++ ++ jmp startup_32 ++SYM_FUNC_END(efi32_entry) ++ + .data + .balign 8 +-SYM_DATA_START(efi32_boot_gdt) ++SYM_DATA_START_LOCAL(efi32_boot_gdt) + .word 0 + .quad 0 + SYM_DATA_END(efi32_boot_gdt) + +-SYM_DATA_START(efi32_boot_idt) ++SYM_DATA_START_LOCAL(efi32_boot_idt) + .word 0 + .quad 0 + SYM_DATA_END(efi32_boot_idt) + +-SYM_DATA_START(efi32_boot_cs) +- .word 0 +-SYM_DATA_END(efi32_boot_cs) +- +-SYM_DATA_START(efi32_boot_ds) +- .word 0 +-SYM_DATA_END(efi32_boot_ds) ++SYM_DATA_LOCAL(efi32_boot_cs, .word 0) ++SYM_DATA_LOCAL(efi32_boot_ds, .word 0) ++SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0) ++SYM_DATA(efi_is64, .byte 1) +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -289,48 +289,6 @@ SYM_FUNC_START(efi32_stub_entry) + popl %esi + jmp efi32_entry + SYM_FUNC_END(efi32_stub_entry) +- +- .text +-/* +- * This is the common EFI stub entry point for mixed mode. +- * +- * Arguments: %ecx image handle +- * %edx EFI system table pointer +- * %esi struct bootparams pointer (or NULL when not using +- * the EFI handover protocol) +- * +- * Since this is the point of no return for ordinary execution, no registers +- * are considered live except for the function parameters. [Note that the EFI +- * stub may still exit and return to the firmware using the Exit() EFI boot +- * service.] +- */ +-SYM_FUNC_START_LOCAL(efi32_entry) +- call 1f +-1: pop %ebx +- +- /* Save firmware GDTR and code/data selectors */ +- sgdtl (efi32_boot_gdt - 1b)(%ebx) +- movw %cs, (efi32_boot_cs - 1b)(%ebx) +- movw %ds, (efi32_boot_ds - 1b)(%ebx) +- +- /* Store firmware IDT descriptor */ +- sidtl (efi32_boot_idt - 1b)(%ebx) +- +- /* Store boot arguments */ +- leal (efi32_boot_args - 1b)(%ebx), %ebx +- movl %ecx, 0(%ebx) +- movl %edx, 4(%ebx) +- movl %esi, 8(%ebx) +- movb $0x0, 12(%ebx) // efi_is64 +- +- /* Disable paging */ +- movl %cr0, %eax +- btrl $X86_CR0_PG_BIT, %eax +- movl %eax, %cr0 +- +- jmp startup_32 +-SYM_FUNC_END(efi32_entry) +- __HEAD + #endif + + .code64 +@@ -779,9 +737,6 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLO + SYM_DATA(image_offset, .long 0) + #endif + #ifdef CONFIG_EFI_MIXED +-SYM_DATA(efi32_boot_args, .long 0, 0, 0) +-SYM_DATA(efi_is64, .byte 1) +- + #define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) + #define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) + #define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) diff --git a/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch b/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch new file mode 100644 index 00000000000..7e64316fce2 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch @@ -0,0 +1,63 @@ +From 91592b5c0c2f076ff9d8cc0c14aa563448ac9fc4 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:04 +0100 +Subject: x86/boot/compressed: Move efi32_pe_entry into .text section + +From: Ard Biesheuvel + +commit 91592b5c0c2f076ff9d8cc0c14aa563448ac9fc4 upstream. + +Move efi32_pe_entry() into the .text section, so that it can be moved +out of head_64.S and into a separate compilation unit in a subsequent +patch. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-5-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -786,7 +786,7 @@ SYM_DATA(efi_is64, .byte 1) + #define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) + #define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) + +- __HEAD ++ .text + .code32 + SYM_FUNC_START(efi32_pe_entry) + /* +@@ -808,12 +808,11 @@ SYM_FUNC_START(efi32_pe_entry) + + call 1f + 1: pop %ebx +- subl $ rva(1b), %ebx + + /* Get the loaded image protocol pointer from the image handle */ + leal -4(%ebp), %eax + pushl %eax // &loaded_image +- leal rva(loaded_image_proto)(%ebx), %eax ++ leal (loaded_image_proto - 1b)(%ebx), %eax + pushl %eax // pass the GUID address + pushl 8(%ebp) // pass the image handle + +@@ -842,13 +841,13 @@ SYM_FUNC_START(efi32_pe_entry) + movl 12(%ebp), %edx // sys_table + movl -4(%ebp), %esi // loaded_image + movl LI32_image_base(%esi), %esi // loaded_image->image_base +- movl %ebx, %ebp // startup_32 for efi32_pe_stub_entry ++ leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32 + /* + * We need to set the image_offset variable here since startup_32() will + * use it before we get to the 64-bit efi_pe_entry() in C code. + */ +- subl %esi, %ebx +- movl %ebx, rva(image_offset)(%ebp) // save image_offset ++ subl %esi, %ebp // calculate image_offset ++ movl %ebp, (image_offset - 1b)(%ebx) // save image_offset + xorl %esi, %esi + jmp efi32_entry // pass %ecx, %edx, %esi + // no other registers remain live diff --git a/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch b/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch new file mode 100644 index 00000000000..8a9c191b26b --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch @@ -0,0 +1,216 @@ +From 7f22ca396778fea9332d83ec2359dbe8396e9a06 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:06 +0100 +Subject: x86/boot/compressed: Move efi32_pe_entry() out of head_64.S + +From: Ard Biesheuvel + +commit 7f22ca396778fea9332d83ec2359dbe8396e9a06 upstream. + +Move the implementation of efi32_pe_entry() into efi-mixed.S, which is a +more suitable location that only gets built if EFI mixed mode is +actually enabled. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-7-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/efi_mixed.S | 82 ++++++++++++++++++++++++++++++++ + arch/x86/boot/compressed/head_64.S | 87 ----------------------------------- + 2 files changed, 83 insertions(+), 86 deletions(-) + +--- a/arch/x86/boot/compressed/efi_mixed.S ++++ b/arch/x86/boot/compressed/efi_mixed.S +@@ -257,6 +257,88 @@ SYM_FUNC_START(efi32_entry) + jmp startup_32 + SYM_FUNC_END(efi32_entry) + ++#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) ++#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) ++#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) ++ ++/* ++ * efi_status_t efi32_pe_entry(efi_handle_t image_handle, ++ * efi_system_table_32_t *sys_table) ++ */ ++SYM_FUNC_START(efi32_pe_entry) ++ pushl %ebp ++ movl %esp, %ebp ++ pushl %eax // dummy push to allocate loaded_image ++ ++ pushl %ebx // save callee-save registers ++ pushl %edi ++ ++ call verify_cpu // check for long mode support ++ testl %eax, %eax ++ movl $0x80000003, %eax // EFI_UNSUPPORTED ++ jnz 2f ++ ++ call 1f ++1: pop %ebx ++ ++ /* Get the loaded image protocol pointer from the image handle */ ++ leal -4(%ebp), %eax ++ pushl %eax // &loaded_image ++ leal (loaded_image_proto - 1b)(%ebx), %eax ++ pushl %eax // pass the GUID address ++ pushl 8(%ebp) // pass the image handle ++ ++ /* ++ * Note the alignment of the stack frame. ++ * sys_table ++ * handle <-- 16-byte aligned on entry by ABI ++ * return address ++ * frame pointer ++ * loaded_image <-- local variable ++ * saved %ebx <-- 16-byte aligned here ++ * saved %edi ++ * &loaded_image ++ * &loaded_image_proto ++ * handle <-- 16-byte aligned for call to handle_protocol ++ */ ++ ++ movl 12(%ebp), %eax // sys_table ++ movl ST32_boottime(%eax), %eax // sys_table->boottime ++ call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol ++ addl $12, %esp // restore argument space ++ testl %eax, %eax ++ jnz 2f ++ ++ movl 8(%ebp), %ecx // image_handle ++ movl 12(%ebp), %edx // sys_table ++ movl -4(%ebp), %esi // loaded_image ++ movl LI32_image_base(%esi), %esi // loaded_image->image_base ++ leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32 ++ /* ++ * We need to set the image_offset variable here since startup_32() will ++ * use it before we get to the 64-bit efi_pe_entry() in C code. ++ */ ++ subl %esi, %ebp // calculate image_offset ++ movl %ebp, (image_offset - 1b)(%ebx) // save image_offset ++ xorl %esi, %esi ++ jmp efi32_entry // pass %ecx, %edx, %esi ++ // no other registers remain live ++ ++2: popl %edi // restore callee-save registers ++ popl %ebx ++ leave ++ RET ++SYM_FUNC_END(efi32_pe_entry) ++ ++ .section ".rodata" ++ /* EFI loaded image protocol GUID */ ++ .balign 4 ++SYM_DATA_START_LOCAL(loaded_image_proto) ++ .long 0x5b1b31a1 ++ .word 0x9562, 0x11d2 ++ .byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ++SYM_DATA_END(loaded_image_proto) ++ + .data + .balign 8 + SYM_DATA_START_LOCAL(efi32_boot_gdt) +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -689,6 +689,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmo + jmp 1b + SYM_FUNC_END(.Lno_longmode) + ++ .globl verify_cpu + #include "../../kernel/verify_cpu.S" + + .data +@@ -736,92 +737,6 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLO + #ifdef CONFIG_EFI_STUB + SYM_DATA(image_offset, .long 0) + #endif +-#ifdef CONFIG_EFI_MIXED +-#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) +-#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) +-#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) +- +- .text +- .code32 +-SYM_FUNC_START(efi32_pe_entry) +-/* +- * efi_status_t efi32_pe_entry(efi_handle_t image_handle, +- * efi_system_table_32_t *sys_table) +- */ +- +- pushl %ebp +- movl %esp, %ebp +- pushl %eax // dummy push to allocate loaded_image +- +- pushl %ebx // save callee-save registers +- pushl %edi +- +- call verify_cpu // check for long mode support +- testl %eax, %eax +- movl $0x80000003, %eax // EFI_UNSUPPORTED +- jnz 2f +- +- call 1f +-1: pop %ebx +- +- /* Get the loaded image protocol pointer from the image handle */ +- leal -4(%ebp), %eax +- pushl %eax // &loaded_image +- leal (loaded_image_proto - 1b)(%ebx), %eax +- pushl %eax // pass the GUID address +- pushl 8(%ebp) // pass the image handle +- +- /* +- * Note the alignment of the stack frame. +- * sys_table +- * handle <-- 16-byte aligned on entry by ABI +- * return address +- * frame pointer +- * loaded_image <-- local variable +- * saved %ebx <-- 16-byte aligned here +- * saved %edi +- * &loaded_image +- * &loaded_image_proto +- * handle <-- 16-byte aligned for call to handle_protocol +- */ +- +- movl 12(%ebp), %eax // sys_table +- movl ST32_boottime(%eax), %eax // sys_table->boottime +- call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol +- addl $12, %esp // restore argument space +- testl %eax, %eax +- jnz 2f +- +- movl 8(%ebp), %ecx // image_handle +- movl 12(%ebp), %edx // sys_table +- movl -4(%ebp), %esi // loaded_image +- movl LI32_image_base(%esi), %esi // loaded_image->image_base +- leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32 +- /* +- * We need to set the image_offset variable here since startup_32() will +- * use it before we get to the 64-bit efi_pe_entry() in C code. +- */ +- subl %esi, %ebp // calculate image_offset +- movl %ebp, (image_offset - 1b)(%ebx) // save image_offset +- xorl %esi, %esi +- jmp efi32_entry // pass %ecx, %edx, %esi +- // no other registers remain live +- +-2: popl %edi // restore callee-save registers +- popl %ebx +- leave +- RET +-SYM_FUNC_END(efi32_pe_entry) +- +- .section ".rodata" +- /* EFI loaded image protocol GUID */ +- .balign 4 +-SYM_DATA_START_LOCAL(loaded_image_proto) +- .long 0x5b1b31a1 +- .word 0x9562, 0x11d2 +- .byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b +-SYM_DATA_END(loaded_image_proto) +-#endif + + #ifdef CONFIG_AMD_MEM_ENCRYPT + __HEAD diff --git a/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch b/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch new file mode 100644 index 00000000000..9725d6ca401 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch @@ -0,0 +1,113 @@ +From b5d854cd4b6a314edd6c15dabc4233b84a0f8e5e Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:13 +0100 +Subject: x86/boot/compressed: Move startup32_check_sev_cbit() into .text + +From: Ard Biesheuvel + +commit b5d854cd4b6a314edd6c15dabc4233b84a0f8e5e upstream. + +Move startup32_check_sev_cbit() into the .text section and turn it into +an ordinary function using the ordinary 32-bit calling convention, +instead of saving/restoring the registers that are known to be live at +the only call site. This improves maintainability, and makes it possible +to move this function out of head_64.S and into a separate compilation +unit that is specific to memory encryption. + +Note that this requires the call site to be moved before the mixed mode +check, as %eax will be live otherwise. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-14-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 35 +++++++++++++++++++---------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -251,6 +251,11 @@ SYM_FUNC_START(startup_32) + movl $__BOOT_TSS, %eax + ltr %ax + ++#ifdef CONFIG_AMD_MEM_ENCRYPT ++ /* Check if the C-bit position is correct when SEV is active */ ++ call startup32_check_sev_cbit ++#endif ++ + /* + * Setup for the jump to 64bit mode + * +@@ -268,8 +273,6 @@ SYM_FUNC_START(startup_32) + leal rva(startup_64_mixed_mode)(%ebp), %eax + 1: + #endif +- /* Check if the C-bit position is correct when SEV is active */ +- call startup32_check_sev_cbit + + pushl $__KERNEL_CS + pushl %eax +@@ -740,16 +743,17 @@ SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBA + * succeed. An incorrect C-bit position will map all memory unencrypted, so that + * the compare will use the encrypted random data and fail. + */ +- __HEAD +-SYM_FUNC_START(startup32_check_sev_cbit) + #ifdef CONFIG_AMD_MEM_ENCRYPT +- pushl %eax ++ .text ++SYM_FUNC_START(startup32_check_sev_cbit) + pushl %ebx +- pushl %ecx +- pushl %edx ++ pushl %ebp ++ ++ call 0f ++0: popl %ebp + + /* Check for non-zero sev_status */ +- movl rva(sev_status)(%ebp), %eax ++ movl (sev_status - 0b)(%ebp), %eax + testl %eax, %eax + jz 4f + +@@ -764,17 +768,18 @@ SYM_FUNC_START(startup32_check_sev_cbit) + jnc 2b + + /* Store to memory and keep it in the registers */ +- movl %eax, rva(sev_check_data)(%ebp) +- movl %ebx, rva(sev_check_data+4)(%ebp) ++ leal (sev_check_data - 0b)(%ebp), %ebp ++ movl %eax, 0(%ebp) ++ movl %ebx, 4(%ebp) + + /* Enable paging to see if encryption is active */ + movl %cr0, %edx /* Backup %cr0 in %edx */ + movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */ + movl %ecx, %cr0 + +- cmpl %eax, rva(sev_check_data)(%ebp) ++ cmpl %eax, 0(%ebp) + jne 3f +- cmpl %ebx, rva(sev_check_data+4)(%ebp) ++ cmpl %ebx, 4(%ebp) + jne 3f + + movl %edx, %cr0 /* Restore previous %cr0 */ +@@ -786,13 +791,11 @@ SYM_FUNC_START(startup32_check_sev_cbit) + jmp 3b + + 4: +- popl %edx +- popl %ecx ++ popl %ebp + popl %ebx +- popl %eax +-#endif + RET + SYM_FUNC_END(startup32_check_sev_cbit) ++#endif + + /* + * Stack and heap for uncompression diff --git a/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch b/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch new file mode 100644 index 00000000000..d2092d812c3 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch @@ -0,0 +1,179 @@ +From 9d7eaae6a071ff1f718e0aa5e610bb712f8cc632 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:14 +0100 +Subject: x86/boot/compressed: Move startup32_check_sev_cbit() out of head_64.S + +From: Ard Biesheuvel + +commit 9d7eaae6a071ff1f718e0aa5e610bb712f8cc632 upstream. + +Now that the startup32_check_sev_cbit() routine can execute from +anywhere and behaves like an ordinary function, it can be moved where it +belongs. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-15-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 71 --------------------------------- + arch/x86/boot/compressed/mem_encrypt.S | 68 +++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 71 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -727,77 +727,6 @@ SYM_DATA_START(boot_idt) + SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBAL, boot_idt_end) + + /* +- * Check for the correct C-bit position when the startup_32 boot-path is used. +- * +- * The check makes use of the fact that all memory is encrypted when paging is +- * disabled. The function creates 64 bits of random data using the RDRAND +- * instruction. RDRAND is mandatory for SEV guests, so always available. If the +- * hypervisor violates that the kernel will crash right here. +- * +- * The 64 bits of random data are stored to a memory location and at the same +- * time kept in the %eax and %ebx registers. Since encryption is always active +- * when paging is off the random data will be stored encrypted in main memory. +- * +- * Then paging is enabled. When the C-bit position is correct all memory is +- * still mapped encrypted and comparing the register values with memory will +- * succeed. An incorrect C-bit position will map all memory unencrypted, so that +- * the compare will use the encrypted random data and fail. +- */ +-#ifdef CONFIG_AMD_MEM_ENCRYPT +- .text +-SYM_FUNC_START(startup32_check_sev_cbit) +- pushl %ebx +- pushl %ebp +- +- call 0f +-0: popl %ebp +- +- /* Check for non-zero sev_status */ +- movl (sev_status - 0b)(%ebp), %eax +- testl %eax, %eax +- jz 4f +- +- /* +- * Get two 32-bit random values - Don't bail out if RDRAND fails +- * because it is better to prevent forward progress if no random value +- * can be gathered. +- */ +-1: rdrand %eax +- jnc 1b +-2: rdrand %ebx +- jnc 2b +- +- /* Store to memory and keep it in the registers */ +- leal (sev_check_data - 0b)(%ebp), %ebp +- movl %eax, 0(%ebp) +- movl %ebx, 4(%ebp) +- +- /* Enable paging to see if encryption is active */ +- movl %cr0, %edx /* Backup %cr0 in %edx */ +- movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */ +- movl %ecx, %cr0 +- +- cmpl %eax, 0(%ebp) +- jne 3f +- cmpl %ebx, 4(%ebp) +- jne 3f +- +- movl %edx, %cr0 /* Restore previous %cr0 */ +- +- jmp 4f +- +-3: /* Check failed - hlt the machine */ +- hlt +- jmp 3b +- +-4: +- popl %ebp +- popl %ebx +- RET +-SYM_FUNC_END(startup32_check_sev_cbit) +-#endif +- +-/* + * Stack and heap for uncompression + */ + .bss +--- a/arch/x86/boot/compressed/mem_encrypt.S ++++ b/arch/x86/boot/compressed/mem_encrypt.S +@@ -243,6 +243,74 @@ SYM_FUNC_START(startup32_load_idt) + RET + SYM_FUNC_END(startup32_load_idt) + ++/* ++ * Check for the correct C-bit position when the startup_32 boot-path is used. ++ * ++ * The check makes use of the fact that all memory is encrypted when paging is ++ * disabled. The function creates 64 bits of random data using the RDRAND ++ * instruction. RDRAND is mandatory for SEV guests, so always available. If the ++ * hypervisor violates that the kernel will crash right here. ++ * ++ * The 64 bits of random data are stored to a memory location and at the same ++ * time kept in the %eax and %ebx registers. Since encryption is always active ++ * when paging is off the random data will be stored encrypted in main memory. ++ * ++ * Then paging is enabled. When the C-bit position is correct all memory is ++ * still mapped encrypted and comparing the register values with memory will ++ * succeed. An incorrect C-bit position will map all memory unencrypted, so that ++ * the compare will use the encrypted random data and fail. ++ */ ++SYM_FUNC_START(startup32_check_sev_cbit) ++ pushl %ebx ++ pushl %ebp ++ ++ call 0f ++0: popl %ebp ++ ++ /* Check for non-zero sev_status */ ++ movl (sev_status - 0b)(%ebp), %eax ++ testl %eax, %eax ++ jz 4f ++ ++ /* ++ * Get two 32-bit random values - Don't bail out if RDRAND fails ++ * because it is better to prevent forward progress if no random value ++ * can be gathered. ++ */ ++1: rdrand %eax ++ jnc 1b ++2: rdrand %ebx ++ jnc 2b ++ ++ /* Store to memory and keep it in the registers */ ++ leal (sev_check_data - 0b)(%ebp), %ebp ++ movl %eax, 0(%ebp) ++ movl %ebx, 4(%ebp) ++ ++ /* Enable paging to see if encryption is active */ ++ movl %cr0, %edx /* Backup %cr0 in %edx */ ++ movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */ ++ movl %ecx, %cr0 ++ ++ cmpl %eax, 0(%ebp) ++ jne 3f ++ cmpl %ebx, 4(%ebp) ++ jne 3f ++ ++ movl %edx, %cr0 /* Restore previous %cr0 */ ++ ++ jmp 4f ++ ++3: /* Check failed - hlt the machine */ ++ hlt ++ jmp 3b ++ ++4: ++ popl %ebp ++ popl %ebx ++ RET ++SYM_FUNC_END(startup32_check_sev_cbit) ++ + .code64 + + #include "../../kernel/sev_verify_cbit.S" diff --git a/queue-6.1/x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch b/queue-6.1/x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch new file mode 100644 index 00000000000..7ddd08db5a4 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch @@ -0,0 +1,99 @@ +From c6355995ba471d7ad574174e593192ce805c7e1a Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:11 +0100 +Subject: x86/boot/compressed: Move startup32_load_idt() into .text section + +From: Ard Biesheuvel + +commit c6355995ba471d7ad574174e593192ce805c7e1a upstream. + +Convert startup32_load_idt() into an ordinary function and move it into +the .text section. This involves turning the rva() immediates into ones +derived from a local label, and preserving/restoring the %ebp and %ebx +as per the calling convention. + +Also move the #ifdef to the only existing call site. This makes it clear +that the function call does nothing if support for memory encryption is +not compiled in. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-12-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -118,7 +118,9 @@ SYM_FUNC_START(startup_32) + 1: + + /* Setup Exception handling for SEV-ES */ ++#ifdef CONFIG_AMD_MEM_ENCRYPT + call startup32_load_idt ++#endif + + /* Make sure cpu supports long mode. */ + call verify_cpu +@@ -732,10 +734,8 @@ SYM_DATA_START(boot32_idt) + .quad 0 + .endr + SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLOBAL, boot32_idt_end) +-#endif + +-#ifdef CONFIG_AMD_MEM_ENCRYPT +- __HEAD ++ .text + .code32 + /* + * Write an IDT entry into boot32_idt +@@ -768,24 +768,32 @@ SYM_FUNC_START_LOCAL(startup32_set_idt_e + + RET + SYM_FUNC_END(startup32_set_idt_entry) +-#endif + + SYM_FUNC_START(startup32_load_idt) +-#ifdef CONFIG_AMD_MEM_ENCRYPT +- leal rva(boot32_idt)(%ebp), %ecx ++ push %ebp ++ push %ebx ++ ++ call 1f ++1: pop %ebp ++ ++ leal (boot32_idt - 1b)(%ebp), %ebx + + /* #VC handler */ +- leal rva(startup32_vc_handler)(%ebp), %eax ++ leal (startup32_vc_handler - 1b)(%ebp), %eax + movl $X86_TRAP_VC, %edx ++ movl %ebx, %ecx + call startup32_set_idt_entry + + /* Load IDT */ +- leal rva(boot32_idt)(%ebp), %eax +- movl %eax, rva(boot32_idt_desc+2)(%ebp) +- lidt rva(boot32_idt_desc)(%ebp) +-#endif ++ leal (boot32_idt_desc - 1b)(%ebp), %ecx ++ movl %ebx, 2(%ecx) ++ lidt (%ecx) ++ ++ pop %ebx ++ pop %ebp + RET + SYM_FUNC_END(startup32_load_idt) ++#endif + + /* + * Check for the correct C-bit position when the startup_32 boot-path is used. +@@ -804,6 +812,7 @@ SYM_FUNC_END(startup32_load_idt) + * succeed. An incorrect C-bit position will map all memory unencrypted, so that + * the compare will use the encrypted random data and fail. + */ ++ __HEAD + SYM_FUNC_START(startup32_check_sev_cbit) + #ifdef CONFIG_AMD_MEM_ENCRYPT + pushl %eax diff --git a/queue-6.1/x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch b/queue-6.1/x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch new file mode 100644 index 00000000000..3adffbbb86f --- /dev/null +++ b/queue-6.1/x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch @@ -0,0 +1,202 @@ +From 9ea813be3d345dfb8ac5bf6fbb29e6a63647a39d Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:12 +0100 +Subject: x86/boot/compressed: Move startup32_load_idt() out of head_64.S + +From: Ard Biesheuvel + +commit 9ea813be3d345dfb8ac5bf6fbb29e6a63647a39d upstream. + +Now that startup32_load_idt() has been refactored into an ordinary +callable function, move it into mem-encrypt.S where it belongs. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-13-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 72 --------------------------------- + arch/x86/boot/compressed/mem_encrypt.S | 72 ++++++++++++++++++++++++++++++++- + 2 files changed, 71 insertions(+), 73 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -723,78 +723,6 @@ SYM_DATA_START(boot_idt) + .endr + SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBAL, boot_idt_end) + +-#ifdef CONFIG_AMD_MEM_ENCRYPT +-SYM_DATA_START(boot32_idt_desc) +- .word boot32_idt_end - boot32_idt - 1 +- .long 0 +-SYM_DATA_END(boot32_idt_desc) +- .balign 8 +-SYM_DATA_START(boot32_idt) +- .rept 32 +- .quad 0 +- .endr +-SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLOBAL, boot32_idt_end) +- +- .text +- .code32 +-/* +- * Write an IDT entry into boot32_idt +- * +- * Parameters: +- * +- * %eax: Handler address +- * %edx: Vector number +- * %ecx: IDT address +- */ +-SYM_FUNC_START_LOCAL(startup32_set_idt_entry) +- /* IDT entry address to %ecx */ +- leal (%ecx, %edx, 8), %ecx +- +- /* Build IDT entry, lower 4 bytes */ +- movl %eax, %edx +- andl $0x0000ffff, %edx # Target code segment offset [15:0] +- orl $(__KERNEL32_CS << 16), %edx # Target code segment selector +- +- /* Store lower 4 bytes to IDT */ +- movl %edx, (%ecx) +- +- /* Build IDT entry, upper 4 bytes */ +- movl %eax, %edx +- andl $0xffff0000, %edx # Target code segment offset [31:16] +- orl $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate +- +- /* Store upper 4 bytes to IDT */ +- movl %edx, 4(%ecx) +- +- RET +-SYM_FUNC_END(startup32_set_idt_entry) +- +-SYM_FUNC_START(startup32_load_idt) +- push %ebp +- push %ebx +- +- call 1f +-1: pop %ebp +- +- leal (boot32_idt - 1b)(%ebp), %ebx +- +- /* #VC handler */ +- leal (startup32_vc_handler - 1b)(%ebp), %eax +- movl $X86_TRAP_VC, %edx +- movl %ebx, %ecx +- call startup32_set_idt_entry +- +- /* Load IDT */ +- leal (boot32_idt_desc - 1b)(%ebp), %ecx +- movl %ebx, 2(%ecx) +- lidt (%ecx) +- +- pop %ebx +- pop %ebp +- RET +-SYM_FUNC_END(startup32_load_idt) +-#endif +- + /* + * Check for the correct C-bit position when the startup_32 boot-path is used. + * +--- a/arch/x86/boot/compressed/mem_encrypt.S ++++ b/arch/x86/boot/compressed/mem_encrypt.S +@@ -12,6 +12,8 @@ + #include + #include + #include ++#include ++#include + + .text + .code32 +@@ -98,7 +100,7 @@ SYM_CODE_START_LOCAL(sev_es_req_cpuid) + jmp 1b + SYM_CODE_END(sev_es_req_cpuid) + +-SYM_CODE_START(startup32_vc_handler) ++SYM_CODE_START_LOCAL(startup32_vc_handler) + pushl %eax + pushl %ebx + pushl %ecx +@@ -184,6 +186,63 @@ SYM_CODE_START(startup32_vc_handler) + jmp .Lfail + SYM_CODE_END(startup32_vc_handler) + ++/* ++ * Write an IDT entry into boot32_idt ++ * ++ * Parameters: ++ * ++ * %eax: Handler address ++ * %edx: Vector number ++ * %ecx: IDT address ++ */ ++SYM_FUNC_START_LOCAL(startup32_set_idt_entry) ++ /* IDT entry address to %ecx */ ++ leal (%ecx, %edx, 8), %ecx ++ ++ /* Build IDT entry, lower 4 bytes */ ++ movl %eax, %edx ++ andl $0x0000ffff, %edx # Target code segment offset [15:0] ++ orl $(__KERNEL32_CS << 16), %edx # Target code segment selector ++ ++ /* Store lower 4 bytes to IDT */ ++ movl %edx, (%ecx) ++ ++ /* Build IDT entry, upper 4 bytes */ ++ movl %eax, %edx ++ andl $0xffff0000, %edx # Target code segment offset [31:16] ++ orl $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate ++ ++ /* Store upper 4 bytes to IDT */ ++ movl %edx, 4(%ecx) ++ ++ RET ++SYM_FUNC_END(startup32_set_idt_entry) ++ ++SYM_FUNC_START(startup32_load_idt) ++ push %ebp ++ push %ebx ++ ++ call 1f ++1: pop %ebp ++ ++ leal (boot32_idt - 1b)(%ebp), %ebx ++ ++ /* #VC handler */ ++ leal (startup32_vc_handler - 1b)(%ebp), %eax ++ movl $X86_TRAP_VC, %edx ++ movl %ebx, %ecx ++ call startup32_set_idt_entry ++ ++ /* Load IDT */ ++ leal (boot32_idt_desc - 1b)(%ebp), %ecx ++ movl %ebx, 2(%ecx) ++ lidt (%ecx) ++ ++ pop %ebx ++ pop %ebp ++ RET ++SYM_FUNC_END(startup32_load_idt) ++ + .code64 + + #include "../../kernel/sev_verify_cbit.S" +@@ -195,4 +254,15 @@ SYM_CODE_END(startup32_vc_handler) + SYM_DATA(sme_me_mask, .quad 0) + SYM_DATA(sev_status, .quad 0) + SYM_DATA(sev_check_data, .quad 0) ++ ++SYM_DATA_START_LOCAL(boot32_idt) ++ .rept 32 ++ .quad 0 ++ .endr ++SYM_DATA_END(boot32_idt) ++ ++SYM_DATA_START_LOCAL(boot32_idt_desc) ++ .word . - boot32_idt - 1 ++ .long 0 ++SYM_DATA_END(boot32_idt_desc) + #endif diff --git a/queue-6.1/x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch b/queue-6.1/x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch new file mode 100644 index 00000000000..d10e4c32005 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch @@ -0,0 +1,47 @@ +From 61de13df95901bc58456bc5acdbd3c18c66cf859 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:16 +0100 +Subject: x86/boot/compressed: Only build mem_encrypt.S if AMD_MEM_ENCRYPT=y + +From: Ard Biesheuvel + +commit 61de13df95901bc58456bc5acdbd3c18c66cf859 upstream. + +Avoid building the mem_encrypt.o object if memory encryption support is +not enabled to begin with. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-17-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/Makefile | 2 +- + arch/x86/boot/compressed/mem_encrypt.S | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -100,7 +100,7 @@ vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += + ifdef CONFIG_X86_64 + vmlinux-objs-y += $(obj)/ident_map_64.o + vmlinux-objs-y += $(obj)/idt_64.o $(obj)/idt_handlers_64.o +- vmlinux-objs-y += $(obj)/mem_encrypt.o ++ vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/mem_encrypt.o + vmlinux-objs-y += $(obj)/pgtable_64.o + vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/sev.o + endif +--- a/arch/x86/boot/compressed/mem_encrypt.S ++++ b/arch/x86/boot/compressed/mem_encrypt.S +@@ -307,7 +307,6 @@ SYM_FUNC_END(startup32_check_sev_cbit) + + .data + +-#ifdef CONFIG_AMD_MEM_ENCRYPT + .balign 8 + SYM_DATA(sme_me_mask, .quad 0) + SYM_DATA(sev_status, .quad 0) +@@ -323,4 +322,3 @@ SYM_DATA_START_LOCAL(boot32_idt_desc) + .word . - boot32_idt - 1 + .long 0 + SYM_DATA_END(boot32_idt_desc) +-#endif diff --git a/queue-6.1/x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch b/queue-6.1/x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch new file mode 100644 index 00000000000..7ee5439e722 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch @@ -0,0 +1,77 @@ +From d73a257f7f86871c3aac24dc20538e3983096647 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:10 +0100 +Subject: x86/boot/compressed: Pull global variable reference into startup32_load_idt() + +From: Ard Biesheuvel + +commit d73a257f7f86871c3aac24dc20538e3983096647 upstream. + +In preparation for moving startup32_load_idt() out of head_64.S and +turning it into an ordinary function using the ordinary 32-bit calling +convention, pull the global variable reference to boot32_idt up into +startup32_load_idt() so that startup32_set_idt_entry() does not need to +discover its own runtime physical address, which will no longer be +correlated with startup_32 once this code is moved into .text. + +While at it, give startup32_set_idt_entry() static linkage. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-11-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -744,16 +744,11 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLO + * + * %eax: Handler address + * %edx: Vector number +- * +- * Physical offset is expected in %ebp ++ * %ecx: IDT address + */ +-SYM_FUNC_START(startup32_set_idt_entry) +- push %ebx +- +- /* IDT entry address to %ebx */ +- leal rva(boot32_idt)(%ebp), %ebx +- shl $3, %edx +- addl %edx, %ebx ++SYM_FUNC_START_LOCAL(startup32_set_idt_entry) ++ /* IDT entry address to %ecx */ ++ leal (%ecx, %edx, 8), %ecx + + /* Build IDT entry, lower 4 bytes */ + movl %eax, %edx +@@ -761,7 +756,7 @@ SYM_FUNC_START(startup32_set_idt_entry) + orl $(__KERNEL32_CS << 16), %edx # Target code segment selector + + /* Store lower 4 bytes to IDT */ +- movl %edx, (%ebx) ++ movl %edx, (%ecx) + + /* Build IDT entry, upper 4 bytes */ + movl %eax, %edx +@@ -769,15 +764,16 @@ SYM_FUNC_START(startup32_set_idt_entry) + orl $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate + + /* Store upper 4 bytes to IDT */ +- movl %edx, 4(%ebx) ++ movl %edx, 4(%ecx) + +- pop %ebx + RET + SYM_FUNC_END(startup32_set_idt_entry) + #endif + + SYM_FUNC_START(startup32_load_idt) + #ifdef CONFIG_AMD_MEM_ENCRYPT ++ leal rva(boot32_idt)(%ebp), %ecx ++ + /* #VC handler */ + leal rva(startup32_vc_handler)(%ebp), %eax + movl $X86_TRAP_VC, %edx diff --git a/queue-6.1/x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch b/queue-6.1/x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch new file mode 100644 index 00000000000..44fac6b4fcb --- /dev/null +++ b/queue-6.1/x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch @@ -0,0 +1,441 @@ +From cb8bda8ad4438b4bcfcf89697fc84803fb210017 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:01 +0100 +Subject: x86/boot/compressed: Rename efi_thunk_64.S to efi-mixed.S + +From: Ard Biesheuvel + +commit cb8bda8ad4438b4bcfcf89697fc84803fb210017 upstream. + +In preparation for moving the mixed mode specific code out of head_64.S, +rename the existing file to clarify that it contains more than just the +mixed mode thunk. + +While at it, clean up the Makefile rules that add it to the build. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-2-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/Makefile | 6 +++--- + arch/x86/boot/compressed/{efi_thunk_64.S => efi_mixed.S} | 0 + arch/x86/boot/compressed/Makefile | 6 + arch/x86/boot/compressed/efi_mixed.S | 195 ++++++++++++++++++++++++++++++++ + arch/x86/boot/compressed/efi_thunk_64.S | 195 -------------------------------- + 3 files changed, 198 insertions(+), 198 deletions(-) + rename arch/x86/boot/compressed/{efi_thunk_64.S => efi_mixed.S} (100%) + +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -108,11 +108,11 @@ endif + vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o + vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o + +-vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o + vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o +-efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a ++vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o ++vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a + +-$(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE ++$(obj)/vmlinux: $(vmlinux-objs-y) FORCE + $(call if_changed,ld) + + OBJCOPYFLAGS_vmlinux.bin := -R .comment -S +--- /dev/null ++++ b/arch/x86/boot/compressed/efi_mixed.S +@@ -0,0 +1,195 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming ++ * ++ * Early support for invoking 32-bit EFI services from a 64-bit kernel. ++ * ++ * Because this thunking occurs before ExitBootServices() we have to ++ * restore the firmware's 32-bit GDT and IDT before we make EFI service ++ * calls. ++ * ++ * On the plus side, we don't have to worry about mangling 64-bit ++ * addresses into 32-bits because we're executing with an identity ++ * mapped pagetable and haven't transitioned to 64-bit virtual addresses ++ * yet. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ .code64 ++ .text ++SYM_FUNC_START(__efi64_thunk) ++ push %rbp ++ push %rbx ++ ++ movl %ds, %eax ++ push %rax ++ movl %es, %eax ++ push %rax ++ movl %ss, %eax ++ push %rax ++ ++ /* Copy args passed on stack */ ++ movq 0x30(%rsp), %rbp ++ movq 0x38(%rsp), %rbx ++ movq 0x40(%rsp), %rax ++ ++ /* ++ * Convert x86-64 ABI params to i386 ABI ++ */ ++ subq $64, %rsp ++ movl %esi, 0x0(%rsp) ++ movl %edx, 0x4(%rsp) ++ movl %ecx, 0x8(%rsp) ++ movl %r8d, 0xc(%rsp) ++ movl %r9d, 0x10(%rsp) ++ movl %ebp, 0x14(%rsp) ++ movl %ebx, 0x18(%rsp) ++ movl %eax, 0x1c(%rsp) ++ ++ leaq 0x20(%rsp), %rbx ++ sgdt (%rbx) ++ ++ addq $16, %rbx ++ sidt (%rbx) ++ ++ leaq 1f(%rip), %rbp ++ ++ /* ++ * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT ++ * and IDT that was installed when the kernel started executing. The ++ * pointers were saved at the EFI stub entry point in head_64.S. ++ * ++ * Pass the saved DS selector to the 32-bit code, and use far return to ++ * restore the saved CS selector. ++ */ ++ leaq efi32_boot_idt(%rip), %rax ++ lidt (%rax) ++ leaq efi32_boot_gdt(%rip), %rax ++ lgdt (%rax) ++ ++ movzwl efi32_boot_ds(%rip), %edx ++ movzwq efi32_boot_cs(%rip), %rax ++ pushq %rax ++ leaq efi_enter32(%rip), %rax ++ pushq %rax ++ lretq ++ ++1: addq $64, %rsp ++ movq %rdi, %rax ++ ++ pop %rbx ++ movl %ebx, %ss ++ pop %rbx ++ movl %ebx, %es ++ pop %rbx ++ movl %ebx, %ds ++ /* Clear out 32-bit selector from FS and GS */ ++ xorl %ebx, %ebx ++ movl %ebx, %fs ++ movl %ebx, %gs ++ ++ /* ++ * Convert 32-bit status code into 64-bit. ++ */ ++ roll $1, %eax ++ rorq $1, %rax ++ ++ pop %rbx ++ pop %rbp ++ RET ++SYM_FUNC_END(__efi64_thunk) ++ ++ .code32 ++/* ++ * EFI service pointer must be in %edi. ++ * ++ * The stack should represent the 32-bit calling convention. ++ */ ++SYM_FUNC_START_LOCAL(efi_enter32) ++ /* Load firmware selector into data and stack segment registers */ ++ movl %edx, %ds ++ movl %edx, %es ++ movl %edx, %fs ++ movl %edx, %gs ++ movl %edx, %ss ++ ++ /* Reload pgtables */ ++ movl %cr3, %eax ++ movl %eax, %cr3 ++ ++ /* Disable paging */ ++ movl %cr0, %eax ++ btrl $X86_CR0_PG_BIT, %eax ++ movl %eax, %cr0 ++ ++ /* Disable long mode via EFER */ ++ movl $MSR_EFER, %ecx ++ rdmsr ++ btrl $_EFER_LME, %eax ++ wrmsr ++ ++ call *%edi ++ ++ /* We must preserve return value */ ++ movl %eax, %edi ++ ++ /* ++ * Some firmware will return with interrupts enabled. Be sure to ++ * disable them before we switch GDTs and IDTs. ++ */ ++ cli ++ ++ lidtl (%ebx) ++ subl $16, %ebx ++ ++ lgdtl (%ebx) ++ ++ movl %cr4, %eax ++ btsl $(X86_CR4_PAE_BIT), %eax ++ movl %eax, %cr4 ++ ++ movl %cr3, %eax ++ movl %eax, %cr3 ++ ++ movl $MSR_EFER, %ecx ++ rdmsr ++ btsl $_EFER_LME, %eax ++ wrmsr ++ ++ xorl %eax, %eax ++ lldt %ax ++ ++ pushl $__KERNEL_CS ++ pushl %ebp ++ ++ /* Enable paging */ ++ movl %cr0, %eax ++ btsl $X86_CR0_PG_BIT, %eax ++ movl %eax, %cr0 ++ lret ++SYM_FUNC_END(efi_enter32) ++ ++ .data ++ .balign 8 ++SYM_DATA_START(efi32_boot_gdt) ++ .word 0 ++ .quad 0 ++SYM_DATA_END(efi32_boot_gdt) ++ ++SYM_DATA_START(efi32_boot_idt) ++ .word 0 ++ .quad 0 ++SYM_DATA_END(efi32_boot_idt) ++ ++SYM_DATA_START(efi32_boot_cs) ++ .word 0 ++SYM_DATA_END(efi32_boot_cs) ++ ++SYM_DATA_START(efi32_boot_ds) ++ .word 0 ++SYM_DATA_END(efi32_boot_ds) +--- a/arch/x86/boot/compressed/efi_thunk_64.S ++++ /dev/null +@@ -1,195 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming +- * +- * Early support for invoking 32-bit EFI services from a 64-bit kernel. +- * +- * Because this thunking occurs before ExitBootServices() we have to +- * restore the firmware's 32-bit GDT and IDT before we make EFI service +- * calls. +- * +- * On the plus side, we don't have to worry about mangling 64-bit +- * addresses into 32-bits because we're executing with an identity +- * mapped pagetable and haven't transitioned to 64-bit virtual addresses +- * yet. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +- .code64 +- .text +-SYM_FUNC_START(__efi64_thunk) +- push %rbp +- push %rbx +- +- movl %ds, %eax +- push %rax +- movl %es, %eax +- push %rax +- movl %ss, %eax +- push %rax +- +- /* Copy args passed on stack */ +- movq 0x30(%rsp), %rbp +- movq 0x38(%rsp), %rbx +- movq 0x40(%rsp), %rax +- +- /* +- * Convert x86-64 ABI params to i386 ABI +- */ +- subq $64, %rsp +- movl %esi, 0x0(%rsp) +- movl %edx, 0x4(%rsp) +- movl %ecx, 0x8(%rsp) +- movl %r8d, 0xc(%rsp) +- movl %r9d, 0x10(%rsp) +- movl %ebp, 0x14(%rsp) +- movl %ebx, 0x18(%rsp) +- movl %eax, 0x1c(%rsp) +- +- leaq 0x20(%rsp), %rbx +- sgdt (%rbx) +- +- addq $16, %rbx +- sidt (%rbx) +- +- leaq 1f(%rip), %rbp +- +- /* +- * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT +- * and IDT that was installed when the kernel started executing. The +- * pointers were saved at the EFI stub entry point in head_64.S. +- * +- * Pass the saved DS selector to the 32-bit code, and use far return to +- * restore the saved CS selector. +- */ +- leaq efi32_boot_idt(%rip), %rax +- lidt (%rax) +- leaq efi32_boot_gdt(%rip), %rax +- lgdt (%rax) +- +- movzwl efi32_boot_ds(%rip), %edx +- movzwq efi32_boot_cs(%rip), %rax +- pushq %rax +- leaq efi_enter32(%rip), %rax +- pushq %rax +- lretq +- +-1: addq $64, %rsp +- movq %rdi, %rax +- +- pop %rbx +- movl %ebx, %ss +- pop %rbx +- movl %ebx, %es +- pop %rbx +- movl %ebx, %ds +- /* Clear out 32-bit selector from FS and GS */ +- xorl %ebx, %ebx +- movl %ebx, %fs +- movl %ebx, %gs +- +- /* +- * Convert 32-bit status code into 64-bit. +- */ +- roll $1, %eax +- rorq $1, %rax +- +- pop %rbx +- pop %rbp +- RET +-SYM_FUNC_END(__efi64_thunk) +- +- .code32 +-/* +- * EFI service pointer must be in %edi. +- * +- * The stack should represent the 32-bit calling convention. +- */ +-SYM_FUNC_START_LOCAL(efi_enter32) +- /* Load firmware selector into data and stack segment registers */ +- movl %edx, %ds +- movl %edx, %es +- movl %edx, %fs +- movl %edx, %gs +- movl %edx, %ss +- +- /* Reload pgtables */ +- movl %cr3, %eax +- movl %eax, %cr3 +- +- /* Disable paging */ +- movl %cr0, %eax +- btrl $X86_CR0_PG_BIT, %eax +- movl %eax, %cr0 +- +- /* Disable long mode via EFER */ +- movl $MSR_EFER, %ecx +- rdmsr +- btrl $_EFER_LME, %eax +- wrmsr +- +- call *%edi +- +- /* We must preserve return value */ +- movl %eax, %edi +- +- /* +- * Some firmware will return with interrupts enabled. Be sure to +- * disable them before we switch GDTs and IDTs. +- */ +- cli +- +- lidtl (%ebx) +- subl $16, %ebx +- +- lgdtl (%ebx) +- +- movl %cr4, %eax +- btsl $(X86_CR4_PAE_BIT), %eax +- movl %eax, %cr4 +- +- movl %cr3, %eax +- movl %eax, %cr3 +- +- movl $MSR_EFER, %ecx +- rdmsr +- btsl $_EFER_LME, %eax +- wrmsr +- +- xorl %eax, %eax +- lldt %ax +- +- pushl $__KERNEL_CS +- pushl %ebp +- +- /* Enable paging */ +- movl %cr0, %eax +- btsl $X86_CR0_PG_BIT, %eax +- movl %eax, %cr0 +- lret +-SYM_FUNC_END(efi_enter32) +- +- .data +- .balign 8 +-SYM_DATA_START(efi32_boot_gdt) +- .word 0 +- .quad 0 +-SYM_DATA_END(efi32_boot_gdt) +- +-SYM_DATA_START(efi32_boot_idt) +- .word 0 +- .quad 0 +-SYM_DATA_END(efi32_boot_idt) +- +-SYM_DATA_START(efi32_boot_cs) +- .word 0 +-SYM_DATA_END(efi32_boot_cs) +- +-SYM_DATA_START(efi32_boot_ds) +- .word 0 +-SYM_DATA_END(efi32_boot_ds) diff --git a/queue-6.1/x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch b/queue-6.1/x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch new file mode 100644 index 00000000000..488c72983f7 --- /dev/null +++ b/queue-6.1/x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch @@ -0,0 +1,64 @@ +From 630f337f0c4fd80390e8600adcab31550aea33df Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:08 +0100 +Subject: x86/boot/compressed: Simplify IDT/GDT preserve/restore in the EFI thunk + +From: Ard Biesheuvel + +commit 630f337f0c4fd80390e8600adcab31550aea33df upstream. + +Tweak the asm and remove some redundant instructions. While at it, +fix the associated comment for style and correctness. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-9-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/efi_mixed.S | 20 +++++++------------- + 1 file changed, 7 insertions(+), 13 deletions(-) + +--- a/arch/x86/boot/compressed/efi_mixed.S ++++ b/arch/x86/boot/compressed/efi_mixed.S +@@ -96,24 +96,20 @@ SYM_FUNC_START(__efi64_thunk) + + leaq 0x20(%rsp), %rbx + sgdt (%rbx) +- +- addq $16, %rbx +- sidt (%rbx) ++ sidt 16(%rbx) + + leaq 1f(%rip), %rbp + + /* +- * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT +- * and IDT that was installed when the kernel started executing. The +- * pointers were saved by the efi32_entry() routine below. ++ * Switch to IDT and GDT with 32-bit segments. These are the firmware ++ * GDT and IDT that were installed when the kernel started executing. ++ * The pointers were saved by the efi32_entry() routine below. + * + * Pass the saved DS selector to the 32-bit code, and use far return to + * restore the saved CS selector. + */ +- leaq efi32_boot_idt(%rip), %rax +- lidt (%rax) +- leaq efi32_boot_gdt(%rip), %rax +- lgdt (%rax) ++ lidt efi32_boot_idt(%rip) ++ lgdt efi32_boot_gdt(%rip) + + movzwl efi32_boot_ds(%rip), %edx + movzwq efi32_boot_cs(%rip), %rax +@@ -187,9 +183,7 @@ SYM_FUNC_START_LOCAL(efi_enter32) + */ + cli + +- lidtl (%ebx) +- subl $16, %ebx +- ++ lidtl 16(%ebx) + lgdtl (%ebx) + + movl %cr4, %eax diff --git a/queue-6.1/x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch b/queue-6.1/x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch new file mode 100644 index 00000000000..159163afab3 --- /dev/null +++ b/queue-6.1/x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch @@ -0,0 +1,141 @@ +From 7734a0f31e99c433df3063bbb7e8ee5a16a2cb82 Mon Sep 17 00:00:00 2001 +From: Alexander Lobakin +Date: Mon, 9 Jan 2023 18:04:02 +0100 +Subject: x86/boot: Robustify calling startup_{32,64}() from the decompressor code + +From: Alexander Lobakin + +commit 7734a0f31e99c433df3063bbb7e8ee5a16a2cb82 upstream. + +After commit ce697ccee1a8 ("kbuild: remove head-y syntax"), I +started digging whether x86 is ready for removing this old cruft. +Removing its objects from the list makes the kernel unbootable. +This applies only to bzImage, vmlinux still works correctly. +The reason is that with no strict object order determined by the +linker arguments, not the linker script, startup_64 can be placed +not right at the beginning of the kernel. +Here's vmlinux.map's beginning before removing: + + ffffffff81000000 vmlinux.o:(.head.text) + ffffffff81000000 startup_64 + ffffffff81000070 secondary_startup_64 + ffffffff81000075 secondary_startup_64_no_verify + ffffffff81000160 verify_cpu + +and after: + + ffffffff81000000 vmlinux.o:(.head.text) + ffffffff81000000 pvh_start_xen + ffffffff81000080 startup_64 + ffffffff810000f0 secondary_startup_64 + ffffffff810000f5 secondary_startup_64_no_verify + +Not a problem itself, but the self-extractor code has the address of +that function hardcoded the beginning, not looking onto the ELF +header, which always contains the address of startup_{32,64}(). + +So, instead of doing an "act of blind faith", just take the address +from the ELF header and extract a relative offset to the entry +point. The decompressor function already returns a pointer to the +beginning of the kernel to the Asm code, which then jumps to it, +so add that offset to the return value. +This doesn't change anything for now, but allows to resign from the +"head object list" for x86 and makes sure valid Kbuild or any other +improvements won't break anything here in general. + +Signed-off-by: Alexander Lobakin +Signed-off-by: Ingo Molnar +Tested-by: Jiri Slaby +Cc: "H. Peter Anvin" +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20230109170403.4117105-2-alexandr.lobakin@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_32.S | 2 +- + arch/x86/boot/compressed/head_64.S | 2 +- + arch/x86/boot/compressed/misc.c | 18 +++++++++++------- + 3 files changed, 13 insertions(+), 9 deletions(-) + +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -187,7 +187,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + leal boot_heap@GOTOFF(%ebx), %eax + pushl %eax /* heap area */ + pushl %esi /* real mode pointer */ +- call extract_kernel /* returns kernel location in %eax */ ++ call extract_kernel /* returns kernel entry point in %eax */ + addl $24, %esp + + /* +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -580,7 +580,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + movl input_len(%rip), %ecx /* input_len */ + movq %rbp, %r8 /* output target address */ + movl output_len(%rip), %r9d /* decompressed length, end of relocs */ +- call extract_kernel /* returns kernel location in %rax */ ++ call extract_kernel /* returns kernel entry point in %rax */ + popq %rsi + + /* +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -277,7 +277,7 @@ static inline void handle_relocations(vo + { } + #endif + +-static void parse_elf(void *output) ++static size_t parse_elf(void *output) + { + #ifdef CONFIG_X86_64 + Elf64_Ehdr ehdr; +@@ -293,10 +293,8 @@ static void parse_elf(void *output) + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || +- ehdr.e_ident[EI_MAG3] != ELFMAG3) { ++ ehdr.e_ident[EI_MAG3] != ELFMAG3) + error("Kernel is not a valid ELF file"); +- return; +- } + + debug_putstr("Parsing ELF... "); + +@@ -328,6 +326,8 @@ static void parse_elf(void *output) + } + + free(phdrs); ++ ++ return ehdr.e_entry - LOAD_PHYSICAL_ADDR; + } + + /* +@@ -356,6 +356,7 @@ asmlinkage __visible void *extract_kerne + const unsigned long kernel_total_size = VO__end - VO__text; + unsigned long virt_addr = LOAD_PHYSICAL_ADDR; + unsigned long needed_size; ++ size_t entry_offset; + + /* Retain x86 boot parameters pointer passed from startup_32/64. */ + boot_params = rmode; +@@ -456,14 +457,17 @@ asmlinkage __visible void *extract_kerne + debug_putstr("\nDecompressing Linux... "); + __decompress(input_data, input_len, NULL, NULL, output, output_len, + NULL, error); +- parse_elf(output); ++ entry_offset = parse_elf(output); + handle_relocations(output, output_len, virt_addr); +- debug_putstr("done.\nBooting the kernel.\n"); ++ ++ debug_putstr("done.\nBooting the kernel (entry_offset: 0x"); ++ debug_puthex(entry_offset); ++ debug_putstr(").\n"); + + /* Disable exception handling before booting the kernel */ + cleanup_exception_handling(); + +- return output; ++ return output + entry_offset; + } + + void fortify_panic(const char *name) diff --git a/queue-6.1/x86-decompressor-assign-paging-related-global-variables-earlier.patch b/queue-6.1/x86-decompressor-assign-paging-related-global-variables-earlier.patch new file mode 100644 index 00000000000..da82e2bf20d --- /dev/null +++ b/queue-6.1/x86-decompressor-assign-paging-related-global-variables-earlier.patch @@ -0,0 +1,63 @@ +From 00c6b0978ec182f1a672095930872168b9d5b1e2 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:05 +0200 +Subject: x86/decompressor: Assign paging related global variables earlier + +From: Ard Biesheuvel + +commit 00c6b0978ec182f1a672095930872168b9d5b1e2 upstream. + +There is no need to defer the assignment of the paging related global +variables 'pgdir_shift' and 'ptrs_per_p4d' until after the trampoline is +cleaned up, so assign them as soon as it is clear that 5-level paging +will be enabled. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-9-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/misc.h | 2 -- + arch/x86/boot/compressed/pgtable_64.c | 14 +++++--------- + 2 files changed, 5 insertions(+), 11 deletions(-) + +--- a/arch/x86/boot/compressed/misc.h ++++ b/arch/x86/boot/compressed/misc.h +@@ -170,9 +170,7 @@ static inline int count_immovable_mem_re + #endif + + /* ident_map_64.c */ +-#ifdef CONFIG_X86_5LEVEL + extern unsigned int __pgtable_l5_enabled, pgdir_shift, ptrs_per_p4d; +-#endif + extern void kernel_add_identity_map(unsigned long start, unsigned long end); + + /* Used by PAGE_KERN* macros: */ +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -130,6 +130,11 @@ struct paging_config paging_prepare(void + native_cpuid_eax(0) >= 7 && + (native_cpuid_ecx(7) & (1 << (X86_FEATURE_LA57 & 31)))) { + paging_config.l5_required = 1; ++ ++ /* Initialize variables for 5-level paging */ ++ __pgtable_l5_enabled = 1; ++ pgdir_shift = 48; ++ ptrs_per_p4d = 512; + } + + paging_config.trampoline_start = find_trampoline_placement(); +@@ -206,13 +211,4 @@ void cleanup_trampoline(void *pgtable) + + /* Restore trampoline memory */ + memcpy(trampoline_32bit, trampoline_save, TRAMPOLINE_32BIT_SIZE); +- +- /* Initialize variables for 5-level paging */ +-#ifdef CONFIG_X86_5LEVEL +- if (__read_cr4() & X86_CR4_LA57) { +- __pgtable_l5_enabled = 1; +- pgdir_shift = 48; +- ptrs_per_p4d = 512; +- } +-#endif + } diff --git a/queue-6.1/x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch b/queue-6.1/x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch new file mode 100644 index 00000000000..6a724fd27ab --- /dev/null +++ b/queue-6.1/x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch @@ -0,0 +1,185 @@ +From bd328aa01ff77a45aeffea5fc4521854291db11f Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:08 +0200 +Subject: x86/decompressor: Avoid the need for a stack in the 32-bit trampoline + +From: Ard Biesheuvel + +commit bd328aa01ff77a45aeffea5fc4521854291db11f upstream. + +The 32-bit trampoline no longer uses the stack for anything except +performing a far return back to long mode, and preserving the caller's +stack pointer value. Currently, the trampoline stack is placed in the +same page that carries the trampoline code, which means this page must +be mapped writable and executable, and the stack is therefore executable +as well. + +Replace the far return with a far jump, so that the return address can +be pre-calculated and patched into the code before it is called. This +removes the need for a 32-bit addressable stack entirely, and in a later +patch, this will be taken advantage of by removing writable permissions +from (and adding executable permissions to) the trampoline code page +when booting via the EFI stub. + +Note that the value of RSP still needs to be preserved explicitly across +the switch into 32-bit mode, as the register may get truncated to 32 +bits. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-12-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 45 ++++++++++++++++++++-------------- + arch/x86/boot/compressed/pgtable.h | 4 +-- + arch/x86/boot/compressed/pgtable_64.c | 12 ++++++++- + 3 files changed, 40 insertions(+), 21 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -558,6 +558,7 @@ SYM_FUNC_END(.Lrelocated) + * trampoline memory. A non-zero second argument (ESI) means that the + * trampoline needs to enable 5-level paging. + */ ++ .section ".rodata", "a", @progbits + SYM_CODE_START(trampoline_32bit_src) + /* + * Preserve live 64-bit registers on the stack: this is necessary +@@ -568,13 +569,9 @@ SYM_CODE_START(trampoline_32bit_src) + pushq %rbp + pushq %rbx + +- /* Set up 32-bit addressable stack and push the old RSP value */ +- leaq (TRAMPOLINE_32BIT_STACK_END - 8)(%rcx), %rbx +- movq %rsp, (%rbx) +- movq %rbx, %rsp +- +- /* Take the address of the trampoline exit code */ +- leaq .Lret(%rip), %rbx ++ /* Preserve top half of RSP in a legacy mode GPR to avoid truncation */ ++ movq %rsp, %rbx ++ shrq $32, %rbx + + /* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */ + pushq $__KERNEL32_CS +@@ -582,9 +579,17 @@ SYM_CODE_START(trampoline_32bit_src) + pushq %rax + lretq + ++ /* ++ * The 32-bit code below will do a far jump back to long mode and end ++ * up here after reconfiguring the number of paging levels. First, the ++ * stack pointer needs to be restored to its full 64-bit value before ++ * the callee save register contents can be popped from the stack. ++ */ + .Lret: ++ shlq $32, %rbx ++ orq %rbx, %rsp ++ + /* Restore the preserved 64-bit registers */ +- movq (%rsp), %rsp + popq %rbx + popq %rbp + popq %r15 +@@ -592,11 +597,6 @@ SYM_CODE_START(trampoline_32bit_src) + + .code32 + 0: +- /* Set up data and stack segments */ +- movl $__KERNEL_DS, %eax +- movl %eax, %ds +- movl %eax, %ss +- + /* Disable paging */ + movl %cr0, %eax + btrl $X86_CR0_PG_BIT, %eax +@@ -651,18 +651,26 @@ SYM_CODE_START(trampoline_32bit_src) + 1: + movl %eax, %cr4 + +- /* Prepare the stack for far return to Long Mode */ +- pushl $__KERNEL_CS +- pushl %ebx +- + /* Enable paging again. */ + movl %cr0, %eax + btsl $X86_CR0_PG_BIT, %eax + movl %eax, %cr0 + +- lret ++ /* ++ * Return to the 64-bit calling code using LJMP rather than LRET, to ++ * avoid the need for a 32-bit addressable stack. The destination ++ * address will be adjusted after the template code is copied into a ++ * 32-bit addressable buffer. ++ */ ++.Ljmp: ljmpl $__KERNEL_CS, $(.Lret - trampoline_32bit_src) + SYM_CODE_END(trampoline_32bit_src) + ++/* ++ * This symbol is placed right after trampoline_32bit_src() so its address can ++ * be used to infer the size of the trampoline code. ++ */ ++SYM_DATA(trampoline_ljmp_imm_offset, .word .Ljmp + 1 - trampoline_32bit_src) ++ + /* + * The trampoline code has a size limit. + * Make sure we fail to compile if the trampoline code grows +@@ -670,6 +678,7 @@ SYM_CODE_END(trampoline_32bit_src) + */ + .org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE + ++ .text + SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode) + /* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */ + 1: +--- a/arch/x86/boot/compressed/pgtable.h ++++ b/arch/x86/boot/compressed/pgtable.h +@@ -8,13 +8,13 @@ + #define TRAMPOLINE_32BIT_CODE_OFFSET PAGE_SIZE + #define TRAMPOLINE_32BIT_CODE_SIZE 0xA0 + +-#define TRAMPOLINE_32BIT_STACK_END TRAMPOLINE_32BIT_SIZE +- + #ifndef __ASSEMBLER__ + + extern unsigned long *trampoline_32bit; + + extern void trampoline_32bit_src(void *trampoline, bool enable_5lvl); + ++extern const u16 trampoline_ljmp_imm_offset; ++ + #endif /* __ASSEMBLER__ */ + #endif /* BOOT_COMPRESSED_PAGETABLE_H */ +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -109,6 +109,7 @@ static unsigned long find_trampoline_pla + struct paging_config paging_prepare(void *rmode) + { + struct paging_config paging_config = {}; ++ void *tramp_code; + + /* Initialize boot_params. Required for cmdline_find_option_bool(). */ + boot_params = rmode; +@@ -148,10 +149,19 @@ struct paging_config paging_prepare(void + memset(trampoline_32bit, 0, TRAMPOLINE_32BIT_SIZE); + + /* Copy trampoline code in place */ +- memcpy(trampoline_32bit + TRAMPOLINE_32BIT_CODE_OFFSET / sizeof(unsigned long), ++ tramp_code = memcpy(trampoline_32bit + ++ TRAMPOLINE_32BIT_CODE_OFFSET / sizeof(unsigned long), + &trampoline_32bit_src, TRAMPOLINE_32BIT_CODE_SIZE); + + /* ++ * Avoid the need for a stack in the 32-bit trampoline code, by using ++ * LJMP rather than LRET to return back to long mode. LJMP takes an ++ * immediate absolute address, which needs to be adjusted based on the ++ * placement of the trampoline. ++ */ ++ *(u32 *)(tramp_code + trampoline_ljmp_imm_offset) += (unsigned long)tramp_code; ++ ++ /* + * The code below prepares page table in trampoline memory. + * + * The new page table will be used by trampoline code for switching diff --git a/queue-6.1/x86-decompressor-call-trampoline-as-a-normal-function.patch b/queue-6.1/x86-decompressor-call-trampoline-as-a-normal-function.patch new file mode 100644 index 00000000000..ef347c10890 --- /dev/null +++ b/queue-6.1/x86-decompressor-call-trampoline-as-a-normal-function.patch @@ -0,0 +1,166 @@ +From e8972a76aa90c05a0078043413f806c02fcb3487 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:06 +0200 +Subject: x86/decompressor: Call trampoline as a normal function + +From: Ard Biesheuvel + +commit e8972a76aa90c05a0078043413f806c02fcb3487 upstream. + +Move the long return to switch to 32-bit mode into the trampoline code +so it can be called as an ordinary function. This will allow it to be +called directly from C code in a subsequent patch. + +While at it, reorganize the code somewhat to keep the prologue and +epilogue of the function together, making the code a bit easier to +follow. Also, given that the trampoline is now entered in 64-bit mode, a +simple RIP-relative reference can be used to take the address of the +exit point. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-10-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 79 ++++++++++++++++--------------------- + arch/x86/boot/compressed/pgtable.h | 2 + 2 files changed, 36 insertions(+), 45 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -450,39 +450,8 @@ SYM_CODE_START(startup_64) + /* Save the trampoline address in RCX */ + movq %rax, %rcx + +- /* Set up 32-bit addressable stack */ +- leaq TRAMPOLINE_32BIT_STACK_END(%rcx), %rsp +- +- /* +- * Preserve live 64-bit registers on the stack: this is necessary +- * because the architecture does not guarantee that GPRs will retain +- * their full 64-bit values across a 32-bit mode switch. +- */ +- pushq %r15 +- pushq %rbp +- pushq %rbx +- +- /* +- * Push the 64-bit address of trampoline_return() onto the new stack. +- * It will be used by the trampoline to return to the main code. Due to +- * the 32-bit mode switch, it cannot be kept it in a register either. +- */ +- leaq trampoline_return(%rip), %rdi +- pushq %rdi +- +- /* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */ +- pushq $__KERNEL32_CS + leaq TRAMPOLINE_32BIT_CODE_OFFSET(%rax), %rax +- pushq %rax +- lretq +-trampoline_return: +- /* Restore live 64-bit registers */ +- popq %rbx +- popq %rbp +- popq %r15 +- +- /* Restore the stack, the 32-bit trampoline uses its own stack */ +- leaq rva(boot_stack_end)(%rbx), %rsp ++ call *%rax + + /* + * cleanup_trampoline() would restore trampoline memory. +@@ -579,7 +548,6 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + jmp *%rax + SYM_FUNC_END(.Lrelocated) + +- .code32 + /* + * This is the 32-bit trampoline that will be copied over to low memory. + * +@@ -588,6 +556,39 @@ SYM_FUNC_END(.Lrelocated) + * Non zero RDX means trampoline needs to enable 5-level paging. + */ + SYM_CODE_START(trampoline_32bit_src) ++ /* ++ * Preserve live 64-bit registers on the stack: this is necessary ++ * because the architecture does not guarantee that GPRs will retain ++ * their full 64-bit values across a 32-bit mode switch. ++ */ ++ pushq %r15 ++ pushq %rbp ++ pushq %rbx ++ ++ /* Set up 32-bit addressable stack and push the old RSP value */ ++ leaq (TRAMPOLINE_32BIT_STACK_END - 8)(%rcx), %rbx ++ movq %rsp, (%rbx) ++ movq %rbx, %rsp ++ ++ /* Take the address of the trampoline exit code */ ++ leaq .Lret(%rip), %rbx ++ ++ /* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */ ++ pushq $__KERNEL32_CS ++ leaq 0f(%rip), %rax ++ pushq %rax ++ lretq ++ ++.Lret: ++ /* Restore the preserved 64-bit registers */ ++ movq (%rsp), %rsp ++ popq %rbx ++ popq %rbp ++ popq %r15 ++ retq ++ ++ .code32 ++0: + /* Set up data and stack segments */ + movl $__KERNEL_DS, %eax + movl %eax, %ds +@@ -651,12 +652,9 @@ SYM_CODE_START(trampoline_32bit_src) + 1: + movl %eax, %cr4 + +- /* Calculate address of paging_enabled() once we are executing in the trampoline */ +- leal .Lpaging_enabled - trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_OFFSET(%ecx), %eax +- + /* Prepare the stack for far return to Long Mode */ + pushl $__KERNEL_CS +- pushl %eax ++ pushl %ebx + + /* Enable paging again. */ + movl %cr0, %eax +@@ -666,12 +664,6 @@ SYM_CODE_START(trampoline_32bit_src) + lret + SYM_CODE_END(trampoline_32bit_src) + +- .code64 +-SYM_FUNC_START_LOCAL_NOALIGN(.Lpaging_enabled) +- /* Return from the trampoline */ +- retq +-SYM_FUNC_END(.Lpaging_enabled) +- + /* + * The trampoline code has a size limit. + * Make sure we fail to compile if the trampoline code grows +@@ -679,7 +671,6 @@ SYM_FUNC_END(.Lpaging_enabled) + */ + .org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE + +- .code32 + SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode) + /* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */ + 1: +--- a/arch/x86/boot/compressed/pgtable.h ++++ b/arch/x86/boot/compressed/pgtable.h +@@ -6,7 +6,7 @@ + #define TRAMPOLINE_32BIT_PGTABLE_OFFSET 0 + + #define TRAMPOLINE_32BIT_CODE_OFFSET PAGE_SIZE +-#define TRAMPOLINE_32BIT_CODE_SIZE 0x80 ++#define TRAMPOLINE_32BIT_CODE_SIZE 0xA0 + + #define TRAMPOLINE_32BIT_STACK_END TRAMPOLINE_32BIT_SIZE + diff --git a/queue-6.1/x86-decompressor-call-trampoline-directly-from-c-code.patch b/queue-6.1/x86-decompressor-call-trampoline-directly-from-c-code.patch new file mode 100644 index 00000000000..66947b1fcee --- /dev/null +++ b/queue-6.1/x86-decompressor-call-trampoline-directly-from-c-code.patch @@ -0,0 +1,189 @@ +From 64ef578b6b6866bec012544416946533444036c8 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:09 +0200 +Subject: x86/decompressor: Call trampoline directly from C code + +From: Ard Biesheuvel + +commit 64ef578b6b6866bec012544416946533444036c8 upstream. + +Instead of returning to the asm calling code to invoke the trampoline, +call it straight from the C code that sets it up. That way, the struct +return type is no longer needed for returning two values, and the call +can be made conditional more cleanly in a subsequent patch. + +This means that all callee save 64-bit registers need to be preserved +and restored, as their contents may not survive the legacy mode switch. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-13-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 31 +++++++++++++------------------ + arch/x86/boot/compressed/pgtable_64.c | 32 +++++++++++++------------------- + 2 files changed, 26 insertions(+), 37 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -433,25 +433,14 @@ SYM_CODE_START(startup_64) + #endif + + /* +- * paging_prepare() sets up the trampoline and checks if we need to +- * enable 5-level paging. +- * +- * paging_prepare() returns a two-quadword structure which lands +- * into RDX:RAX: +- * - Address of the trampoline is returned in RAX. +- * - Non zero RDX means trampoline needs to enable 5-level +- * paging. ++ * configure_5level_paging() updates the number of paging levels using ++ * a trampoline in 32-bit addressable memory if the current number does ++ * not match the desired number. + * + * Pass the boot_params pointer as the first argument. + */ + movq %r15, %rdi +- call paging_prepare +- +- /* Pass the trampoline address and boolean flag as args #1 and #2 */ +- movq %rax, %rdi +- movq %rdx, %rsi +- leaq TRAMPOLINE_32BIT_CODE_OFFSET(%rax), %rax +- call *%rax ++ call configure_5level_paging + + /* + * cleanup_trampoline() would restore trampoline memory. +@@ -561,11 +550,14 @@ SYM_FUNC_END(.Lrelocated) + .section ".rodata", "a", @progbits + SYM_CODE_START(trampoline_32bit_src) + /* +- * Preserve live 64-bit registers on the stack: this is necessary +- * because the architecture does not guarantee that GPRs will retain +- * their full 64-bit values across a 32-bit mode switch. ++ * Preserve callee save 64-bit registers on the stack: this is ++ * necessary because the architecture does not guarantee that GPRs will ++ * retain their full 64-bit values across a 32-bit mode switch. + */ + pushq %r15 ++ pushq %r14 ++ pushq %r13 ++ pushq %r12 + pushq %rbp + pushq %rbx + +@@ -592,6 +584,9 @@ SYM_CODE_START(trampoline_32bit_src) + /* Restore the preserved 64-bit registers */ + popq %rbx + popq %rbp ++ popq %r12 ++ popq %r13 ++ popq %r14 + popq %r15 + retq + +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -16,11 +16,6 @@ unsigned int __section(".data") pgdir_sh + unsigned int __section(".data") ptrs_per_p4d = 1; + #endif + +-struct paging_config { +- unsigned long trampoline_start; +- unsigned long l5_required; +-}; +- + /* Buffer to preserve trampoline memory */ + static char trampoline_save[TRAMPOLINE_32BIT_SIZE]; + +@@ -29,7 +24,7 @@ static char trampoline_save[TRAMPOLINE_3 + * purposes. + * + * Avoid putting the pointer into .bss as it will be cleared between +- * paging_prepare() and extract_kernel(). ++ * configure_5level_paging() and extract_kernel(). + */ + unsigned long *trampoline_32bit __section(".data"); + +@@ -106,13 +101,13 @@ static unsigned long find_trampoline_pla + return bios_start - TRAMPOLINE_32BIT_SIZE; + } + +-struct paging_config paging_prepare(void *rmode) ++asmlinkage void configure_5level_paging(struct boot_params *bp) + { +- struct paging_config paging_config = {}; +- void *tramp_code; ++ void (*toggle_la57)(void *trampoline, bool enable_5lvl); ++ bool l5_required = false; + + /* Initialize boot_params. Required for cmdline_find_option_bool(). */ +- boot_params = rmode; ++ boot_params = bp; + + /* + * Check if LA57 is desired and supported. +@@ -130,7 +125,7 @@ struct paging_config paging_prepare(void + !cmdline_find_option_bool("no5lvl") && + native_cpuid_eax(0) >= 7 && + (native_cpuid_ecx(7) & (1 << (X86_FEATURE_LA57 & 31)))) { +- paging_config.l5_required = 1; ++ l5_required = true; + + /* Initialize variables for 5-level paging */ + __pgtable_l5_enabled = 1; +@@ -138,9 +133,7 @@ struct paging_config paging_prepare(void + ptrs_per_p4d = 512; + } + +- paging_config.trampoline_start = find_trampoline_placement(); +- +- trampoline_32bit = (unsigned long *)paging_config.trampoline_start; ++ trampoline_32bit = (unsigned long *)find_trampoline_placement(); + + /* Preserve trampoline memory */ + memcpy(trampoline_save, trampoline_32bit, TRAMPOLINE_32BIT_SIZE); +@@ -149,7 +142,7 @@ struct paging_config paging_prepare(void + memset(trampoline_32bit, 0, TRAMPOLINE_32BIT_SIZE); + + /* Copy trampoline code in place */ +- tramp_code = memcpy(trampoline_32bit + ++ toggle_la57 = memcpy(trampoline_32bit + + TRAMPOLINE_32BIT_CODE_OFFSET / sizeof(unsigned long), + &trampoline_32bit_src, TRAMPOLINE_32BIT_CODE_SIZE); + +@@ -159,7 +152,8 @@ struct paging_config paging_prepare(void + * immediate absolute address, which needs to be adjusted based on the + * placement of the trampoline. + */ +- *(u32 *)(tramp_code + trampoline_ljmp_imm_offset) += (unsigned long)tramp_code; ++ *(u32 *)((u8 *)toggle_la57 + trampoline_ljmp_imm_offset) += ++ (unsigned long)toggle_la57; + + /* + * The code below prepares page table in trampoline memory. +@@ -175,10 +169,10 @@ struct paging_config paging_prepare(void + * We are not going to use the page table in trampoline memory if we + * are already in the desired paging mode. + */ +- if (paging_config.l5_required == !!(native_read_cr4() & X86_CR4_LA57)) ++ if (l5_required == !!(native_read_cr4() & X86_CR4_LA57)) + goto out; + +- if (paging_config.l5_required) { ++ if (l5_required) { + /* + * For 4- to 5-level paging transition, set up current CR3 as + * the first and the only entry in a new top-level page table. +@@ -201,7 +195,7 @@ struct paging_config paging_prepare(void + } + + out: +- return paging_config; ++ toggle_la57(trampoline_32bit, l5_required); + } + + void cleanup_trampoline(void *pgtable) diff --git a/queue-6.1/x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch b/queue-6.1/x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch new file mode 100644 index 00000000000..28c6f171966 --- /dev/null +++ b/queue-6.1/x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch @@ -0,0 +1,87 @@ +From 03dda95137d3247564854ad9032c0354273a159d Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:12 +0200 +Subject: x86/decompressor: Merge trampoline cleanup with switching code + +From: Ard Biesheuvel + +commit 03dda95137d3247564854ad9032c0354273a159d upstream. + +Now that the trampoline setup code and the actual invocation of it are +all done from the C routine, the trampoline cleanup can be merged into +it as well, instead of returning to asm just to call another C function. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-16-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 14 ++++---------- + arch/x86/boot/compressed/pgtable_64.c | 18 ++++-------------- + 2 files changed, 8 insertions(+), 24 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -433,20 +433,14 @@ SYM_CODE_START(startup_64) + * a trampoline in 32-bit addressable memory if the current number does + * not match the desired number. + * +- * Pass the boot_params pointer as the first argument. ++ * Pass the boot_params pointer as the first argument. The second ++ * argument is the relocated address of the page table to use instead ++ * of the page table in trampoline memory (if required). + */ + movq %r15, %rdi ++ leaq rva(top_pgtable)(%rbx), %rsi + call configure_5level_paging + +- /* +- * cleanup_trampoline() would restore trampoline memory. +- * +- * RDI is address of the page table to use instead of page table +- * in trampoline memory (if required). +- */ +- leaq rva(top_pgtable)(%rbx), %rdi +- call cleanup_trampoline +- + /* Zero EFLAGS */ + pushq $0 + popfq +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -101,7 +101,7 @@ static unsigned long find_trampoline_pla + return bios_start - TRAMPOLINE_32BIT_SIZE; + } + +-asmlinkage void configure_5level_paging(struct boot_params *bp) ++asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable) + { + void (*toggle_la57)(void *cr3); + bool l5_required = false; +@@ -191,22 +191,12 @@ asmlinkage void configure_5level_paging( + } + + toggle_la57(trampoline_32bit); +-} +- +-void cleanup_trampoline(void *pgtable) +-{ +- void *trampoline_pgtable; +- +- trampoline_pgtable = trampoline_32bit; + + /* +- * Move the top level page table out of trampoline memory, +- * if it's there. ++ * Move the top level page table out of trampoline memory. + */ +- if ((void *)__native_read_cr3() == trampoline_pgtable) { +- memcpy(pgtable, trampoline_pgtable, PAGE_SIZE); +- native_write_cr3((unsigned long)pgtable); +- } ++ memcpy(pgtable, trampoline_32bit, PAGE_SIZE); ++ native_write_cr3((unsigned long)pgtable); + + /* Restore trampoline memory */ + memcpy(trampoline_32bit, trampoline_save, TRAMPOLINE_32BIT_SIZE); diff --git a/queue-6.1/x86-decompressor-move-global-symbol-references-to-c-code.patch b/queue-6.1/x86-decompressor-move-global-symbol-references-to-c-code.patch new file mode 100644 index 00000000000..640071c10b3 --- /dev/null +++ b/queue-6.1/x86-decompressor-move-global-symbol-references-to-c-code.patch @@ -0,0 +1,132 @@ +From 24388292e2d7fae79a0d4183cc91716b851299cf Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:16 +0200 +Subject: x86/decompressor: Move global symbol references to C code + +From: Ard Biesheuvel + +commit 24388292e2d7fae79a0d4183cc91716b851299cf upstream. + +It is no longer necessary to be cautious when referring to global +variables in the position independent decompressor code, now that it is +built using PIE codegen and makes an assertion in the linker script that +no GOT entries exist (which would require adjustment for the actual +runtime load address of the decompressor binary). + +This means global variables can be referenced directly from C code, +instead of having to pass their runtime addresses into C routines from +asm code, which needs to happen at each call site. Do so for the code +that will be called directly from the EFI stub after a subsequent patch, +and avoid the need to duplicate this logic a third time. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-20-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_32.S | 8 -------- + arch/x86/boot/compressed/head_64.S | 10 ++-------- + arch/x86/boot/compressed/misc.c | 16 +++++++++------- + 3 files changed, 11 insertions(+), 23 deletions(-) + +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -179,13 +179,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + */ + /* push arguments for extract_kernel: */ + +- pushl output_len@GOTOFF(%ebx) /* decompressed length, end of relocs */ + pushl %ebp /* output address */ +- pushl input_len@GOTOFF(%ebx) /* input_len */ +- leal input_data@GOTOFF(%ebx), %eax +- pushl %eax /* input_data */ +- leal boot_heap@GOTOFF(%ebx), %eax +- pushl %eax /* heap area */ + pushl %esi /* real mode pointer */ + call extract_kernel /* returns kernel entry point in %eax */ + addl $24, %esp +@@ -213,8 +207,6 @@ SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt + */ + .bss + .balign 4 +-boot_heap: +- .fill BOOT_HEAP_SIZE, 1, 0 + boot_stack: + .fill BOOT_STACK_SIZE, 1, 0 + boot_stack_end: +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -511,13 +511,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + /* + * Do the extraction, and jump to the new kernel.. + */ +- /* pass struct boot_params pointer */ ++ /* pass struct boot_params pointer and output target address */ + movq %r15, %rdi +- leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ +- leaq input_data(%rip), %rdx /* input_data */ +- movl input_len(%rip), %ecx /* input_len */ +- movq %rbp, %r8 /* output target address */ +- movl output_len(%rip), %r9d /* decompressed length, end of relocs */ ++ movq %rbp, %rsi + call extract_kernel /* returns kernel entry point in %rax */ + + /* +@@ -675,8 +671,6 @@ SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBA + */ + .bss + .balign 4 +-SYM_DATA_LOCAL(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0) +- + SYM_DATA_START_LOCAL(boot_stack) + .fill BOOT_STACK_SIZE, 1, 0 + .balign 16 +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -330,6 +330,11 @@ static size_t parse_elf(void *output) + return ehdr.e_entry - LOAD_PHYSICAL_ADDR; + } + ++static u8 boot_heap[BOOT_HEAP_SIZE] __aligned(4); ++ ++extern unsigned char input_data[]; ++extern unsigned int input_len, output_len; ++ + /* + * The compressed kernel image (ZO), has been moved so that its position + * is against the end of the buffer used to hold the uncompressed kernel +@@ -347,14 +352,11 @@ static size_t parse_elf(void *output) + * |-------uncompressed kernel image---------| + * + */ +-asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, +- unsigned char *input_data, +- unsigned long input_len, +- unsigned char *output, +- unsigned long output_len) ++asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) + { + const unsigned long kernel_total_size = VO__end - VO__text; + unsigned long virt_addr = LOAD_PHYSICAL_ADDR; ++ memptr heap = (memptr)boot_heap; + unsigned long needed_size; + size_t entry_offset; + +@@ -412,7 +414,7 @@ asmlinkage __visible void *extract_kerne + * entries. This ensures the full mapped area is usable RAM + * and doesn't include any reserved areas. + */ +- needed_size = max(output_len, kernel_total_size); ++ needed_size = max_t(unsigned long, output_len, kernel_total_size); + #ifdef CONFIG_X86_64 + needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN); + #endif +@@ -443,7 +445,7 @@ asmlinkage __visible void *extract_kerne + #ifdef CONFIG_X86_64 + if (heap > 0x3fffffffffffUL) + error("Destination address too large"); +- if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE) ++ if (virt_addr + needed_size > KERNEL_IMAGE_SIZE) + error("Destination virtual address is beyond the kernel mapping area"); + #else + if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) diff --git a/queue-6.1/x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch b/queue-6.1/x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch new file mode 100644 index 00000000000..e493019b5f4 --- /dev/null +++ b/queue-6.1/x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch @@ -0,0 +1,166 @@ +From f97b67a773cd84bd8b55c0a0ec32448a87fc56bb Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:10 +0200 +Subject: x86/decompressor: Only call the trampoline when changing paging levels + +From: Ard Biesheuvel + +commit f97b67a773cd84bd8b55c0a0ec32448a87fc56bb upstream. + +Since the current and desired number of paging levels are known when the +trampoline is being prepared, avoid calling the trampoline at all if it +is clear that calling it is not going to result in a change to the +number of paging levels. + +Given that the CPU is already running in long mode, the PAE and LA57 +settings are necessarily consistent with the currently active page +tables, and other fields in CR4 will be initialized by the startup code +in the kernel proper. So limit the manipulation of CR4 to toggling the +LA57 bit, which is the only thing that really needs doing at this point +in the boot. This also means that there is no need to pass the value of +l5_required to toggle_la57(), as it will not be called unless CR4.LA57 +needs to toggle. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-14-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 45 +++------------------------------- + arch/x86/boot/compressed/pgtable_64.c | 22 ++++++---------- + 2 files changed, 13 insertions(+), 54 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -390,10 +390,6 @@ SYM_CODE_START(startup_64) + * For the trampoline, we need the top page table to reside in lower + * memory as we don't have a way to load 64-bit values into CR3 in + * 32-bit mode. +- * +- * We go though the trampoline even if we don't have to: if we're +- * already in a desired paging mode. This way the trampoline code gets +- * tested on every boot. + */ + + /* Make sure we have GDT with 32-bit code segment */ +@@ -544,8 +540,7 @@ SYM_FUNC_END(.Lrelocated) + * + * Return address is at the top of the stack (might be above 4G). + * The first argument (EDI) contains the 32-bit addressable base of the +- * trampoline memory. A non-zero second argument (ESI) means that the +- * trampoline needs to enable 5-level paging. ++ * trampoline memory. + */ + .section ".rodata", "a", @progbits + SYM_CODE_START(trampoline_32bit_src) +@@ -597,25 +592,10 @@ SYM_CODE_START(trampoline_32bit_src) + btrl $X86_CR0_PG_BIT, %eax + movl %eax, %cr0 + +- /* Check what paging mode we want to be in after the trampoline */ +- testl %esi, %esi +- jz 1f +- +- /* We want 5-level paging: don't touch CR3 if it already points to 5-level page tables */ +- movl %cr4, %eax +- testl $X86_CR4_LA57, %eax +- jnz 3f +- jmp 2f +-1: +- /* We want 4-level paging: don't touch CR3 if it already points to 4-level page tables */ +- movl %cr4, %eax +- testl $X86_CR4_LA57, %eax +- jz 3f +-2: + /* Point CR3 to the trampoline's new top level page table */ + leal TRAMPOLINE_32BIT_PGTABLE_OFFSET(%edi), %eax + movl %eax, %cr3 +-3: ++ + /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */ + movl $MSR_EFER, %ecx + rdmsr +@@ -624,26 +604,9 @@ SYM_CODE_START(trampoline_32bit_src) + jc 1f + wrmsr + 1: +-#ifdef CONFIG_X86_MCE +- /* +- * Preserve CR4.MCE if the kernel will enable #MC support. +- * Clearing MCE may fault in some environments (that also force #MC +- * support). Any machine check that occurs before #MC support is fully +- * configured will crash the system regardless of the CR4.MCE value set +- * here. +- */ ++ /* Toggle CR4.LA57 */ + movl %cr4, %eax +- andl $X86_CR4_MCE, %eax +-#else +- movl $0, %eax +-#endif +- +- /* Enable PAE and LA57 (if required) paging modes */ +- orl $X86_CR4_PAE, %eax +- testl %esi, %esi +- jz 1f +- orl $X86_CR4_LA57, %eax +-1: ++ btcl $X86_CR4_LA57_BIT, %eax + movl %eax, %cr4 + + /* Enable paging again. */ +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -103,7 +103,7 @@ static unsigned long find_trampoline_pla + + asmlinkage void configure_5level_paging(struct boot_params *bp) + { +- void (*toggle_la57)(void *trampoline, bool enable_5lvl); ++ void (*toggle_la57)(void *trampoline); + bool l5_required = false; + + /* Initialize boot_params. Required for cmdline_find_option_bool(). */ +@@ -133,6 +133,13 @@ asmlinkage void configure_5level_paging( + ptrs_per_p4d = 512; + } + ++ /* ++ * The trampoline will not be used if the paging mode is already set to ++ * the desired one. ++ */ ++ if (l5_required == !!(native_read_cr4() & X86_CR4_LA57)) ++ return; ++ + trampoline_32bit = (unsigned long *)find_trampoline_placement(); + + /* Preserve trampoline memory */ +@@ -160,18 +167,8 @@ asmlinkage void configure_5level_paging( + * + * The new page table will be used by trampoline code for switching + * from 4- to 5-level paging or vice versa. +- * +- * If switching is not required, the page table is unused: trampoline +- * code wouldn't touch CR3. + */ + +- /* +- * We are not going to use the page table in trampoline memory if we +- * are already in the desired paging mode. +- */ +- if (l5_required == !!(native_read_cr4() & X86_CR4_LA57)) +- goto out; +- + if (l5_required) { + /* + * For 4- to 5-level paging transition, set up current CR3 as +@@ -194,8 +191,7 @@ asmlinkage void configure_5level_paging( + (void *)src, PAGE_SIZE); + } + +-out: +- toggle_la57(trampoline_32bit, l5_required); ++ toggle_la57(trampoline_32bit); + } + + void cleanup_trampoline(void *pgtable) diff --git a/queue-6.1/x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch b/queue-6.1/x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch new file mode 100644 index 00000000000..586e1c79061 --- /dev/null +++ b/queue-6.1/x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch @@ -0,0 +1,101 @@ +From cb83cece57e1889109dd73ea08ee338668c9d1b8 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:11 +0200 +Subject: x86/decompressor: Pass pgtable address to trampoline directly + +From: Ard Biesheuvel + +commit cb83cece57e1889109dd73ea08ee338668c9d1b8 upstream. + +The only remaining use of the trampoline address by the trampoline +itself is deriving the page table address from it, and this involves +adding an offset of 0x0. So simplify this, and pass the new CR3 value +directly. + +This makes the fact that the page table happens to be at the start of +the trampoline allocation an implementation detail of the caller. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-15-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 8 ++++---- + arch/x86/boot/compressed/pgtable.h | 2 -- + arch/x86/boot/compressed/pgtable_64.c | 9 ++++----- + 3 files changed, 8 insertions(+), 11 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -539,8 +539,9 @@ SYM_FUNC_END(.Lrelocated) + * running in 64-bit mode. + * + * Return address is at the top of the stack (might be above 4G). +- * The first argument (EDI) contains the 32-bit addressable base of the +- * trampoline memory. ++ * The first argument (EDI) contains the address of the temporary PGD level ++ * page table in 32-bit addressable memory which will be programmed into ++ * register CR3. + */ + .section ".rodata", "a", @progbits + SYM_CODE_START(trampoline_32bit_src) +@@ -593,8 +594,7 @@ SYM_CODE_START(trampoline_32bit_src) + movl %eax, %cr0 + + /* Point CR3 to the trampoline's new top level page table */ +- leal TRAMPOLINE_32BIT_PGTABLE_OFFSET(%edi), %eax +- movl %eax, %cr3 ++ movl %edi, %cr3 + + /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */ + movl $MSR_EFER, %ecx +--- a/arch/x86/boot/compressed/pgtable.h ++++ b/arch/x86/boot/compressed/pgtable.h +@@ -3,8 +3,6 @@ + + #define TRAMPOLINE_32BIT_SIZE (2 * PAGE_SIZE) + +-#define TRAMPOLINE_32BIT_PGTABLE_OFFSET 0 +- + #define TRAMPOLINE_32BIT_CODE_OFFSET PAGE_SIZE + #define TRAMPOLINE_32BIT_CODE_SIZE 0xA0 + +--- a/arch/x86/boot/compressed/pgtable_64.c ++++ b/arch/x86/boot/compressed/pgtable_64.c +@@ -103,7 +103,7 @@ static unsigned long find_trampoline_pla + + asmlinkage void configure_5level_paging(struct boot_params *bp) + { +- void (*toggle_la57)(void *trampoline); ++ void (*toggle_la57)(void *cr3); + bool l5_required = false; + + /* Initialize boot_params. Required for cmdline_find_option_bool(). */ +@@ -174,7 +174,7 @@ asmlinkage void configure_5level_paging( + * For 4- to 5-level paging transition, set up current CR3 as + * the first and the only entry in a new top-level page table. + */ +- trampoline_32bit[TRAMPOLINE_32BIT_PGTABLE_OFFSET] = __native_read_cr3() | _PAGE_TABLE_NOENC; ++ *trampoline_32bit = __native_read_cr3() | _PAGE_TABLE_NOENC; + } else { + unsigned long src; + +@@ -187,8 +187,7 @@ asmlinkage void configure_5level_paging( + * may be above 4G. + */ + src = *(unsigned long *)__native_read_cr3() & PAGE_MASK; +- memcpy(trampoline_32bit + TRAMPOLINE_32BIT_PGTABLE_OFFSET / sizeof(unsigned long), +- (void *)src, PAGE_SIZE); ++ memcpy(trampoline_32bit, (void *)src, PAGE_SIZE); + } + + toggle_la57(trampoline_32bit); +@@ -198,7 +197,7 @@ void cleanup_trampoline(void *pgtable) + { + void *trampoline_pgtable; + +- trampoline_pgtable = trampoline_32bit + TRAMPOLINE_32BIT_PGTABLE_OFFSET / sizeof(unsigned long); ++ trampoline_pgtable = trampoline_32bit; + + /* + * Move the top level page table out of trampoline memory, diff --git a/queue-6.1/x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch b/queue-6.1/x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch new file mode 100644 index 00000000000..b2686612787 --- /dev/null +++ b/queue-6.1/x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch @@ -0,0 +1,160 @@ +From 8b63cba746f86a754d66e302c43209cc9b9b6e39 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:04 +0200 +Subject: x86/decompressor: Store boot_params pointer in callee save register + +From: Ard Biesheuvel + +commit 8b63cba746f86a754d66e302c43209cc9b9b6e39 upstream. + +Instead of pushing and popping %RSI several times to preserve the struct +boot_params pointer across the execution of the startup code, move it +into a callee save register before the first call into C, and copy it +back when needed. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-8-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 42 ++++++++++++++----------------------- + 1 file changed, 16 insertions(+), 26 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -408,10 +408,14 @@ SYM_CODE_START(startup_64) + lretq + + .Lon_kernel_cs: ++ /* ++ * RSI holds a pointer to a boot_params structure provided by the ++ * loader, and this needs to be preserved across C function calls. So ++ * move it into a callee saved register. ++ */ ++ movq %rsi, %r15 + +- pushq %rsi + call load_stage1_idt +- popq %rsi + + #ifdef CONFIG_AMD_MEM_ENCRYPT + /* +@@ -422,12 +426,10 @@ SYM_CODE_START(startup_64) + * CPUID instructions being issued, so go ahead and do that now via + * sev_enable(), which will also handle the rest of the SEV-related + * detection/setup to ensure that has been done in advance of any dependent +- * code. ++ * code. Pass the boot_params pointer as the first argument. + */ +- pushq %rsi +- movq %rsi, %rdi /* real mode address */ ++ movq %r15, %rdi + call sev_enable +- popq %rsi + #endif + + /* +@@ -440,13 +442,10 @@ SYM_CODE_START(startup_64) + * - Non zero RDX means trampoline needs to enable 5-level + * paging. + * +- * RSI holds real mode data and needs to be preserved across +- * this function call. ++ * Pass the boot_params pointer as the first argument. + */ +- pushq %rsi +- movq %rsi, %rdi /* real mode address */ ++ movq %r15, %rdi + call paging_prepare +- popq %rsi + + /* Save the trampoline address in RCX */ + movq %rax, %rcx +@@ -459,9 +458,9 @@ SYM_CODE_START(startup_64) + * because the architecture does not guarantee that GPRs will retain + * their full 64-bit values across a 32-bit mode switch. + */ ++ pushq %r15 + pushq %rbp + pushq %rbx +- pushq %rsi + + /* + * Push the 64-bit address of trampoline_return() onto the new stack. +@@ -478,9 +477,9 @@ SYM_CODE_START(startup_64) + lretq + trampoline_return: + /* Restore live 64-bit registers */ +- popq %rsi + popq %rbx + popq %rbp ++ popq %r15 + + /* Restore the stack, the 32-bit trampoline uses its own stack */ + leaq rva(boot_stack_end)(%rbx), %rsp +@@ -490,14 +489,9 @@ trampoline_return: + * + * RDI is address of the page table to use instead of page table + * in trampoline memory (if required). +- * +- * RSI holds real mode data and needs to be preserved across +- * this function call. + */ +- pushq %rsi + leaq rva(top_pgtable)(%rbx), %rdi + call cleanup_trampoline +- popq %rsi + + /* Zero EFLAGS */ + pushq $0 +@@ -507,7 +501,6 @@ trampoline_return: + * Copy the compressed kernel to the end of our buffer + * where decompression in place becomes safe. + */ +- pushq %rsi + leaq (_bss-8)(%rip), %rsi + leaq rva(_bss-8)(%rbx), %rdi + movl $(_bss - startup_32), %ecx +@@ -515,7 +508,6 @@ trampoline_return: + std + rep movsq + cld +- popq %rsi + + /* + * The GDT may get overwritten either during the copy we just did or +@@ -562,30 +554,28 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + shrq $3, %rcx + rep stosq + +- pushq %rsi + call load_stage2_idt + + /* Pass boot_params to initialize_identity_maps() */ +- movq (%rsp), %rdi ++ movq %r15, %rdi + call initialize_identity_maps +- popq %rsi + + /* + * Do the extraction, and jump to the new kernel.. + */ +- pushq %rsi /* Save the real mode argument */ +- movq %rsi, %rdi /* real mode address */ ++ /* pass struct boot_params pointer */ ++ movq %r15, %rdi + leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ + leaq input_data(%rip), %rdx /* input_data */ + movl input_len(%rip), %ecx /* input_len */ + movq %rbp, %r8 /* output target address */ + movl output_len(%rip), %r9d /* decompressed length, end of relocs */ + call extract_kernel /* returns kernel entry point in %rax */ +- popq %rsi + + /* + * Jump to the decompressed kernel. + */ ++ movq %r15, %rsi + jmp *%rax + SYM_FUNC_END(.Lrelocated) + diff --git a/queue-6.1/x86-decompressor-use-standard-calling-convention-for-trampoline.patch b/queue-6.1/x86-decompressor-use-standard-calling-convention-for-trampoline.patch new file mode 100644 index 00000000000..05a13a53870 --- /dev/null +++ b/queue-6.1/x86-decompressor-use-standard-calling-convention-for-trampoline.patch @@ -0,0 +1,109 @@ +From 918a7a04e71745e99a0efc6753e587439b794b29 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:07 +0200 +Subject: x86/decompressor: Use standard calling convention for trampoline + +From: Ard Biesheuvel + +commit 918a7a04e71745e99a0efc6753e587439b794b29 upstream. + +Update the trampoline code so its arguments are passed via RDI and RSI, +which matches the ordinary SysV calling convention for x86_64. This will +allow this code to be called directly from C. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Kirill A. Shutemov +Link: https://lore.kernel.org/r/20230807162720.545787-11-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/head_64.S | 27 +++++++++++++-------------- + arch/x86/boot/compressed/pgtable.h | 2 +- + 2 files changed, 14 insertions(+), 15 deletions(-) + +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -447,9 +447,9 @@ SYM_CODE_START(startup_64) + movq %r15, %rdi + call paging_prepare + +- /* Save the trampoline address in RCX */ +- movq %rax, %rcx +- ++ /* Pass the trampoline address and boolean flag as args #1 and #2 */ ++ movq %rax, %rdi ++ movq %rdx, %rsi + leaq TRAMPOLINE_32BIT_CODE_OFFSET(%rax), %rax + call *%rax + +@@ -549,11 +549,14 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated + SYM_FUNC_END(.Lrelocated) + + /* +- * This is the 32-bit trampoline that will be copied over to low memory. ++ * This is the 32-bit trampoline that will be copied over to low memory. It ++ * will be called using the ordinary 64-bit calling convention from code ++ * running in 64-bit mode. + * + * Return address is at the top of the stack (might be above 4G). +- * ECX contains the base address of the trampoline memory. +- * Non zero RDX means trampoline needs to enable 5-level paging. ++ * The first argument (EDI) contains the 32-bit addressable base of the ++ * trampoline memory. A non-zero second argument (ESI) means that the ++ * trampoline needs to enable 5-level paging. + */ + SYM_CODE_START(trampoline_32bit_src) + /* +@@ -600,7 +603,7 @@ SYM_CODE_START(trampoline_32bit_src) + movl %eax, %cr0 + + /* Check what paging mode we want to be in after the trampoline */ +- testl %edx, %edx ++ testl %esi, %esi + jz 1f + + /* We want 5-level paging: don't touch CR3 if it already points to 5-level page tables */ +@@ -615,21 +618,17 @@ SYM_CODE_START(trampoline_32bit_src) + jz 3f + 2: + /* Point CR3 to the trampoline's new top level page table */ +- leal TRAMPOLINE_32BIT_PGTABLE_OFFSET(%ecx), %eax ++ leal TRAMPOLINE_32BIT_PGTABLE_OFFSET(%edi), %eax + movl %eax, %cr3 + 3: + /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */ +- pushl %ecx +- pushl %edx + movl $MSR_EFER, %ecx + rdmsr + btsl $_EFER_LME, %eax + /* Avoid writing EFER if no change was made (for TDX guest) */ + jc 1f + wrmsr +-1: popl %edx +- popl %ecx +- ++1: + #ifdef CONFIG_X86_MCE + /* + * Preserve CR4.MCE if the kernel will enable #MC support. +@@ -646,7 +645,7 @@ SYM_CODE_START(trampoline_32bit_src) + + /* Enable PAE and LA57 (if required) paging modes */ + orl $X86_CR4_PAE, %eax +- testl %edx, %edx ++ testl %esi, %esi + jz 1f + orl $X86_CR4_LA57, %eax + 1: +--- a/arch/x86/boot/compressed/pgtable.h ++++ b/arch/x86/boot/compressed/pgtable.h +@@ -14,7 +14,7 @@ + + extern unsigned long *trampoline_32bit; + +-extern void trampoline_32bit_src(void *return_ptr); ++extern void trampoline_32bit_src(void *trampoline, bool enable_5lvl); + + #endif /* __ASSEMBLER__ */ + #endif /* BOOT_COMPRESSED_PAGETABLE_H */ diff --git a/queue-6.1/x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch b/queue-6.1/x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch new file mode 100644 index 00000000000..8810960e319 --- /dev/null +++ b/queue-6.1/x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch @@ -0,0 +1,136 @@ +From cc3fdda2876e58a7e83e558ab51853cf106afb6a Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 22 Nov 2022 17:10:17 +0100 +Subject: x86/efi: Make the deprecated EFI handover protocol optional + +From: Ard Biesheuvel + +commit cc3fdda2876e58a7e83e558ab51853cf106afb6a upstream. + +The EFI handover protocol permits a bootloader to invoke the kernel as a +EFI PE/COFF application, while passing a bootparams struct as a third +argument to the entrypoint function call. + +This has no basis in the UEFI specification, and there are better ways +to pass additional data to a UEFI application (UEFI configuration +tables, UEFI variables, UEFI protocols) than going around the +StartImage() boot service and jumping to a fixed offset in the loaded +image, just to call a different function that takes a third parameter. + +The reason for handling struct bootparams in the bootloader was that the +EFI stub could only load initrd images from the EFI system partition, +and so passing it via struct bootparams was needed for loaders like +GRUB, which pass the initrd in memory, and may load it from anywhere, +including from the network. Another motivation was EFI mixed mode, which +could not use the initrd loader in the EFI stub at all due to 32/64 bit +incompatibilities (which will be fixed shortly [0]), and could not +invoke the ordinary PE/COFF entry point either, for the same reasons. + +Given that loaders such as GRUB already carried the bootparams handling +in order to implement non-EFI boot, retaining that code and just passing +bootparams to the EFI stub was a reasonable choice (although defining an +alternate entrypoint could have been avoided.) However, the GRUB side +changes never made it upstream, and are only shipped by some of the +distros in their downstream versions. + +In the meantime, EFI support has been added to other Linux architecture +ports, as well as to U-boot and systemd, including arch-agnostic methods +for passing initrd images in memory [1], and for doing mixed mode boot +[2], none of them requiring anything like the EFI handover protocol. So +given that only out-of-tree distro GRUB relies on this, let's permit it +to be omitted from the build, in preparation for retiring it completely +at a later date. (Note that systemd-boot does have an implementation as +well, but only uses it as a fallback for booting images that do not +implement the LoadFile2 based initrd loading method, i.e., v5.8 or older) + +[0] https://lore.kernel.org/all/20220927085842.2860715-1-ardb@kernel.org/ +[1] ec93fc371f01 ("efi/libstub: Add support for loading the initrd from a device path") +[2] 97aa276579b2 ("efi/x86: Add true mixed mode entry point into .compat section") + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20221122161017.2426828-18-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/Kconfig | 17 +++++++++++++++++ + arch/x86/boot/compressed/head_64.S | 4 +++- + arch/x86/boot/header.S | 2 +- + arch/x86/boot/tools/build.c | 2 ++ + 4 files changed, 23 insertions(+), 2 deletions(-) + +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1982,6 +1982,23 @@ config EFI_STUB + + See Documentation/admin-guide/efi-stub.rst for more information. + ++config EFI_HANDOVER_PROTOCOL ++ bool "EFI handover protocol (DEPRECATED)" ++ depends on EFI_STUB ++ default y ++ help ++ Select this in order to include support for the deprecated EFI ++ handover protocol, which defines alternative entry points into the ++ EFI stub. This is a practice that has no basis in the UEFI ++ specification, and requires a priori knowledge on the part of the ++ bootloader about Linux/x86 specific ways of passing the command line ++ and initrd, and where in memory those assets may be loaded. ++ ++ If in doubt, say Y. Even though the corresponding support is not ++ present in upstream GRUB or other bootloaders, most distros build ++ GRUB with numerous downstream patches applied, and may rely on the ++ handover protocol as as result. ++ + config EFI_MIXED + bool "EFI mixed-mode support" + depends on EFI_STUB && X86_64 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -286,7 +286,7 @@ SYM_FUNC_START(startup_32) + lret + SYM_FUNC_END(startup_32) + +-#ifdef CONFIG_EFI_MIXED ++#if IS_ENABLED(CONFIG_EFI_MIXED) && IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL) + .org 0x190 + SYM_FUNC_START(efi32_stub_entry) + add $0x4, %esp /* Discard return address */ +@@ -535,7 +535,9 @@ trampoline_return: + SYM_CODE_END(startup_64) + + #ifdef CONFIG_EFI_STUB ++#ifdef CONFIG_EFI_HANDOVER_PROTOCOL + .org 0x390 ++#endif + SYM_FUNC_START(efi64_stub_entry) + and $~0xf, %rsp /* realign the stack */ + movq %rdx, %rbx /* save boot_params pointer */ +--- a/arch/x86/boot/header.S ++++ b/arch/x86/boot/header.S +@@ -406,7 +406,7 @@ xloadflags: + # define XLF1 0 + #endif + +-#ifdef CONFIG_EFI_STUB ++#ifdef CONFIG_EFI_HANDOVER_PROTOCOL + # ifdef CONFIG_EFI_MIXED + # define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64) + # else +--- a/arch/x86/boot/tools/build.c ++++ b/arch/x86/boot/tools/build.c +@@ -290,6 +290,7 @@ static void efi_stub_entry_update(void) + { + unsigned long addr = efi32_stub_entry; + ++#ifdef CONFIG_EFI_HANDOVER_PROTOCOL + #ifdef CONFIG_X86_64 + /* Yes, this is really how we defined it :( */ + addr = efi64_stub_entry - 0x200; +@@ -299,6 +300,7 @@ static void efi_stub_entry_update(void) + if (efi32_stub_entry != addr) + die("32-bit and 64-bit EFI entry points do not match\n"); + #endif ++#endif + put_unaligned_le32(addr, &buf[0x264]); + } + diff --git a/queue-6.1/x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch b/queue-6.1/x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch new file mode 100644 index 00000000000..9f44f687b53 --- /dev/null +++ b/queue-6.1/x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch @@ -0,0 +1,69 @@ +From d2d7a54f69b67cd0a30e0ebb5307cb2de625baac Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 7 Aug 2023 18:27:00 +0200 +Subject: x86/efistub: Branch straight to kernel entry point from C code + +From: Ard Biesheuvel + +commit d2d7a54f69b67cd0a30e0ebb5307cb2de625baac upstream. + +Instead of returning to the calling code in assembler that does nothing +more than perform an indirect call with the boot_params pointer in +register ESI/RSI, perform the jump directly from the EFI stub C code. +This will allow the asm entrypoint code to be dropped entirely in +subsequent patches. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230807162720.545787-4-ardb@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/efi/libstub/x86-stub.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +--- a/drivers/firmware/efi/libstub/x86-stub.c ++++ b/drivers/firmware/efi/libstub/x86-stub.c +@@ -279,7 +279,7 @@ adjust_memory_range_protection(unsigned + #define TRAMPOLINE_PLACEMENT_BASE ((128 - 8)*1024) + #define TRAMPOLINE_PLACEMENT_SIZE (640*1024 - (128 - 8)*1024) + +-void startup_32(struct boot_params *boot_params); ++extern const u8 startup_32[], startup_64[]; + + static void + setup_memory_protection(unsigned long image_base, unsigned long image_size) +@@ -760,10 +760,19 @@ static efi_status_t exit_boot(struct boo + return EFI_SUCCESS; + } + ++static void __noreturn enter_kernel(unsigned long kernel_addr, ++ struct boot_params *boot_params) ++{ ++ /* enter decompressed kernel with boot_params pointer in RSI/ESI */ ++ asm("jmp *%0"::"r"(kernel_addr), "S"(boot_params)); ++ ++ unreachable(); ++} ++ + /* +- * On success, we return the address of startup_32, which has potentially been +- * relocated by efi_relocate_kernel. +- * On failure, we exit to the firmware via efi_exit instead of returning. ++ * On success, this routine will jump to the relocated image directly and never ++ * return. On failure, it will exit to the firmware via efi_exit() instead of ++ * returning. + */ + asmlinkage unsigned long efi_main(efi_handle_t handle, + efi_system_table_t *sys_table_arg, +@@ -905,7 +914,10 @@ asmlinkage unsigned long efi_main(efi_ha + goto fail; + } + +- return bzimage_addr; ++ if (IS_ENABLED(CONFIG_X86_64)) ++ bzimage_addr += startup_64 - startup_32; ++ ++ enter_kernel(bzimage_addr, boot_params); + fail: + efi_err("efi_main() failed!\n"); + -- 2.47.3