Skip to content

Commit 48e7b76

Browse files
npigginmpe
authored andcommitted
powerpc/64s/hash: Convert SLB miss handlers to C
This patch moves SLB miss handlers completely to C, using the standard exception handler macros to set up the stack and branch to C. This can be done because the segment containing the kernel stack is always bolted, so accessing it with relocation on will not cause an SLB exception. Arbitrary kernel memory must not be accessed when handling kernel space SLB misses, so care should be taken there. However user SLB misses can access any kernel memory, which can be used to move some fields out of the paca (in later patches). User SLB misses could quite easily reconcile IRQs and set up a first class kernel environment and exit via ret_from_except, however that doesn't seem to be necessary at the moment, so we only do that if a bad fault is encountered. [ Credit to Aneesh for bug fixes, error checks, and improvements to bad address handling, etc ] Signed-off-by: Nicholas Piggin <[email protected]> [mpe: Disallow tracing for all of slb.c for now.] Signed-off-by: Michael Ellerman <[email protected]>
1 parent 4c2de74 commit 48e7b76

File tree

6 files changed

+214
-626
lines changed

6 files changed

+214
-626
lines changed

arch/powerpc/include/asm/asm-prototypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ void kernel_bad_stack(struct pt_regs *regs);
7777
void system_reset_exception(struct pt_regs *regs);
7878
void machine_check_exception(struct pt_regs *regs);
7979
void emulation_assist_interrupt(struct pt_regs *regs);
80+
long do_slb_fault(struct pt_regs *regs, unsigned long ea);
81+
void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err);
8082

8183
/* signals, syscalls and interrupts */
8284
long sys_swapcontext(struct ucontext __user *old_ctx,

arch/powerpc/include/asm/exception-64s.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,6 @@
6060
*/
6161
#define MAX_MCE_DEPTH 4
6262

63-
/*
64-
* EX_LR is only used in EXSLB and where it does not overlap with EX_DAR
65-
* EX_CCR similarly with DSISR, but being 4 byte registers there is a hole
66-
* in the save area so it's not necessary to overlap them. Could be used
67-
* for future savings though if another 4 byte register was to be saved.
68-
*/
69-
#define EX_LR EX_DAR
70-
7163
/*
7264
* EX_R3 is only used by the bad_stack handler. bad_stack reloads and
7365
* saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 42 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -596,28 +596,36 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
596596

597597

598598
EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
599-
SET_SCRATCH0(r13)
600-
EXCEPTION_PROLOG_0(PACA_EXSLB)
601-
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
602-
mr r12,r3 /* save r3 */
603-
mfspr r3,SPRN_DAR
604-
mfspr r11,SPRN_SRR1
605-
crset 4*cr6+eq
606-
BRANCH_TO_COMMON(r10, slb_miss_common)
599+
EXCEPTION_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, KVMTEST_PR, 0x380);
607600
EXC_REAL_END(data_access_slb, 0x380, 0x80)
608601

609602
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
610-
SET_SCRATCH0(r13)
611-
EXCEPTION_PROLOG_0(PACA_EXSLB)
612-
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380)
613-
mr r12,r3 /* save r3 */
614-
mfspr r3,SPRN_DAR
615-
mfspr r11,SPRN_SRR1
616-
crset 4*cr6+eq
617-
BRANCH_TO_COMMON(r10, slb_miss_common)
603+
EXCEPTION_RELON_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, NOTEST, 0x380);
618604
EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
605+
619606
TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
620607

608+
EXC_COMMON_BEGIN(data_access_slb_common)
609+
mfspr r10,SPRN_DAR
610+
std r10,PACA_EXSLB+EX_DAR(r13)
611+
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB)
612+
ld r4,PACA_EXSLB+EX_DAR(r13)
613+
std r4,_DAR(r1)
614+
addi r3,r1,STACK_FRAME_OVERHEAD
615+
bl do_slb_fault
616+
cmpdi r3,0
617+
bne- 1f
618+
b fast_exception_return
619+
1: /* Error case */
620+
std r3,RESULT(r1)
621+
bl save_nvgprs
622+
RECONCILE_IRQ_STATE(r10, r11)
623+
ld r4,_DAR(r1)
624+
ld r5,RESULT(r1)
625+
addi r3,r1,STACK_FRAME_OVERHEAD
626+
bl do_bad_slb_fault
627+
b ret_from_except
628+
621629

