| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Low-level exception handling code | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2012 ARM Ltd. | 
					
						
							|  |  |  |  * Authors:	Catalin Marinas <catalin.marinas@arm.com>
 | 
					
						
							|  |  |  |  *		Will Deacon <will.deacon@arm.com>
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify
 | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License version 2 as | 
					
						
							|  |  |  |  * published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/init.h> | 
					
						
							|  |  |  | #include <linux/linkage.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/assembler.h> | 
					
						
							|  |  |  | #include <asm/asm-offsets.h> | 
					
						
							|  |  |  | #include <asm/errno.h> | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | #include <asm/esr.h> | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | #include <asm/thread_info.h> | 
					
						
							|  |  |  | #include <asm/unistd.h> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Context tracking subsystem.  Used to instrument transitions | 
					
						
							|  |  |  |  * between user and kernel mode. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.macro ct_user_exit, syscall = 0 | 
					
						
							|  |  |  | #ifdef CONFIG_CONTEXT_TRACKING | 
					
						
							|  |  |  | 	bl	context_tracking_user_exit | 
					
						
							|  |  |  | 	.if \syscall == 1 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Save/restore needed during syscalls.  Restore syscall arguments from | 
					
						
							|  |  |  | 	 * the values already saved on stack during kernel_entry. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	ldp	x0, x1, [sp] | 
					
						
							|  |  |  | 	ldp	x2, x3, [sp, #S_X2] | 
					
						
							|  |  |  | 	ldp	x4, x5, [sp, #S_X4] | 
					
						
							|  |  |  | 	ldp	x6, x7, [sp, #S_X6] | 
					
						
							|  |  |  | 	.endif | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.macro ct_user_enter
 | 
					
						
							|  |  |  | #ifdef CONFIG_CONTEXT_TRACKING | 
					
						
							|  |  |  | 	bl	context_tracking_user_enter | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Bad Abort numbers | 
					
						
							|  |  |  |  *----------------- | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define BAD_SYNC	0 | 
					
						
							|  |  |  | #define BAD_IRQ		1 | 
					
						
							|  |  |  | #define BAD_FIQ		2 | 
					
						
							|  |  |  | #define BAD_ERROR	3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.macro	kernel_entry, el, regsize = 64 | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	sub	sp, sp, #S_FRAME_SIZE | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.if	\regsize == 32 | 
					
						
							|  |  |  | 	mov	w0, w0				// zero upper 32 bits of x0 | 
					
						
							|  |  |  | 	.endif | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	stp	x0, x1, [sp, #16 * 0] | 
					
						
							|  |  |  | 	stp	x2, x3, [sp, #16 * 1] | 
					
						
							|  |  |  | 	stp	x4, x5, [sp, #16 * 2] | 
					
						
							|  |  |  | 	stp	x6, x7, [sp, #16 * 3] | 
					
						
							|  |  |  | 	stp	x8, x9, [sp, #16 * 4] | 
					
						
							|  |  |  | 	stp	x10, x11, [sp, #16 * 5] | 
					
						
							|  |  |  | 	stp	x12, x13, [sp, #16 * 6] | 
					
						
							|  |  |  | 	stp	x14, x15, [sp, #16 * 7] | 
					
						
							|  |  |  | 	stp	x16, x17, [sp, #16 * 8] | 
					
						
							|  |  |  | 	stp	x18, x19, [sp, #16 * 9] | 
					
						
							|  |  |  | 	stp	x20, x21, [sp, #16 * 10] | 
					
						
							|  |  |  | 	stp	x22, x23, [sp, #16 * 11] | 
					
						
							|  |  |  | 	stp	x24, x25, [sp, #16 * 12] | 
					
						
							|  |  |  | 	stp	x26, x27, [sp, #16 * 13] | 
					
						
							|  |  |  | 	stp	x28, x29, [sp, #16 * 14] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.if	\el == 0 | 
					
						
							|  |  |  | 	mrs	x21, sp_el0 | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	get_thread_info tsk			// Ensure MDSCR_EL1.SS is clear, | 
					
						
							|  |  |  | 	ldr	x19, [tsk, #TI_FLAGS]		// since we can unmask debug | 
					
						
							|  |  |  | 	disable_step_tsk x19, x20		// exceptions when scheduling. | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.else | 
					
						
							|  |  |  | 	add	x21, sp, #S_FRAME_SIZE | 
					
						
							|  |  |  | 	.endif | 
					
						
							|  |  |  | 	mrs	x22, elr_el1 | 
					
						
							|  |  |  | 	mrs	x23, spsr_el1 | 
					
						
							|  |  |  | 	stp	lr, x21, [sp, #S_LR] | 
					
						
							|  |  |  | 	stp	x22, x23, [sp, #S_PC] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Set syscallno to -1 by default (overridden later if real syscall). | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	.if	\el == 0 | 
					
						
							|  |  |  | 	mvn	x21, xzr | 
					
						
							|  |  |  | 	str	x21, [sp, #S_SYSCALLNO] | 
					
						
							|  |  |  | 	.endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Registers that may be useful after this macro is invoked: | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * x21 - aborted SP | 
					
						
							|  |  |  | 	 * x22 - aborted PC | 
					
						
							|  |  |  | 	 * x23 - aborted PSTATE | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.macro	kernel_exit, el, ret = 0 | 
					
						
							|  |  |  | 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR | 
					
						
							|  |  |  | 	.if	\el == 0 | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_enter | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	ldr	x23, [sp, #S_SP]		// load return stack pointer | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	msr	sp_el0, x23 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.endif | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	msr	elr_el1, x21			// set up the return data | 
					
						
							|  |  |  | 	msr	spsr_el1, x22 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.if	\ret | 
					
						
							|  |  |  | 	ldr	x1, [sp, #S_X1]			// preserve x0 (syscall return) | 
					
						
							|  |  |  | 	.else | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	ldp	x0, x1, [sp, #16 * 0] | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.endif | 
					
						
							| 
									
										
										
										
											2014-09-29 12:26:41 +01:00
										 |  |  | 	ldp	x2, x3, [sp, #16 * 1] | 
					
						
							|  |  |  | 	ldp	x4, x5, [sp, #16 * 2] | 
					
						
							|  |  |  | 	ldp	x6, x7, [sp, #16 * 3] | 
					
						
							|  |  |  | 	ldp	x8, x9, [sp, #16 * 4] | 
					
						
							|  |  |  | 	ldp	x10, x11, [sp, #16 * 5] | 
					
						
							|  |  |  | 	ldp	x12, x13, [sp, #16 * 6] | 
					
						
							|  |  |  | 	ldp	x14, x15, [sp, #16 * 7] | 
					
						
							|  |  |  | 	ldp	x16, x17, [sp, #16 * 8] | 
					
						
							|  |  |  | 	ldp	x18, x19, [sp, #16 * 9] | 
					
						
							|  |  |  | 	ldp	x20, x21, [sp, #16 * 10] | 
					
						
							|  |  |  | 	ldp	x22, x23, [sp, #16 * 11] | 
					
						
							|  |  |  | 	ldp	x24, x25, [sp, #16 * 12] | 
					
						
							|  |  |  | 	ldp	x26, x27, [sp, #16 * 13] | 
					
						
							|  |  |  | 	ldp	x28, x29, [sp, #16 * 14] | 
					
						
							|  |  |  | 	ldr	lr, [sp, #S_LR] | 
					
						
							|  |  |  | 	add	sp, sp, #S_FRAME_SIZE		// restore sp | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	eret					// return to kernel | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.macro	get_thread_info, rd | 
					
						
							|  |  |  | 	mov	\rd, sp | 
					
						
							| 
									
										
										
										
											2013-07-23 18:52:31 +01:00
										 |  |  | 	and	\rd, \rd, #~(THREAD_SIZE - 1)	// top of stack | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * These are the registers used in the syscall handler, and allow us to | 
					
						
							|  |  |  |  * have in theory up to 7 arguments to a function - x0 to x6. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * x7 is reserved for the system call number in 32-bit mode. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | sc_nr	.req	x25		// number of system calls | 
					
						
							|  |  |  | scno	.req	x26		// syscall number | 
					
						
							|  |  |  | stbl	.req	x27		// syscall table pointer | 
					
						
							|  |  |  | tsk	.req	x28		// current thread_info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Interrupt handling. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.macro	irq_handler
 | 
					
						
							| 
									
										
										
										
											2014-11-21 21:50:38 +00:00
										 |  |  | 	adrp	x1, handle_arch_irq | 
					
						
							|  |  |  | 	ldr	x1, [x1, #:lo12:handle_arch_irq] | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	blr	x1 | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.text | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Exception vectors. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	11
 | 
					
						
							|  |  |  | ENTRY(vectors) | 
					
						
							|  |  |  | 	ventry	el1_sync_invalid		// Synchronous EL1t | 
					
						
							|  |  |  | 	ventry	el1_irq_invalid			// IRQ EL1t | 
					
						
							|  |  |  | 	ventry	el1_fiq_invalid			// FIQ EL1t | 
					
						
							|  |  |  | 	ventry	el1_error_invalid		// Error EL1t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ventry	el1_sync			// Synchronous EL1h | 
					
						
							|  |  |  | 	ventry	el1_irq				// IRQ EL1h | 
					
						
							|  |  |  | 	ventry	el1_fiq_invalid			// FIQ EL1h | 
					
						
							|  |  |  | 	ventry	el1_error_invalid		// Error EL1h | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ventry	el0_sync			// Synchronous 64-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_irq				// IRQ 64-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_fiq_invalid			// FIQ 64-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_error_invalid		// Error 64-bit EL0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_COMPAT | 
					
						
							|  |  |  | 	ventry	el0_sync_compat			// Synchronous 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_irq_compat			// IRQ 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_fiq_invalid_compat		// FIQ 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_error_invalid_compat	// Error 32-bit EL0 | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  | 	ventry	el0_sync_invalid		// Synchronous 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_irq_invalid			// IRQ 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_fiq_invalid			// FIQ 32-bit EL0 | 
					
						
							|  |  |  | 	ventry	el0_error_invalid		// Error 32-bit EL0 | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | END(vectors) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Invalid mode handlers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.macro	inv_entry, el, reason, regsize = 64 | 
					
						
							|  |  |  | 	kernel_entry el, \regsize | 
					
						
							|  |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	mov	x1, #\reason | 
					
						
							|  |  |  | 	mrs	x2, esr_el1 | 
					
						
							|  |  |  | 	b	bad_mode | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_sync_invalid: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_SYNC | 
					
						
							|  |  |  | ENDPROC(el0_sync_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_irq_invalid: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_IRQ | 
					
						
							|  |  |  | ENDPROC(el0_irq_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_fiq_invalid: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_FIQ | 
					
						
							|  |  |  | ENDPROC(el0_fiq_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_error_invalid: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_ERROR | 
					
						
							|  |  |  | ENDPROC(el0_error_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_COMPAT | 
					
						
							|  |  |  | el0_fiq_invalid_compat: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_FIQ, 32 | 
					
						
							|  |  |  | ENDPROC(el0_fiq_invalid_compat) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_error_invalid_compat: | 
					
						
							|  |  |  | 	inv_entry 0, BAD_ERROR, 32 | 
					
						
							|  |  |  | ENDPROC(el0_error_invalid_compat) | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el1_sync_invalid: | 
					
						
							|  |  |  | 	inv_entry 1, BAD_SYNC | 
					
						
							|  |  |  | ENDPROC(el1_sync_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el1_irq_invalid: | 
					
						
							|  |  |  | 	inv_entry 1, BAD_IRQ | 
					
						
							|  |  |  | ENDPROC(el1_irq_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el1_fiq_invalid: | 
					
						
							|  |  |  | 	inv_entry 1, BAD_FIQ | 
					
						
							|  |  |  | ENDPROC(el1_fiq_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el1_error_invalid: | 
					
						
							|  |  |  | 	inv_entry 1, BAD_ERROR | 
					
						
							|  |  |  | ENDPROC(el1_error_invalid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * EL1 mode handlers. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el1_sync: | 
					
						
							|  |  |  | 	kernel_entry 1 | 
					
						
							|  |  |  | 	mrs	x1, esr_el1			// read the syndrome register | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	lsr	x24, x1, #ESR_EL1_EC_SHIFT	// exception class | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_DABT_EL1	// data abort in EL1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el1_da | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_SYS64		// configurable trap | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el1_undef | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_SP_ALIGN	// stack alignment exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el1_sp_pc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_PC_ALIGN	// pc alignment exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el1_sp_pc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_UNKNOWN	// unknown exception in EL1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el1_undef | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_BREAKPT_EL1	// debug exception in EL1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.ge	el1_dbg | 
					
						
							|  |  |  | 	b	el1_inv | 
					
						
							|  |  |  | el1_da: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Data abort handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	mrs	x0, far_el1 | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	// re-enable interrupts if they were enabled in the aborted context | 
					
						
							|  |  |  | 	tbnz	x23, #7, 1f			// PSR_I_BIT | 
					
						
							|  |  |  | 	enable_irq | 
					
						
							|  |  |  | 1: | 
					
						
							|  |  |  | 	mov	x2, sp				// struct pt_regs | 
					
						
							|  |  |  | 	bl	do_mem_abort | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// disable interrupts before pulling preserved data off the stack | 
					
						
							|  |  |  | 	disable_irq | 
					
						
							|  |  |  | 	kernel_exit 1 | 
					
						
							|  |  |  | el1_sp_pc: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Stack or PC alignment exception handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	mrs	x0, far_el1 | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x2, sp | 
					
						
							|  |  |  | 	b	do_sp_pc_abort | 
					
						
							|  |  |  | el1_undef: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Undefined instruction | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	b	do_undefinstr | 
					
						
							|  |  |  | el1_dbg: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Debug exception handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-12-04 05:50:20 +00:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_BRK64		// if BRK64 | 
					
						
							|  |  |  | 	cinc	x24, x24, eq			// set bit '0' | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	tbz	x24, #0, el1_inv		// EL1 only | 
					
						
							|  |  |  | 	mrs	x0, far_el1 | 
					
						
							|  |  |  | 	mov	x2, sp				// struct pt_regs | 
					
						
							|  |  |  | 	bl	do_debug_exception | 
					
						
							|  |  |  | 	kernel_exit 1 | 
					
						
							|  |  |  | el1_inv: | 
					
						
							|  |  |  | 	// TODO: add support for undefined instructions in kernel mode | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	mov	x1, #BAD_SYNC | 
					
						
							|  |  |  | 	mrs	x2, esr_el1 | 
					
						
							|  |  |  | 	b	bad_mode | 
					
						
							|  |  |  | ENDPROC(el1_sync) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el1_irq: | 
					
						
							|  |  |  | 	kernel_entry 1 | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | #ifdef CONFIG_TRACE_IRQFLAGS | 
					
						
							|  |  |  | 	bl	trace_hardirqs_off | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2013-11-12 17:11:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	irq_handler | 
					
						
							| 
									
										
										
										
											2013-11-12 17:11:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | #ifdef CONFIG_PREEMPT | 
					
						
							| 
									
										
										
										
											2013-11-12 17:11:53 +00:00
										 |  |  | 	get_thread_info tsk | 
					
						
							| 
									
										
										
										
											2014-01-13 08:57:56 +00:00
										 |  |  | 	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count | 
					
						
							| 
									
										
										
										
											2013-11-04 20:14:58 +00:00
										 |  |  | 	cbnz	w24, 1f				// preempt count != 0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	ldr	x0, [tsk, #TI_FLAGS]		// get flags | 
					
						
							|  |  |  | 	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling? | 
					
						
							|  |  |  | 	bl	el1_preempt | 
					
						
							|  |  |  | 1: | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #ifdef CONFIG_TRACE_IRQFLAGS | 
					
						
							|  |  |  | 	bl	trace_hardirqs_on | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	kernel_exit 1 | 
					
						
							|  |  |  | ENDPROC(el1_irq) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_PREEMPT | 
					
						
							|  |  |  | el1_preempt: | 
					
						
							|  |  |  | 	mov	x24, lr | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 1:	bl	preempt_schedule_irq		// irq en/disable is done inside | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	ldr	x0, [tsk, #TI_FLAGS]		// get new tasks TI_FLAGS | 
					
						
							|  |  |  | 	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling? | 
					
						
							|  |  |  | 	ret	x24 | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * EL0 mode handlers. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el0_sync: | 
					
						
							|  |  |  | 	kernel_entry 0 | 
					
						
							|  |  |  | 	mrs	x25, esr_el1			// read the syndrome register | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	lsr	x24, x25, #ESR_EL1_EC_SHIFT	// exception class | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_SVC64		// SVC in 64-bit state | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_svc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_DABT_EL0	// data abort in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_da | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_IABT_EL0	// instruction abort in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_ia | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_FP_ASIMD	// FP/ASIMD access | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_fpsimd_acc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_FP_EXC64	// FP/ASIMD exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_fpsimd_exc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_SYS64		// configurable trap | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_undef | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_SP_ALIGN	// stack alignment exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_sp_pc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_PC_ALIGN	// pc alignment exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_sp_pc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_UNKNOWN	// unknown exception in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_undef | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_BREAKPT_EL0	// debug exception in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.ge	el0_dbg | 
					
						
							|  |  |  | 	b	el0_inv | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_COMPAT | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el0_sync_compat: | 
					
						
							|  |  |  | 	kernel_entry 0, 32 | 
					
						
							|  |  |  | 	mrs	x25, esr_el1			// read the syndrome register | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	lsr	x24, x25, #ESR_EL1_EC_SHIFT	// exception class | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_SVC32		// SVC in 32-bit state | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_svc_compat | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_DABT_EL0	// data abort in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_da | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_IABT_EL0	// instruction abort in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_ia | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_FP_ASIMD	// FP/ASIMD access | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_fpsimd_acc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_FP_EXC32	// FP/ASIMD exception | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_fpsimd_exc | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_UNKNOWN	// unknown exception in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.eq	el0_undef | 
					
						
							| 
									
										
										
										
											2013-05-24 12:02:35 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_CP15_32	// CP15 MRC/MCR trap | 
					
						
							|  |  |  | 	b.eq	el0_undef | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_CP15_64	// CP15 MRRC/MCRR trap | 
					
						
							|  |  |  | 	b.eq	el0_undef | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_CP14_MR	// CP14 MRC/MCR trap | 
					
						
							|  |  |  | 	b.eq	el0_undef | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_CP14_LS	// CP14 LDC/STC trap | 
					
						
							|  |  |  | 	b.eq	el0_undef | 
					
						
							|  |  |  | 	cmp	x24, #ESR_EL1_EC_CP14_64	// CP14 MRRC/MCRR trap | 
					
						
							|  |  |  | 	b.eq	el0_undef | 
					
						
							| 
									
										
										
										
											2013-04-08 17:17:03 +01:00
										 |  |  | 	cmp	x24, #ESR_EL1_EC_BREAKPT_EL0	// debug exception in EL0 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b.ge	el0_dbg | 
					
						
							|  |  |  | 	b	el0_inv | 
					
						
							|  |  |  | el0_svc_compat: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * AArch32 syscall handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	adr	stbl, compat_sys_call_table	// load compat syscall table pointer | 
					
						
							|  |  |  | 	uxtw	scno, w7			// syscall number in w7 (r7) | 
					
						
							|  |  |  | 	mov     sc_nr, #__NR_compat_syscalls | 
					
						
							|  |  |  | 	b	el0_svc_naked | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el0_irq_compat: | 
					
						
							|  |  |  | 	kernel_entry 0, 32 | 
					
						
							|  |  |  | 	b	el0_irq_naked | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | el0_da: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Data abort handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	mrs	x26, far_el1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	// enable interrupts before calling the main handler | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg_and_irq | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	bic	x0, x26, #(0xff << 56) | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x1, x25 | 
					
						
							|  |  |  | 	mov	x2, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_mem_abort | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_ia: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Instruction abort handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	mrs	x26, far_el1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	// enable interrupts before calling the main handler | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg_and_irq | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	mov	x0, x26 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	orr	x1, x25, #1 << 24		// use reserved ISS bit for instruction aborts | 
					
						
							|  |  |  | 	mov	x2, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_mem_abort | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_fpsimd_acc: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Floating Point or Advanced SIMD access | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, x25 | 
					
						
							|  |  |  | 	mov	x1, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_fpsimd_acc | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_fpsimd_exc: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Floating Point or Advanced SIMD exception | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, x25 | 
					
						
							|  |  |  | 	mov	x1, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_fpsimd_exc | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_sp_pc: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Stack or PC alignment exception handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	mrs	x26, far_el1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	// enable interrupts before calling the main handler | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg_and_irq | 
					
						
							| 
									
										
										
										
											2014-05-30 20:34:14 +01:00
										 |  |  | 	mov	x0, x26 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x1, x25 | 
					
						
							|  |  |  | 	mov	x2, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_sp_pc_abort | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_undef: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Undefined instruction | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-08-22 11:47:37 +01:00
										 |  |  | 	// enable interrupts before calling the main handler | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg_and_irq | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	mov	x0, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_undefinstr | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_dbg: | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Debug exception handling | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	tbnz	x24, #0, el0_inv		// EL0 only | 
					
						
							|  |  |  | 	mrs	x0, far_el1 | 
					
						
							|  |  |  | 	mov	x1, x25 | 
					
						
							|  |  |  | 	mov	x2, sp | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	bl	do_debug_exception | 
					
						
							|  |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | el0_inv: | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	mov	x1, #BAD_SYNC | 
					
						
							|  |  |  | 	mrs	x2, esr_el1 | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	bad_mode | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | ENDPROC(el0_sync) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el0_irq: | 
					
						
							|  |  |  | 	kernel_entry 0 | 
					
						
							|  |  |  | el0_irq_naked: | 
					
						
							|  |  |  | 	enable_dbg | 
					
						
							|  |  |  | #ifdef CONFIG_TRACE_IRQFLAGS | 
					
						
							|  |  |  | 	bl	trace_hardirqs_off | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2013-11-12 17:11:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	irq_handler | 
					
						
							| 
									
										
										
										
											2013-11-12 17:11:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | #ifdef CONFIG_TRACE_IRQFLAGS | 
					
						
							|  |  |  | 	bl	trace_hardirqs_on | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							|  |  |  | ENDPROC(el0_irq) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Register switch for AArch64. The callee-saved registers need to be saved | 
					
						
							|  |  |  |  * and restored. On entry: | 
					
						
							|  |  |  |  *   x0 = previous task_struct (must be preserved across the switch) | 
					
						
							|  |  |  |  *   x1 = next task_struct | 
					
						
							|  |  |  |  * Previous and next are guaranteed not to be the same. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ENTRY(cpu_switch_to) | 
					
						
							|  |  |  | 	add	x8, x0, #THREAD_CPU_CONTEXT | 
					
						
							|  |  |  | 	mov	x9, sp | 
					
						
							|  |  |  | 	stp	x19, x20, [x8], #16		// store callee-saved registers | 
					
						
							|  |  |  | 	stp	x21, x22, [x8], #16 | 
					
						
							|  |  |  | 	stp	x23, x24, [x8], #16 | 
					
						
							|  |  |  | 	stp	x25, x26, [x8], #16 | 
					
						
							|  |  |  | 	stp	x27, x28, [x8], #16 | 
					
						
							|  |  |  | 	stp	x29, x9, [x8], #16 | 
					
						
							|  |  |  | 	str	lr, [x8] | 
					
						
							|  |  |  | 	add	x8, x1, #THREAD_CPU_CONTEXT | 
					
						
							|  |  |  | 	ldp	x19, x20, [x8], #16		// restore callee-saved registers | 
					
						
							|  |  |  | 	ldp	x21, x22, [x8], #16 | 
					
						
							|  |  |  | 	ldp	x23, x24, [x8], #16 | 
					
						
							|  |  |  | 	ldp	x25, x26, [x8], #16 | 
					
						
							|  |  |  | 	ldp	x27, x28, [x8], #16 | 
					
						
							|  |  |  | 	ldp	x29, x9, [x8], #16 | 
					
						
							|  |  |  | 	ldr	lr, [x8] | 
					
						
							|  |  |  | 	mov	sp, x9 | 
					
						
							|  |  |  | 	ret | 
					
						
							|  |  |  | ENDPROC(cpu_switch_to) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This is the fast syscall return path.  We do as little as possible here, | 
					
						
							|  |  |  |  * and this includes saving x0 back into the kernel stack. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ret_fast_syscall: | 
					
						
							|  |  |  | 	disable_irq				// disable interrupts | 
					
						
							|  |  |  | 	ldr	x1, [tsk, #TI_FLAGS] | 
					
						
							|  |  |  | 	and	x2, x1, #_TIF_WORK_MASK | 
					
						
							|  |  |  | 	cbnz	x2, fast_work_pending | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_step_tsk x1, x2 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	kernel_exit 0, ret = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Ok, we need to do extra processing, enter the slow path. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | fast_work_pending: | 
					
						
							|  |  |  | 	str	x0, [sp, #S_X0]			// returned x0 | 
					
						
							|  |  |  | work_pending: | 
					
						
							|  |  |  | 	tbnz	x1, #TIF_NEED_RESCHED, work_resched | 
					
						
							| 
									
										
										
										
											2014-05-08 11:20:23 +02:00
										 |  |  | 	/* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */ | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	ldr	x2, [sp, #S_PSTATE] | 
					
						
							|  |  |  | 	mov	x0, sp				// 'regs' | 
					
						
							|  |  |  | 	tst	x2, #PSR_MODE_MASK		// user mode regs? | 
					
						
							|  |  |  | 	b.ne	no_work_pending			// returning to kernel | 
					
						
							| 
									
										
										
										
											2012-10-08 18:04:21 +01:00
										 |  |  | 	enable_irq				// enable interrupts for do_notify_resume() | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	bl	do_notify_resume | 
					
						
							|  |  |  | 	b	ret_to_user | 
					
						
							|  |  |  | work_resched: | 
					
						
							|  |  |  | 	bl	schedule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * "slow" syscall return path. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-09-10 16:11:46 +01:00
										 |  |  | ret_to_user: | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	disable_irq				// disable interrupts | 
					
						
							|  |  |  | 	ldr	x1, [tsk, #TI_FLAGS] | 
					
						
							|  |  |  | 	and	x2, x1, #_TIF_WORK_MASK | 
					
						
							|  |  |  | 	cbnz	x2, work_pending | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_step_tsk x1, x2 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | no_work_pending: | 
					
						
							|  |  |  | 	kernel_exit 0, ret = 0 | 
					
						
							|  |  |  | ENDPROC(ret_to_user) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This is how we return from a fork. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ENTRY(ret_from_fork) | 
					
						
							|  |  |  | 	bl	schedule_tail | 
					
						
							| 
									
										
										
										
											2012-10-05 12:31:20 +01:00
										 |  |  | 	cbz	x19, 1f				// not a kernel thread | 
					
						
							|  |  |  | 	mov	x0, x20 | 
					
						
							|  |  |  | 	blr	x19 | 
					
						
							|  |  |  | 1:	get_thread_info tsk | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b	ret_to_user | 
					
						
							|  |  |  | ENDPROC(ret_from_fork) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * SVC handler. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 	.align	6
 | 
					
						
							|  |  |  | el0_svc: | 
					
						
							|  |  |  | 	adrp	stbl, sys_call_table		// load syscall table pointer | 
					
						
							|  |  |  | 	uxtw	scno, w8			// syscall number in w8 | 
					
						
							|  |  |  | 	mov	sc_nr, #__NR_syscalls | 
					
						
							|  |  |  | el0_svc_naked:					// compat entry point | 
					
						
							|  |  |  | 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number | 
					
						
							| 
									
										
											  
											
												arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
  - Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
    avoid disabling step in the MDSCR when we don't need to.
    MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
    userspace.
  - Ensure debug exceptions are re-enabled on *all* exception entry
    paths, even the debug exception handling path (where we re-enable
    exceptions after invoking the handler). Since we can now rely on
    MDSCR_EL1.SS being cleared by the entry code, exception handlers can
    usually enable debug immediately before enabling interrupts.
  - Remove all debug exception unmasking from ret_to_user and
    el1_preempt, since we will never get here with debug exceptions
    masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
											
										 
											2014-04-29 19:04:06 +01:00
										 |  |  | 	enable_dbg_and_irq | 
					
						
							| 
									
										
										
										
											2014-05-30 12:34:15 -07:00
										 |  |  | 	ct_user_exit 1 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-30 10:51:29 +01:00
										 |  |  | 	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks | 
					
						
							|  |  |  | 	tst	x16, #_TIF_SYSCALL_WORK | 
					
						
							|  |  |  | 	b.ne	__sys_trace | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	cmp     scno, sc_nr                     // check upper syscall limit | 
					
						
							|  |  |  | 	b.hs	ni_sys | 
					
						
							|  |  |  | 	ldr	x16, [stbl, scno, lsl #3]	// address in the syscall table | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	blr	x16				// call sys_* routine | 
					
						
							|  |  |  | 	b	ret_fast_syscall | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | ni_sys: | 
					
						
							|  |  |  | 	mov	x0, sp | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	bl	do_ni_syscall | 
					
						
							|  |  |  | 	b	ret_fast_syscall | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | ENDPROC(el0_svc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * This is the really slow path.  We're going to be doing context | 
					
						
							|  |  |  | 	 * switches, and waiting for our parent to respond. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | __sys_trace: | 
					
						
							| 
									
										
										
										
											2014-11-28 05:26:35 +00:00
										 |  |  | 	mov	w0, #-1				// set default errno for | 
					
						
							|  |  |  | 	cmp     scno, x0			// user-issued syscall(-1) | 
					
						
							|  |  |  | 	b.ne	1f | 
					
						
							|  |  |  | 	mov	x0, #-ENOSYS | 
					
						
							|  |  |  | 	str	x0, [sp, #S_X0] | 
					
						
							|  |  |  | 1:	mov	x0, sp | 
					
						
							| 
									
										
										
										
											2014-04-30 10:51:30 +01:00
										 |  |  | 	bl	syscall_trace_enter | 
					
						
							| 
									
										
										
										
											2014-11-28 05:26:35 +00:00
										 |  |  | 	cmp	w0, #-1				// skip the syscall? | 
					
						
							|  |  |  | 	b.eq	__sys_trace_return_skipped | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	uxtw	scno, w0			// syscall number (possibly new) | 
					
						
							|  |  |  | 	mov	x1, sp				// pointer to regs | 
					
						
							|  |  |  | 	cmp	scno, sc_nr			// check upper syscall limit | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	b.hs	__ni_sys_trace | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	ldp	x0, x1, [sp]			// restore the syscall args | 
					
						
							|  |  |  | 	ldp	x2, x3, [sp, #S_X2] | 
					
						
							|  |  |  | 	ldp	x4, x5, [sp, #S_X4] | 
					
						
							|  |  |  | 	ldp	x6, x7, [sp, #S_X6] | 
					
						
							|  |  |  | 	ldr	x16, [stbl, scno, lsl #3]	// address in the syscall table | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | 	blr	x16				// call sys_* routine | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | __sys_trace_return: | 
					
						
							| 
									
										
										
										
											2014-11-28 05:26:35 +00:00
										 |  |  | 	str	x0, [sp, #S_X0]			// save returned x0 | 
					
						
							|  |  |  | __sys_trace_return_skipped: | 
					
						
							| 
									
										
										
										
											2014-04-30 10:51:30 +01:00
										 |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	bl	syscall_trace_exit | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | 	b	ret_to_user | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 11:44:01 +01:00
										 |  |  | __ni_sys_trace: | 
					
						
							|  |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	bl	do_ni_syscall | 
					
						
							|  |  |  | 	b	__sys_trace_return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-05 11:49:27 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Special system call wrappers. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ENTRY(sys_rt_sigreturn_wrapper) | 
					
						
							|  |  |  | 	mov	x0, sp | 
					
						
							|  |  |  | 	b	sys_rt_sigreturn | 
					
						
							|  |  |  | ENDPROC(sys_rt_sigreturn_wrapper) |