Skip to content

Commit

Permalink
Merge tag 'powerpc-5.11-5' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/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
  • Loading branch information
torvalds committed Jan 24, 2021
2 parents c509ce2 + 08685be commit 14c50a6
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 7 deletions.
13 changes: 13 additions & 0 deletions arch/powerpc/include/asm/exception-64s.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,26 @@
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
*/
#define INTERRUPT_TO_KERNEL \
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
*
Expand Down
10 changes: 10 additions & 0 deletions arch/powerpc/include/asm/feature-fixups.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"; \
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions arch/powerpc/kernel/exceptions-64s.S
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions arch/powerpc/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -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 = .;
Expand Down
24 changes: 21 additions & 3 deletions arch/powerpc/lib/feature-fixups.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;

Expand All @@ -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" :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion tools/testing/selftests/powerpc/mm/pkey_exec_prot.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,5 @@ static int test(void)

int main(void)
{
test_harness(test, "pkey_exec_prot");
return test_harness(test, "pkey_exec_prot");
}
2 changes: 1 addition & 1 deletion tools/testing/selftests/powerpc/mm/pkey_siginfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,5 +329,5 @@ static int test(void)

int main(void)
{
test_harness(test, "pkey_siginfo");
return test_harness(test, "pkey_siginfo");
}

0 comments on commit 14c50a6

Please sign in to comment.