622630
EXC_REAL(instruction_access, 0x400, 0x80)
623631
EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400)
@@ -640,160 +648,34 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
640648

641649

642650
EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
643-
SET_SCRATCH0(r13)
644-
EXCEPTION_PROLOG_0(PACA_EXSLB)
645-
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
646-
mr r12,r3 /* save r3 */
647-
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
648-
mfspr r11,SPRN_SRR1
649-
crclr 4*cr6+eq
650-
BRANCH_TO_COMMON(r10, slb_miss_common)
651+
EXCEPTION_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, KVMTEST_PR, 0x480);
651652
EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
652653

653654
EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
654-
SET_SCRATCH0(r13)
655-
EXCEPTION_PROLOG_0(PACA_EXSLB)
656-
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480)
657-
mr r12,r3 /* save r3 */
658-
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
659-
mfspr r11,SPRN_SRR1
660-
crclr 4*cr6+eq
661-
BRANCH_TO_COMMON(r10, slb_miss_common)
655+
EXCEPTION_RELON_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, NOTEST, 0x480);
662656
EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
663-
TRAMP_KVM(PACA_EXSLB, 0x480)
664-
665-
666-
/*
667-
* This handler is used by the 0x380 and 0x480 SLB miss interrupts, as well as
668-
* the virtual mode 0x4380 and 0x4480 interrupts if AIL is enabled.
669-
*/
670-
EXC_COMMON_BEGIN(slb_miss_common)
671-
/*
672-
* r13 points to the PACA, r9 contains the saved CR,
673-
* r12 contains the saved r3,
674-
* r11 contain the saved SRR1, SRR0 is still ready for return
675-
* r3 has the faulting address
676-
* r9 - r13 are saved in paca->exslb.
677-
* cr6.eq is set for a D-SLB miss, clear for a I-SLB miss
678-
* We assume we aren't going to take any exceptions during this
679-
* procedure.
680-
*/
681-
mflr r10
682-
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
683-
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
684-
685-
andi. r9,r11,MSR_PR // Check for exception from userspace
686-
cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later
687-
688-
/*
689-
* Test MSR_RI before calling slb_allocate_realmode, because the
690-
* MSR in r11 gets clobbered. However we still want to allocate
691-
* SLB in case MSR_RI=0, to minimise the risk of getting stuck in
692-
* recursive SLB faults. So use cr5 for this, which is preserved.
693-
*/
694-
andi. r11,r11,MSR_RI /* check for unrecoverable exception */
695-
cmpdi cr5,r11,MSR_RI
696-
697-
crset 4*cr0+eq
698-
#ifdef CONFIG_PPC_BOOK3S_64
699-
BEGIN_MMU_FTR_SECTION
700-
bl slb_allocate
701-
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
702-
#endif
703-
704-
ld r10,PACA_EXSLB+EX_LR(r13)
705-
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
706-
mtlr r10
707-
708-
/*
709-
* Large address, check whether we have to allocate new contexts.
710-
*/
711-
beq- 8f
712657

