From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
To: Ingo Molnar <mingo@redhat.com>,
x86@kernel.org, Thomas Gleixner <tglx@linutronix.de>,
"H. Peter Anvin" <hpa@zytor.com>
Cc: Hugh Dickins <hughd@google.com>,
linux-kernel@vger.kernel.org,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Subject: [PATCH 1/2] x86/boot/compressed/64: Set up GOT for paging_prepare() and cleanup_trampoline()
Date: Thu, 10 May 2018 20:38:05 +0300 [thread overview]
Message-ID: <20180510173806.4332-2-kirill.shutemov@linux.intel.com> (raw)
In-Reply-To: <20180510173806.4332-1-kirill.shutemov@linux.intel.com>
Eric and Hugh have reported instant reboot due to my recent changes in
decompression code.
The root cause is that I didn't realize that we need to adjust GOT to be
able to run C code that early.
The problem is only visible with old toolchain. Binutils >= 2.24 is able
to eliminate GOT references by replacing them with RIP-relative address
loads[1].
We need to adjust GOT two times:
- before calling paging_prepare() with address the binary was loaded by bootloader
- before relocating the kernel to the new place with relocation address
[1] https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=80d873266dec
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Fixes: 194a9749c73d ("x86/boot/compressed/64: Handle 5-level paging boot if kernel is above 4G")
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Reported-by: Hugh Dickins <hughd@google.com>
---
arch/x86/boot/compressed/head_64.S | 66 ++++++++++++++++++++++++------
1 file changed, 53 insertions(+), 13 deletions(-)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index fca012baba19..6cbb2d64c91e 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -305,6 +305,21 @@ ENTRY(startup_64)
/* Set up the stack */
leaq boot_stack_end(%rbx), %rsp
+ /*
+ * paging_prepare() and cleanup_trampoline() below can have GOT
+ * references. Adjust the table with address we are running at.
+ */
+
+ /* The GOP was not adjusted before */
+ xorq %rax, %rax
+
+ /* Calculate the address the binary is loaded at. */
+ call 1f
+1: popq %rdi
+ subq $1b, %rdi
+
+ call adjust_gop
+
/*
* At this point we are in long mode with 4-level paging enabled,
* but we might want to enable 5-level paging or vice versa.
@@ -381,6 +396,24 @@ trampoline_return:
pushq $0
popfq
+ /*
+ * Previously we've adjusted the GOT with address the binary was
+ * loaded at. Now we need to re-adjust for relocation address.
+ */
+
+ /*
+ * Calculate the address the binary is loaded at.
+ * This address was used to adjust the table before and we need to
+ * undo the change.
+ */
+ call 1f
+1: popq %rax
+ subq $1b, %rax
+
+ /* The new adjustment is relocation address */
+ movq %rbx, %rdi
+ call adjust_gop
+
/*
* Copy the compressed kernel to the end of our buffer
* where decompression in place becomes safe.
@@ -481,19 +514,6 @@ relocated:
shrq $3, %rcx
rep stosq
-/*
- * Adjust our own GOT
- */
- leaq _got(%rip), %rdx
- leaq _egot(%rip), %rcx
-1:
- cmpq %rcx, %rdx
- jae 2f
- addq %rbx, (%rdx)
- addq $8, %rdx
- jmp 1b
-2:
-
/*
* Do the extraction, and jump to the new kernel..
*/
@@ -512,6 +532,26 @@ relocated:
*/
jmp *%rax
+/*
+ * Adjust global offest table
+ *
+ * RAX is previous adjustment of the table to undo (0 if it's the first time we touch GOP).
+ * RDI is the new adjustment to apply.
+ */
+adjust_gop:
+ /* Walk through the GOT adding the address to the entries */
+ leaq _got(%rip), %rdx
+ leaq _egot(%rip), %rcx
+1:
+ cmpq %rcx, %rdx
+ jae 2f
+ subq %rax, (%rdx) /* Undo previous adjustment */
+ addq %rdi, (%rdx) /* Apply the new adjustment */
+ addq $8, %rdx
+ jmp 1b
+2:
+ ret
+
.code32
/*
* This is the 32-bit trampoline that will be copied over to low memory.
--
2.17.0
next prev parent reply other threads:[~2018-05-10 17:38 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-10 17:38 [PATCH for v4.17 0/2] Fix two crashes in decomression code Kirill A. Shutemov
2018-05-10 17:38 ` Kirill A. Shutemov [this message]
2018-05-13 18:55 ` [PATCH 1/2] x86/boot/compressed/64: Set up GOT for paging_prepare() and cleanup_trampoline() Thomas Gleixner
2018-05-13 20:03 ` Kirill A. Shutemov
2018-05-13 21:30 ` Thomas Gleixner
2018-05-10 17:38 ` [PATCH 2/2] x86/boot/compressed/64: Fix moving page table out of trampoline memory Kirill A. Shutemov
2018-05-13 18:56 ` Thomas Gleixner
2018-05-13 20:05 ` Kirill A. Shutemov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180510173806.4332-2-kirill.shutemov@linux.intel.com \
--to=kirill.shutemov@linux.intel.com \
--cc=hpa@zytor.com \
--cc=hughd@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.