powerpc fixes for 5.11 #5
Fix a bad interaction between the scv handling and the fallback L1D flush, which could lead to user register corruption. Only affects people using scv (~no one) on machines with old firmware that are missing the L1D flush. Two small selftest fixes. Thanks to Eirik Fuller, Libor Pechacek, Nicholas Piggin, Sandipan Das, Tulio Magno Quites Machado Filho. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmAMrdETHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgF+xD/97Hl6qlS5GllC1mVHUW/eyekfqt7io XHSPeeayZddj3FhfX+eyfICUtmeQP9MXhp9Jyz/JyD+RCpIIiEbJ40CnCpsLeOFj RmRxiVX1lB8tEp5gMZnVdv8z3XDTkzt9YDPlHA7Ta/rqkD0ursF8yVnDG61ZjWnF +2uAozJp9p+nOVrd6wqd5wzdJyWyVXHCkCfyN/HD1rPAR0b6oFm8R3Pca7UR6Qk3 Nt5deAaTisl3jDT+1C+PNq/YErHeERwNyLcRP7dT7VvO9Cch2ijxqc3e0loLT1Nz bTL6bI1JhqePXZQRWRTxpk0A6yss0hWlMudSoRbQzhDbcEY+4QxK90oXevalHXcC C3e3qgO6JoN1hN4tw9kFQr1r+x+xsKpR+jO9MfE7ndFGfAPc2An5rSRbFEB6cUvr qqVh3iNHNGILeE74EyAthjGF2nZEmxI1DAFZFjoDoeWMi+VyE2MAzcIMJg22mhYx 5n64CCrqqTjhXtJgXm31L8WUKHz2JZnwwH3nTnrPXswzTMhkYp2fTQSySWCE4Zyo xygoMfnxIuNkL3hZN0cxNzjr0uGrWIdQq/JFui1Wek68qNK0NEH5r5FmDTTFgk0D A3sJAEmKehs3Ka64LA5ejYza0zU1wnrOcyJKDpxQAWKldcKiQQw7Gup9dQe218Vc ZemyuT9YDlOilQ== =4nYe -----END PGP SIGNATURE----- Merge tag 'powerpc-5.11-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc fixes from Michael Ellerman: - Fix a bad interaction between the scv handling and the fallback L1D flush, which could lead to user register corruption. Only affects people using scv (~no one) on machines with old firmware that are missing the L1D flush. - Two small selftest fixes. Thanks to Eirik Fuller, Libor Pechacek, Nicholas Piggin, Sandipan Das, and Tulio Magno Quites Machado Filho. * tag 'powerpc-5.11-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64s: fix scv entry fallback flush vs interrupt selftests/powerpc: Only test lwm/stmw on big endian selftests/powerpc: Fix exit status of pkey tests
This commit is contained in:
commit
14c50a6618
@ -63,6 +63,12 @@
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
#define SCV_ENTRY_FLUSH_SLOT \
|
||||
SCV_ENTRY_FLUSH_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
/*
|
||||
* r10 must be free to use, r13 must be paca
|
||||
*/
|
||||
@ -70,6 +76,13 @@
|
||||
STF_ENTRY_BARRIER_SLOT; \
|
||||
ENTRY_FLUSH_SLOT
|
||||
|
||||
/*
|
||||
* r10, ctr must be free to use, r13 must be paca
|
||||
*/
|
||||
#define SCV_INTERRUPT_TO_KERNEL \
|
||||
STF_ENTRY_BARRIER_SLOT; \
|
||||
SCV_ENTRY_FLUSH_SLOT
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
*
|
||||
|
@ -240,6 +240,14 @@ label##3: \
|
||||
FTR_ENTRY_OFFSET 957b-958b; \
|
||||
.popsection;
|
||||
|
||||
#define SCV_ENTRY_FLUSH_FIXUP_SECTION \
|
||||
957: \
|
||||
.pushsection __scv_entry_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
958: \
|
||||
FTR_ENTRY_OFFSET 957b-958b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
@ -273,10 +281,12 @@ label##3: \
|
||||
|
||||
extern long stf_barrier_fallback;
|
||||
extern long entry_flush_fallback;
|
||||
extern long scv_entry_flush_fallback;
|
||||
extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
|
||||
extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
|
||||
extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
|
||||
extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
|
||||
extern long __start___scv_entry_flush_fixup, __stop___scv_entry_flush_fixup;
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
|
||||
extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
|
||||
|
@ -75,7 +75,7 @@ BEGIN_FTR_SECTION
|
||||
bne .Ltabort_syscall
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
||||
#endif
|
||||
INTERRUPT_TO_KERNEL
|
||||
SCV_INTERRUPT_TO_KERNEL
|
||||
mr r10,r1
|
||||
ld r1,PACAKSAVE(r13)
|
||||
std r10,0(r1)
|
||||
|
@ -2993,6 +2993,25 @@ TRAMP_REAL_BEGIN(entry_flush_fallback)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
blr
|
||||
|
||||
/*
|
||||
* The SCV entry flush happens with interrupts enabled, so it must disable
|
||||
* to prevent EXRFI being clobbered by NMIs (e.g., soft_nmi_common). r10
|
||||
* (containing LR) does not need to be preserved here because scv entry
|
||||
* puts 0 in the pt_regs, CTR can be clobbered for the same reason.
|
||||
*/
|
||||
TRAMP_REAL_BEGIN(scv_entry_flush_fallback)
|
||||
li r10,0
|
||||
mtmsrd r10,1
|
||||
lbz r10,PACAIRQHAPPENED(r13)
|
||||
ori r10,r10,PACA_IRQ_HARD_DIS
|
||||
stb r10,PACAIRQHAPPENED(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
L1D_DISPLACEMENT_FLUSH
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
li r10,MSR_RI
|
||||
mtmsrd r10,1
|
||||
blr
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
|
@ -145,6 +145,13 @@ SECTIONS
|
||||
__stop___entry_flush_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__scv_entry_flush_fixup : AT(ADDR(__scv_entry_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___scv_entry_flush_fixup = .;
|
||||
*(__scv_entry_flush_fixup)
|
||||
__stop___scv_entry_flush_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) {
|
||||
__start___stf_exit_barrier_fixup = .;
|
||||
|
@ -290,9 +290,6 @@ void do_entry_flush_fixups(enum l1d_flush_type types)
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___entry_flush_fixup);
|
||||
end = PTRRELOC(&__stop___entry_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
@ -312,6 +309,8 @@ void do_entry_flush_fixups(enum l1d_flush_type types)
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
start = PTRRELOC(&__start___entry_flush_fixup);
|
||||
end = PTRRELOC(&__stop___entry_flush_fixup);
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
@ -328,6 +327,25 @@ void do_entry_flush_fixups(enum l1d_flush_type types)
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
}
|
||||
|
||||
start = PTRRELOC(&__start___scv_entry_flush_fixup);
|
||||
end = PTRRELOC(&__stop___scv_entry_flush_fixup);
|
||||
for (; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
|
||||
|
||||
if (types == L1D_FLUSH_FALLBACK)
|
||||
patch_branch((struct ppc_inst *)(dest + 1), (unsigned long)&scv_entry_flush_fallback,
|
||||
BRANCH_SET_LINK);
|
||||
else
|
||||
patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
|
||||
|
||||
patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i,
|
||||
(types == L1D_FLUSH_NONE) ? "no" :
|
||||
(types == L1D_FLUSH_FALLBACK) ? "fallback displacement" :
|
||||
|
@ -443,7 +443,6 @@ int test_alignment_handler_integer(void)
|
||||
LOAD_DFORM_TEST(ldu);
|
||||
LOAD_XFORM_TEST(ldx);
|
||||
LOAD_XFORM_TEST(ldux);
|
||||
LOAD_DFORM_TEST(lmw);
|
||||
STORE_DFORM_TEST(stb);
|
||||
STORE_XFORM_TEST(stbx);
|
||||
STORE_DFORM_TEST(stbu);
|
||||
@ -462,7 +461,11 @@ int test_alignment_handler_integer(void)
|
||||
STORE_XFORM_TEST(stdx);
|
||||
STORE_DFORM_TEST(stdu);
|
||||
STORE_XFORM_TEST(stdux);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
LOAD_DFORM_TEST(lmw);
|
||||
STORE_DFORM_TEST(stmw);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -290,5 +290,5 @@ static int test(void)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_harness(test, "pkey_exec_prot");
|
||||
return test_harness(test, "pkey_exec_prot");
|
||||
}
|
||||
|
@ -329,5 +329,5 @@ static int test(void)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_harness(test, "pkey_siginfo");
|
||||
return test_harness(test, "pkey_siginfo");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user