713-
bne- cr5,2f /* if unrecoverable exception, oops */
714-
715-
/* All done -- return from exception. */
716-
717-
bne cr4,1f /* returning to kernel */
718-
719-
mtcrf 0x80,r9
720-
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
721-
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
722-
mtcrf 0x02,r9 /* I/D indication is in cr6 */
723-
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
724-
725-
RESTORE_CTR(r9, PACA_EXSLB)
726-
RESTORE_PPR_PACA(PACA_EXSLB, r9)
727-
mr r3,r12
728-
ld r9,PACA_EXSLB+EX_R9(r13)
729-
ld r10,PACA_EXSLB+EX_R10(r13)
730-
ld r11,PACA_EXSLB+EX_R11(r13)
731-
ld r12,PACA_EXSLB+EX_R12(r13)
732-
ld r13,PACA_EXSLB+EX_R13(r13)
733-
RFI_TO_USER
734-
b . /* prevent speculative execution */
735-
1:
736-
mtcrf 0x80,r9
737-
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
738-
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
739-
mtcrf 0x02,r9 /* I/D indication is in cr6 */
740-
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
741-
742-
RESTORE_CTR(r9, PACA_EXSLB)
743-
RESTORE_PPR_PACA(PACA_EXSLB, r9)
744-
mr r3,r12
745-
ld r9,PACA_EXSLB+EX_R9(r13)
746-
ld r10,PACA_EXSLB+EX_R10(r13)
747-
ld r11,PACA_EXSLB+EX_R11(r13)
748-
ld r12,PACA_EXSLB+EX_R12(r13)
749-
ld r13,PACA_EXSLB+EX_R13(r13)
750-
RFI_TO_KERNEL
751-
b . /* prevent speculative execution */
752-
753-
754-
2: std r3,PACA_EXSLB+EX_DAR(r13)
755-
mr r3,r12
756-
mfspr r11,SPRN_SRR0
757-
mfspr r12,SPRN_SRR1
758-
LOAD_HANDLER(r10,unrecov_slb)
759-
mtspr SPRN_SRR0,r10
760-
ld r10,PACAKMSR(r13)
761-
mtspr SPRN_SRR1,r10
762-
RFI_TO_KERNEL
763-
b .
764-
765-
8: std r3,PACA_EXSLB+EX_DAR(r13)
766-
mr r3,r12
767-
mfspr r11,SPRN_SRR0
768-
mfspr r12,SPRN_SRR1
769-
LOAD_HANDLER(r10, large_addr_slb)
770-
mtspr SPRN_SRR0,r10
771-
ld r10,PACAKMSR(r13)
772-
mtspr SPRN_SRR1,r10
773-
RFI_TO_KERNEL
774-
b .
658+
TRAMP_KVM(PACA_EXSLB, 0x480)
775659

776-
EXC_COMMON_BEGIN(unrecov_slb)
777-
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
778-
RECONCILE_IRQ_STATE(r10, r11)
660+
EXC_COMMON_BEGIN(instruction_access_slb_common)
661+
EXCEPTION_PROLOG_COMMON(0x480, PACA_EXSLB)
662+
ld r4,_NIP(r1)
663+
addi r3,r1,STACK_FRAME_OVERHEAD
664+
bl do_slb_fault
665+
cmpdi r3,0
666+
bne- 1f
667+
b fast_exception_return
668+
1: /* Error case */
669+
std r3,RESULT(r1)
779670
bl save_nvgprs
780-
1: addi r3,r1,STACK_FRAME_OVERHEAD
781-
bl unrecoverable_exception
782-
b 1b
783-
784-
EXC_COMMON_BEGIN(large_addr_slb)
785-
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB)
786671
RECONCILE_IRQ_STATE(r10, r11)
787-
ld r3, PACA_EXSLB+EX_DAR(r13)
788-
std r3, _DAR(r1)
789-
beq cr6, 2f
790-
li r10, 0x481 /* fix trap number for I-SLB miss */
791-
std r10, _TRAP(r1)
792-
2: bl save_nvgprs
793-
addi r3, r1, STACK_FRAME_OVERHEAD
794-
bl slb_miss_large_addr
672+
ld r4,_NIP(r1)
673+
ld r5,RESULT(r1)
674+
addi r3,r1,STACK_FRAME_OVERHEAD
675+
bl do_bad_slb_fault
795676
b ret_from_except
796677

678+
797679
EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100)
798680
.globl hardware_interrupt_hv;
799681
hardware_interrupt_hv:

arch/powerpc/mm/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
77

88
ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
99

10+
CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE)
11+
1012
obj-y := fault.o mem.o pgtable.o mmap.o \
1113
init_$(BITS).o pgtable_$(BITS).o \
1214
init-common.o mmu_context.o drmem.o
@@ -15,7 +17,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \
1517
obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o
1618
hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o
1719
obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o
18-
obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o
20+
obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o
1921
obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o
2022
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o
2123
obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o

0 commit comments

Comments
 (0)