FreeBSD Bugzilla – Attachment 230798 Details for
Bug 209821
UEFI - installation media hangs when booting on ASUS P6P67 DELUXE
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
[PATCH] [releng/12.3] efi: loader: Inline copy_finish function in amd64 trampoline
0001-efi-loader-Inline-copy_finish-function-in-amd64-tram.patch (text/plain), 5.54 KB, created by
David Sebek
on 2022-01-07 21:46:48 UTC
(
hide
)
Description:
[PATCH] [releng/12.3] efi: loader: Inline copy_finish function in amd64 trampoline
Filename:
MIME Type:
Creator:
David Sebek
Created:
2022-01-07 21:46:48 UTC
Size:
5.54 KB
patch
obsolete
>From 1372e1bddfb492f5aa8860babebe6e31edfd9b9a Mon Sep 17 00:00:00 2001 >From: David Sebek <dasebek@gmail.com> >Date: Fri, 7 Jan 2022 15:18:49 -0500 >Subject: [PATCH] efi: loader: Inline copy_finish function in amd64 trampoline > >Instead of calling the efi_copy_finish function from amd64_tramp, >include the copy instructions in the trampoline code itself. >This avoids boot hangs and restarts in the cases when >the efi_copy_finish code happens to be located at a memory >location that is overwritten during the copy process. >--- > stand/efi/loader/arch/amd64/amd64_tramp.S | 53 +++++++++++++++++++++ > stand/efi/loader/arch/amd64/elf64_freebsd.c | 18 ++++--- > stand/efi/loader/copy.c | 8 ++++ > stand/efi/loader/loader_efi.h | 1 + > 4 files changed, 73 insertions(+), 7 deletions(-) > >diff --git a/stand/efi/loader/arch/amd64/amd64_tramp.S b/stand/efi/loader/arch/amd64/amd64_tramp.S >index c102d924358..0d608bc3c07 100644 >--- a/stand/efi/loader/arch/amd64/amd64_tramp.S >+++ b/stand/efi/loader/arch/amd64/amd64_tramp.S >@@ -58,7 +58,60 @@ amd64_tramp: > ALIGN_TEXT > amd64_tramp_end: > >+ .globl amd64_tramp_inline >+ >+/* >+ * void amd64_tramp_inline(uint64_t stack, uint64_t kernend, >+ * uint64_t modulep, uint64_t pagetable, uint64_t entry, >+ * uint64_t copy_dst, uint64_t copy_src, uint64_t copy_src_end) >+ */ >+amd64_tramp_inline: >+ cli /* Make sure we don't get interrupted. */ >+ >+ movq %rsi,%r12 /* Stash the kernel values for later. */ >+ movq %rdx,%r13 >+ movq %rcx,%r14 >+ movq %r8,%r15 >+ >+ /* Copy the kernel from the staging area to the expected location >+ * in memory. The following code is equivalent to the efi_copy_finish >+ * function that amd64_tramp used to call. Inlining this code avoids >+ * a scenario when the system froze because efi_copy_finish >+ * overwrote its own code that just happened to be located somewhere >+ * in the destination range. >+ * >+ * while (copy_src < copy_src_end) *copy_dst++ = *copy_src++; >+ */ >+ movq 8(%rsp), %rax /* rax = copy_src */ >+ movq 16(%rsp), %rcx /* rcx = copy_src_end */ >+ cmpq %rcx, %rax >+ jnb copy_done >+ subq %rax, %r9 /* r9 = copy_dst - copy_src */ >+loop: >+ movq (%rax), %rdx >+ movq %rdx, (%rax,%r9) >+ addq $8, %rax >+ cmpq %rax, %rcx >+ ja loop >+copy_done: >+ >+ movq %rdi,%rsp /* Switch to our temporary stack. */ >+ >+ pushq %r12 /* Push kernend. */ >+ salq $32,%r13 /* Shift modulep and push it. */ >+ pushq %r13 >+ pushq %r15 /* Push the entry address. */ >+ movq %r14,%cr3 /* Switch page tables. */ >+ ret /* "Return" to kernel entry. */ >+ >+ ALIGN_TEXT >+amd64_tramp_inline_end: >+ > .data > .globl amd64_tramp_size > amd64_tramp_size: > .long amd64_tramp_end-amd64_tramp >+ >+ .globl amd64_tramp_inline_size >+amd64_tramp_inline_size: >+ .long amd64_tramp_inline_end-amd64_tramp_inline >\ No newline at end of file >diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c >index 896041e066c..6fcd561cb2f 100644 >--- a/stand/efi/loader/arch/amd64/elf64_freebsd.c >+++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c >@@ -78,11 +78,12 @@ static pml4_entry_t *PT4; > static pdp_entry_t *PT3; > static pd_entry_t *PT2; > >-static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, >- uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry); >+static void (*trampoline)(uint64_t stack, uint64_t kernend, >+ uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry, >+ uint64_t copy_dst, uint64_t copy_src, uint64_t copy_src_end); > >-extern uintptr_t amd64_tramp; >-extern uint32_t amd64_tramp_size; >+extern uintptr_t amd64_tramp_inline; >+extern uint32_t amd64_tramp_inline_size; > > /* > * There is an ELF kernel and one or more ELF modules loaded. >@@ -95,6 +96,7 @@ elf64_exec(struct preloaded_file *fp) > struct file_metadata *md; > Elf_Ehdr *ehdr; > vm_offset_t modulep, kernend, trampcode, trampstack; >+ uint64_t copy_dst, copy_src, copy_src_end; > int err, i; > ACPI_TABLE_RSDP *rsdp; > char buf[24]; >@@ -153,7 +155,7 @@ elf64_exec(struct preloaded_file *fp) > (EFI_PHYSICAL_ADDRESS *)&trampcode); > bzero((void *)trampcode, EFI_PAGE_SIZE); > trampstack = trampcode + EFI_PAGE_SIZE - 8; >- bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size); >+ bcopy((void *)&amd64_tramp_inline, (void *)trampcode, amd64_tramp_inline_size); > trampoline = (void *)trampcode; > > PT4 = (pml4_entry_t *)0x0000000040000000; >@@ -194,8 +196,10 @@ elf64_exec(struct preloaded_file *fp) > > dev_cleanup(); > >- trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4, >- ehdr->e_entry); >+ efi_copy_get_locations(©_dst, ©_src, ©_src_end); >+ >+ trampoline(trampstack, kernend, modulep, PT4, >+ ehdr->e_entry, copy_dst, copy_src, copy_src_end); > > panic("exec returned"); > } >diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c >index 5a174dbf51e..307ad3e0ac7 100644 >--- a/stand/efi/loader/copy.c >+++ b/stand/efi/loader/copy.c >@@ -361,3 +361,11 @@ efi_copy_finish(void) > while (src < last) > *dst++ = *src++; > } >+ >+void >+efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end) >+{ >+ *src = (uint64_t)staging; >+ *dst = (uint64_t)(staging - stage_offset); >+ *src_end = (uint64_t)staging_end; >+} >diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h >index 4d077514e42..5f0c7c6825a 100644 >--- a/stand/efi/loader/loader_efi.h >+++ b/stand/efi/loader/loader_efi.h >@@ -44,5 +44,6 @@ ssize_t efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); > void * efi_translate(vm_offset_t ptr); > > void efi_copy_finish(void); >+void efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end); > > #endif /* _LOADER_EFI_COPY_H_ */ >-- >2.33.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 209821
:
225333
|
225480
|
230798
|
230812
|
230823