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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox