]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Mar 2024 10:35:24 +0000 (11:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Mar 2024 10:35:24 +0000 (11:35 +0100)
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

33 files changed:
queue-6.1/decompress-use-8-byte-alignment.patch [new file with mode: 0644]
queue-6.1/efi-libstub-use-efi_loader_code-region-when-moving-the-kernel-in-memory.patch [new file with mode: 0644]
queue-6.1/efi-verify-that-variable-services-are-supported.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/x86-boot-compressed-adhere-to-calling-convention-in-get_sev_encryption_bit.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-avoid-touching-ecx-in-startup32_set_idt_entry.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-efi-merge-multiple-definitions-of-image_offset-into-one.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-32-bit-entrypoint-code-into-.text-section.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-bootargs-parsing-out-of-32-bit-startup-code.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-efi32_entry-out-of-head_64.s.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-efi32_pe_entry-into-.text-section.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-efi32_pe_entry-out-of-head_64.s.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-into-.text.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-startup32_check_sev_cbit-out-of-head_64.s.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-startup32_load_idt-into-.text-section.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-move-startup32_load_idt-out-of-head_64.s.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-only-build-mem_encrypt.s-if-amd_mem_encrypt-y.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-pull-global-variable-reference-into-startup32_load_idt.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-rename-efi_thunk_64.s-to-efi-mixed.s.patch [new file with mode: 0644]
queue-6.1/x86-boot-compressed-simplify-idt-gdt-preserve-restore-in-the-efi-thunk.patch [new file with mode: 0644]
queue-6.1/x86-boot-robustify-calling-startup_-32-64-from-the-decompressor-code.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-assign-paging-related-global-variables-earlier.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-avoid-the-need-for-a-stack-in-the-32-bit-trampoline.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-call-trampoline-as-a-normal-function.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-call-trampoline-directly-from-c-code.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-merge-trampoline-cleanup-with-switching-code.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-move-global-symbol-references-to-c-code.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-only-call-the-trampoline-when-changing-paging-levels.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-pass-pgtable-address-to-trampoline-directly.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-store-boot_params-pointer-in-callee-save-register.patch [new file with mode: 0644]
queue-6.1/x86-decompressor-use-standard-calling-convention-for-trampoline.patch [new file with mode: 0644]
queue-6.1/x86-efi-make-the-deprecated-efi-handover-protocol-optional.patch [new file with mode: 0644]
queue-6.1/x86-efistub-branch-straight-to-kernel-entry-point-from-c-code.patch [new file with mode: 0644]

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 (file)
index 0000000..b108d74
--- /dev/null
@@ -0,0 +1,31 @@
+From 8217ad0a435ff06d651d7298ea8ae8d72388179e Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:15 +0200
+Subject: decompress: Use 8 byte alignment
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-19-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2000334
--- /dev/null
@@ -0,0 +1,126 @@
+From 9cf42bca30e98a1c6c9e8abf876940a551eaa3d1 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..4989245
--- /dev/null
@@ -0,0 +1,71 @@
+From bad267f9e18f8e9e628abd1811d2899b1735a4e1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Thu, 19 Jan 2023 17:42:54 +0100
+Subject: efi: verify that variable services are supported
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+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 <johan+linaro@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+ }
index 50ad2f186adf4aa0d394acabe1bd4a48fbdc8552..daa18aaf2aa9e9c8a3205ba4e9ebb42028b16917 100644 (file)
@@ -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 (file)
index 0000000..3cffd86
--- /dev/null
@@ -0,0 +1,69 @@
+From 30c9ca16a5271ba6f8ad9c86507ff1c789c94677 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-16-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5d56173
--- /dev/null
@@ -0,0 +1,55 @@
+From 6aac80a8da46d70f2ae7ff97c9f45a15c7c9b3ef Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:09 +0100
+Subject: x86/boot/compressed: Avoid touching ECX in startup32_set_idt_entry()
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-10-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9b54a3e
--- /dev/null
@@ -0,0 +1,72 @@
+From 4b52016247aeaa55ca3e3bc2e03cd91114c145c2 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-8-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9a9c7be
--- /dev/null
@@ -0,0 +1,98 @@
+From e2ab9eab324cdf240de89741e4a1aa79919f0196 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:02 +0100
+Subject: x86/boot/compressed: Move 32-bit entrypoint code into .text section
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-3-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..13c9792
--- /dev/null
@@ -0,0 +1,115 @@
+From 5c3a85f35b583259cf5ca0344cd79c8899ba1bb7 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-4-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..cfc1832
--- /dev/null
@@ -0,0 +1,163 @@
+From 73a6dec80e2acedaef3ca603d4b5799049f6e9f8 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:05 +0100
+Subject: x86/boot/compressed: Move efi32_entry out of head_64.S
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-6-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7e64316
--- /dev/null
@@ -0,0 +1,63 @@
+From 91592b5c0c2f076ff9d8cc0c14aa563448ac9fc4 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:04 +0100
+Subject: x86/boot/compressed: Move efi32_pe_entry into .text section
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-5-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..8a9c191
--- /dev/null
@@ -0,0 +1,216 @@
+From 7f22ca396778fea9332d83ec2359dbe8396e9a06 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-7-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9725d6c
--- /dev/null
@@ -0,0 +1,113 @@
+From b5d854cd4b6a314edd6c15dabc4233b84a0f8e5e Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:13 +0100
+Subject: x86/boot/compressed: Move startup32_check_sev_cbit() into .text
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-14-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d2092d8
--- /dev/null
@@ -0,0 +1,179 @@
+From 9d7eaae6a071ff1f718e0aa5e610bb712f8cc632 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-15-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7ddd08d
--- /dev/null
@@ -0,0 +1,99 @@
+From c6355995ba471d7ad574174e593192ce805c7e1a Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:11 +0100
+Subject: x86/boot/compressed: Move startup32_load_idt() into .text section
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-12-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..3adffbb
--- /dev/null
@@ -0,0 +1,202 @@
+From 9ea813be3d345dfb8ac5bf6fbb29e6a63647a39d Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-13-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <asm/processor-flags.h>
+ #include <asm/msr.h>
+ #include <asm/asm-offsets.h>
++#include <asm/segment.h>
++#include <asm/trapnr.h>
+       .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 (file)
index 0000000..d10e4c3
--- /dev/null
@@ -0,0 +1,47 @@
+From 61de13df95901bc58456bc5acdbd3c18c66cf859 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-17-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7ee5439
--- /dev/null
@@ -0,0 +1,77 @@
+From d73a257f7f86871c3aac24dc20538e3983096647 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:10 +0100
+Subject: x86/boot/compressed: Pull global variable reference into startup32_load_idt()
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-11-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..44fac6b
--- /dev/null
@@ -0,0 +1,441 @@
+From cb8bda8ad4438b4bcfcf89697fc84803fb210017 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-2-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/linkage.h>
++#include <asm/msr.h>
++#include <asm/page_types.h>
++#include <asm/processor-flags.h>
++#include <asm/segment.h>
++
++      .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 <linux/linkage.h>
+-#include <asm/msr.h>
+-#include <asm/page_types.h>
+-#include <asm/processor-flags.h>
+-#include <asm/segment.h>
+-
+-      .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 (file)
index 0000000..488c729
--- /dev/null
@@ -0,0 +1,64 @@
+From 630f337f0c4fd80390e8600adcab31550aea33df Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-9-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..159163a
--- /dev/null
@@ -0,0 +1,141 @@
+From 7734a0f31e99c433df3063bbb7e8ee5a16a2cb82 Mon Sep 17 00:00:00 2001
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+Date: Mon, 9 Jan 2023 18:04:02 +0100
+Subject: x86/boot: Robustify calling startup_{32,64}() from the decompressor code
+
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+
+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 <alexandr.lobakin@intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Jiri Slaby <jirislaby@kernel.org>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/20230109170403.4117105-2-alexandr.lobakin@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..da82e2b
--- /dev/null
@@ -0,0 +1,63 @@
+From 00c6b0978ec182f1a672095930872168b9d5b1e2 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:05 +0200
+Subject: x86/decompressor: Assign paging related global variables earlier
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-9-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6a724fd
--- /dev/null
@@ -0,0 +1,185 @@
+From bd328aa01ff77a45aeffea5fc4521854291db11f Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+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 <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-12-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..ef347c1
--- /dev/null
@@ -0,0 +1,166 @@
+From e8972a76aa90c05a0078043413f806c02fcb3487 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:06 +0200
+Subject: x86/decompressor: Call trampoline as a normal function
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-10-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..66947b1
--- /dev/null
@@ -0,0 +1,189 @@
+From 64ef578b6b6866bec012544416946533444036c8 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:09 +0200
+Subject: x86/decompressor: Call trampoline directly from C code
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-13-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..28c6f17
--- /dev/null
@@ -0,0 +1,87 @@
+From 03dda95137d3247564854ad9032c0354273a159d Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:12 +0200
+Subject: x86/decompressor: Merge trampoline cleanup with switching code
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-16-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..640071c
--- /dev/null
@@ -0,0 +1,132 @@
+From 24388292e2d7fae79a0d4183cc91716b851299cf Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:16 +0200
+Subject: x86/decompressor: Move global symbol references to C code
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-20-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e493019
--- /dev/null
@@ -0,0 +1,166 @@
+From f97b67a773cd84bd8b55c0a0ec32448a87fc56bb Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:10 +0200
+Subject: x86/decompressor: Only call the trampoline when changing paging levels
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-14-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..586e1c7
--- /dev/null
@@ -0,0 +1,101 @@
+From cb83cece57e1889109dd73ea08ee338668c9d1b8 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:11 +0200
+Subject: x86/decompressor: Pass pgtable address to trampoline directly
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-15-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..b268661
--- /dev/null
@@ -0,0 +1,160 @@
+From 8b63cba746f86a754d66e302c43209cc9b9b6e39 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:04 +0200
+Subject: x86/decompressor: Store boot_params pointer in callee save register
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-8-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..05a13a5
--- /dev/null
@@ -0,0 +1,109 @@
+From 918a7a04e71745e99a0efc6753e587439b794b29 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:07 +0200
+Subject: x86/decompressor: Use standard calling convention for trampoline
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Link: https://lore.kernel.org/r/20230807162720.545787-11-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..8810960
--- /dev/null
@@ -0,0 +1,136 @@
+From cc3fdda2876e58a7e83e558ab51853cf106afb6a Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 22 Nov 2022 17:10:17 +0100
+Subject: x86/efi: Make the deprecated EFI handover protocol optional
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20221122161017.2426828-18-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9f44f68
--- /dev/null
@@ -0,0 +1,69 @@
+From d2d7a54f69b67cd0a30e0ebb5307cb2de625baac Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 7 Aug 2023 18:27:00 +0200
+Subject: x86/efistub: Branch straight to kernel entry point from C code
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+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 <ardb@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230807162720.545787-4-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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");