Commit 1a4b739b authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

powerpc/32: implement fast entry for syscalls on BOOKE



This patch implements a fast entry for syscalls.

Syscalls don't have to preserve non volatile registers except LR.

This patch then implement a fast entry for syscalls, where
volatile registers get clobbered.

As this entry is dedicated to syscall it always sets MSR_EE
and warns in case MSR_EE was previously off

It also assumes that the call is always from user, system calls are
unexpected from kernel.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent b86fb888
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -342,7 +342,6 @@ stack_ovf:
	SYNC
	RFI

#ifndef CONFIG_BOOKE	/* to be removed once BOOKE uses fast syscall entry */
#ifdef CONFIG_TRACE_IRQFLAGS
trace_syscall_entry_irq_off:
	/*
@@ -369,7 +368,6 @@ transfer_to_syscall:
	andi.	r12,r9,MSR_EE
	beq-	trace_syscall_entry_irq_off
#endif /* CONFIG_TRACE_IRQFLAGS */
#endif /* !CONFIG_BOOKE */

/*
 * Handle a system call.
@@ -382,11 +380,6 @@ _GLOBAL(DoSyscall)
	stw	r3,ORIG_GPR3(r1)
	li	r12,0
	stw	r12,RESULT(r1)
#ifdef CONFIG_BOOKE	/* to be removed once BOOKE uses fast syscall entry */
	lwz	r11,_CCR(r1)	/* Clear SO bit in CR */
	rlwinm	r11,r11,0,4,2
	stw	r11,_CCR(r1)
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
	/* Make sure interrupts are enabled */
	mfmsr	r11
