Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "An unfortunately larger set of fixes, but a large portion is selftests: - Fix the missing clusterid initializaiton for x2apic cluster management which caused boot failures due to IPIs being sent to the wrong cluster - Drop TX_COMPAT when a 64bit executable is exec()'ed from a compat task - Wrap access to __supported_pte_mask in __startup_64() where clang compile fails due to a non PC relative access being generated. - Two fixes for 5 level paging fallout in the decompressor: - Handle GOT correctly for paging_prepare() and cleanup_trampoline() - Fix the page table handling in cleanup_trampoline() to avoid page table corruption. - Stop special casing protection key 0 as this is inconsistent with the manpage and also inconsistent with the allocation map handling. - Override the protection key wen moving away from PROT_EXEC to prevent inaccessible memory. - Fix and update the protection key selftests to address breakage and to cover the above issue - Add a MOV SS self test" [ Part of the x86 fixes were in the earlier core pull due to dependencies ] * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (21 commits) x86/mm: Drop TS_COMPAT on 64-bit exec() syscall x86/apic/x2apic: Initialize cluster ID properly x86/boot/compressed/64: Fix moving page table out of trampoline memory x86/boot/compressed/64: Set up GOT for paging_prepare() and cleanup_trampoline() x86/pkeys: Do not special case protection key 0 x86/pkeys/selftests: Add a test for pkey 0 x86/pkeys/selftests: Save off 'prot' for allocations x86/pkeys/selftests: Fix pointer math x86/pkeys: Override pkey when moving away from PROT_EXEC x86/pkeys/selftests: Fix pkey exhaustion test off-by-one x86/pkeys/selftests: Add PROT_EXEC test x86/pkeys/selftests: Factor out "instruction page" x86/pkeys/selftests: Allow faults on unknown keys x86/pkeys/selftests: Avoid printf-in-signal deadlocks x86/pkeys/selftests: Remove dead debugging code, fix dprint_in_signal x86/pkeys/selftests: Stop using assert() x86/pkeys/selftests: Give better unexpected fault error messages x86/selftests: Add mov_to_ss test x86/mpx/selftests: Adjust the self-test to fresh distros that export the MPX ABI x86/pkeys/selftests: Adjust the self-test to fresh distros that export the pkeys ABI ...
This commit is contained in:
@@ -305,6 +305,25 @@ 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.
|
||||
*
|
||||
* Zero RAX for adjust_got: the GOT was not adjusted before;
|
||||
* there's no adjustment to undo.
|
||||
*/
|
||||
xorq %rax, %rax
|
||||
|
||||
/*
|
||||
* Calculate the address the binary is loaded at and use it as
|
||||
* a GOT adjustment.
|
||||
*/
|
||||
call 1f
|
||||
1: popq %rdi
|
||||
subq $1b, %rdi
|
||||
|
||||
call adjust_got
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@@ -370,10 +389,14 @@ trampoline_return:
|
||||
/*
|
||||
* cleanup_trampoline() would restore trampoline memory.
|
||||
*
|
||||
* 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 top_pgtable(%rbx), %rdi
|
||||
call cleanup_trampoline
|
||||
popq %rsi
|
||||
|
||||
@@ -381,6 +404,21 @@ 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, so that we can
|
||||
* undo the previous GOT adjustment.
|
||||
*/
|
||||
call 1f
|
||||
1: popq %rax
|
||||
subq $1b, %rax
|
||||
|
||||
/* The new adjustment is the relocation address */
|
||||
movq %rbx, %rdi
|
||||
call adjust_got
|
||||
|
||||
/*
|
||||
* Copy the compressed kernel to the end of our buffer
|
||||
* where decompression in place becomes safe.
|
||||
@@ -481,19 +519,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 +537,27 @@ relocated:
|
||||
*/
|
||||
jmp *%rax
|
||||
|
||||
/*
|
||||
* Adjust the global offset table
|
||||
*
|
||||
* RAX is the previous adjustment of the table to undo (use 0 if it's the
|
||||
* first time we touch GOT).
|
||||
* RDI is the new adjustment to apply.
|
||||
*/
|
||||
adjust_got:
|
||||
/* 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.
|
||||
@@ -649,3 +695,10 @@ boot_stack_end:
|
||||
.balign 4096
|
||||
pgtable:
|
||||
.fill BOOT_PGT_SIZE, 1, 0
|
||||
|
||||
/*
|
||||
* The page table is going to be used instead of page table in the trampoline
|
||||
* memory.
|
||||
*/
|
||||
top_pgtable:
|
||||
.fill PAGE_SIZE, 1, 0
|
||||
|
@@ -22,14 +22,6 @@ struct paging_config {
|
||||
/* Buffer to preserve trampoline memory */
|
||||
static char trampoline_save[TRAMPOLINE_32BIT_SIZE];
|
||||
|
||||
/*
|
||||
* The page table is going to be used instead of page table in the trampoline
|
||||
* memory.
|
||||
*
|
||||
* It must not be in BSS as BSS is cleared after cleanup_trampoline().
|
||||
*/
|
||||
static char top_pgtable[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data);
|
||||
|
||||
/*
|
||||
* Trampoline address will be printed by extract_kernel() for debugging
|
||||
* purposes.
|
||||
@@ -134,7 +126,7 @@ out:
|
||||
return paging_config;
|
||||
}
|
||||
|
||||
void cleanup_trampoline(void)
|
||||
void cleanup_trampoline(void *pgtable)
|
||||
{
|
||||
void *trampoline_pgtable;
|
||||
|
||||
@@ -145,8 +137,8 @@ void cleanup_trampoline(void)
|
||||
* if it's there.
|
||||
*/
|
||||
if ((void *)__native_read_cr3() == trampoline_pgtable) {
|
||||
memcpy(top_pgtable, trampoline_pgtable, PAGE_SIZE);
|
||||
native_write_cr3((unsigned long)top_pgtable);
|
||||
memcpy(pgtable, trampoline_pgtable, PAGE_SIZE);
|
||||
native_write_cr3((unsigned long)pgtable);
|
||||
}
|
||||
|
||||
/* Restore trampoline memory */
|
||||
|
Fai riferimento in un nuovo problema
Block a user