+1 −2
Original line number Diff line number Diff line
@@ -285,8 +285,7 @@ interrupt_base:
#endif
	/* System Call Interrupt */
	START_EXCEPTION(SystemCall)
	NORMAL_EXCEPTION_PROLOG(BOOKE_INTERRUPT_SYSCALL)
	EXC_XFER_SYS(0x0c00, DoSyscall)
	SYSCALL_ENTRY   0xc00 BOOKE_INTERRUPT_SYSCALL

	/* Auxiliary Processor Unavailable Interrupt */
	EXCEPTION(0x2020, BOOKE_INTERRUPT_AP_UNAVAIL, \
+98 −5
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_booke_hv_asm.h>

#ifdef __ASSEMBLY__

/*
 * Macros used for common Book-e exception handling
 */
@@ -81,6 +83,101 @@ END_BTB_FLUSH_SECTION
	SAVE_4GPRS(3, r11);						     \
	SAVE_2GPRS(7, r11)

.macro SYSCALL_ENTRY trapno intno
	mfspr	r10, SPRN_SPRG_THREAD
#ifdef CONFIG_KVM_BOOKE_HV
BEGIN_FTR_SECTION
	mtspr	SPRN_SPRG_WSCRATCH0, r10
	stw	r11, THREAD_NORMSAVE(0)(r10)
	stw	r13, THREAD_NORMSAVE(2)(r10)
	mfcr	r13			/* save CR in r13 for now	   */
	mfspr	r11, SPRN_SRR1
	mtocrf	0x80, r11	/* check MSR[GS] without clobbering reg */
	bf	3, 1975f
	b	kvmppc_handler_BOOKE_INTERRUPT_\intno\()_SPRN_SRR1
1975:
	mr	r12, r13
	lwz	r13, THREAD_NORMSAVE(2)(r10)
FTR_SECTION_ELSE
#endif
	mfcr	r12
#ifdef CONFIG_KVM_BOOKE_HV
ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
#endif
	BOOKE_CLEAR_BTB(r11)
	lwz	r11, TASK_STACK - THREAD(r10)
	rlwinm	r12,r12,0,4,2	/* Clear SO bit in CR */
	ALLOC_STACK_FRAME(r11, THREAD_SIZE - INT_FRAME_SIZE)
	stw	r12, _CCR(r11)		/* save various registers */
	mflr	r12
	stw	r12,_LINK(r11)
	mfspr	r12,SPRN_SRR0
	stw	r1, GPR1(r11)
	mfspr	r9,SPRN_SRR1
	stw	r1, 0(r11)
	mr	r1, r11
	stw	r12,_NIP(r11)
	rlwinm	r9,r9,0,14,12		/* clear MSR_WE (necessary?)	   */
	lis	r12, STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
	stw	r2,GPR2(r11)
	addi	r12, r12, STACK_FRAME_REGS_MARKER@l
	stw	r9,_MSR(r11)
	li	r2, \trapno + 1
	stw	r12, 8(r11)
	stw	r2,_TRAP(r11)
	SAVE_GPR(0, r11)
	SAVE_4GPRS(3, r11)
	SAVE_2GPRS(7, r11)

	addi	r11,r1,STACK_FRAME_OVERHEAD
	addi	r2,r10,-THREAD
	stw	r11,PT_REGS(r10)
	/* Check to see if the dbcr0 register is set up to debug.  Use the
	   internal debug mode bit to do this. */
	lwz	r12,THREAD_DBCR0(r10)
	andis.	r12,r12,DBCR0_IDM@h
	ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
	beq+	3f
	/* From user and task is ptraced - load up global dbcr0 */
	li	r12,-1			/* clear all pending debug events */
	mtspr	SPRN_DBSR,r12
	lis	r11,global_dbcr0@ha
	tophys(r11,r11)
	addi	r11,r11,global_dbcr0@l
#ifdef CONFIG_SMP
	lwz	r9,TASK_CPU(r2)
	slwi	r9,r9,3
	add	r11,r11,r9
#endif
	lwz	r12,0(r11)
	mtspr	SPRN_DBCR0,r12
	lwz	r12,4(r11)
	addi	r12,r12,-1
	stw	r12,4(r11)

3:
	tovirt(r2, r2)			/* set r2 to current */
	lis	r11, transfer_to_syscall@h
	ori	r11, r11, transfer_to_syscall@l
#ifdef CONFIG_TRACE_IRQFLAGS
	/*
	 * If MSR is changing we need to keep interrupts disabled at this point
	 * otherwise we might risk taking an interrupt before we tell lockdep
	 * they are enabled.
	 */
	lis	r10, MSR_KERNEL@h
	ori	r10, r10, MSR_KERNEL@l
	rlwimi	r10, r9, 0, MSR_EE
#else
	lis	r10, (MSR_KERNEL | MSR_EE)@h
	ori	r10, r10, (MSR_KERNEL | MSR_EE)@l
#endif
	mtspr	SPRN_SRR1,r10
	mtspr	SPRN_SRR0,r11
	SYNC
	RFI				/* jump to handler, enable MMU */
.endm

/* To handle the additional exception priority levels on 40x and Book-E
 * processors we allocate a stack per additional priority level.
 *
@@ -245,10 +342,6 @@ label:
	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \
			  ret_from_except)

#define EXC_XFER_SYS(n, hdlr)						\
	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL | MSR_EE, transfer_to_handler, \
			  ret_from_except)

/* Check for a single step debug exception while in an exception
 * handler before state has been saved.  This is to catch the case
 * where an instruction that we are trying to single step causes
@@ -418,7 +511,7 @@ label:
1:	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
	EXC_XFER_STD(0x800, kernel_fp_unavailable_exception)

#ifndef __ASSEMBLY__
#else /* __ASSEMBLY__ */
struct exception_regs {
	unsigned long mas0;
	unsigned long mas1;
+1 −2
Original line number Diff line number Diff line
@@ -413,8 +413,7 @@ interrupt_base:

	/* System Call Interrupt */
	START_EXCEPTION(SystemCall)
	NORMAL_EXCEPTION_PROLOG(SYSCALL)
	EXC_XFER_SYS(0x0c00, DoSyscall)
	SYSCALL_ENTRY   0xc00 SYSCALL

	/* Auxiliary Processor Unavailable Interrupt */
	EXCEPTION(0x2900, AP_UNAVAIL, AuxillaryProcessorUnavailable, \