svn commit: r295142 - in head/sys/arm64: arm64 include

Andrew Turner andrew at FreeBSD.org
Tue Feb 2 10:28:58 UTC 2016


Author: andrew
Date: Tue Feb  2 10:28:56 2016
New Revision: 295142
URL: https://svnweb.freebsd.org/changeset/base/295142

Log:
  Implement single stepping on arm64. We need to set the single step bits in
  the processor and debug state registers. A flag has been added to the pcb
  to tell us when to enable single stepping for a given thread.
  
  Reviewed by:	kib
  Sponsored by:	ABT Systems Ltd
  Differential Revision:	https://reviews.freebsd.org/D4730

Modified:
  head/sys/arm64/arm64/genassym.c
  head/sys/arm64/arm64/machdep.c
  head/sys/arm64/arm64/mp_machdep.c
  head/sys/arm64/arm64/swtch.S
  head/sys/arm64/arm64/trap.c
  head/sys/arm64/include/armreg.h
  head/sys/arm64/include/pcb.h

Modified: head/sys/arm64/arm64/genassym.c
==============================================================================
--- head/sys/arm64/arm64/genassym.c	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/arm64/genassym.c	Tue Feb  2 10:28:56 2016	(r295142)
@@ -49,10 +49,12 @@ ASSYM(PC_CURTHREAD, offsetof(struct pcpu
 
 /* Size of pcb, rounded to keep stack alignment */
 ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1));
+ASSYM(PCB_SINGLE_STEP_SHIFT, PCB_SINGLE_STEP_SHIFT);
 ASSYM(PCB_REGS, offsetof(struct pcb, pcb_x));
 ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
 ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr));
 ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
 
 ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
 

Modified: head/sys/arm64/arm64/machdep.c
==============================================================================
--- head/sys/arm64/arm64/machdep.c	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/arm64/machdep.c	Tue Feb  2 10:28:56 2016	(r295142)
@@ -233,7 +233,8 @@ int
 ptrace_single_step(struct thread *td)
 {
 
-	/* TODO; */
+	td->td_frame->tf_spsr |= PSR_SS;
+	td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
 	return (0);
 }
 
@@ -241,7 +242,8 @@ int
 ptrace_clear_single_step(struct thread *td)
 {
 
-	/* TODO; */
+	td->td_frame->tf_spsr &= ~PSR_SS;
+	td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
 	return (0);
 }
 

Modified: head/sys/arm64/arm64/mp_machdep.c
==============================================================================
--- head/sys/arm64/arm64/mp_machdep.c	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/arm64/mp_machdep.c	Tue Feb  2 10:28:56 2016	(r295142)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_extern.h>
 #include <vm/vm_kern.h>
 
+#include <machine/debug_monitor.h>
 #include <machine/intr.h>
 #include <machine/smp.h>
 #ifdef VFP
@@ -247,6 +248,8 @@ init_secondary(uint64_t cpu)
 	vfp_init();
 #endif
 
+	dbg_monitor_init();
+
 	/* Enable interrupts */
 	intr_enable();
 

Modified: head/sys/arm64/arm64/swtch.S
==============================================================================
--- head/sys/arm64/arm64/swtch.S	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/arm64/swtch.S	Tue Feb  2 10:28:56 2016	(r295142)
@@ -37,10 +37,37 @@
 
 __FBSDID("$FreeBSD$");
 
+.macro clear_step_flag pcbflags, tmp
+	tbz	\pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
+	mrs	\tmp, mdscr_el1
+	bic	\tmp, \tmp, #1
+	msr	mdscr_el1, \tmp
+	isb
+999:
+.endm
+
+.macro set_step_flag pcbflags, tmp
+	tbz	\pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
+	mrs	\tmp, mdscr_el1
+	orr	\tmp, \tmp, #1
+	msr	mdscr_el1, \tmp
+	isb
+999:
+.endm
+
 /*
  * void cpu_throw(struct thread *old, struct thread *new)
  */
 ENTRY(cpu_throw)
+	/* Of old == NULL skip disabling stepping */
+	cbz	x0, 1f
+
+	/* If we were single stepping, disable it */
+	ldr	x4, [x0, #TD_PCB]
+	ldr	w5, [x4, #PCB_FLAGS]
+	clear_step_flag w5, x6
+1:
+
 #ifdef VFP
 	/* Backup the new thread pointer around a call to C code */
 	mov	x19, x1
@@ -69,6 +96,10 @@ ENTRY(cpu_throw)
 	dsb	sy
 	isb
 
+	/* If we are single stepping, enable it */
+	ldr	w5, [x4, #PCB_FLAGS]
+	set_step_flag w5, x6
+
 	/* Restore the registers */
 	ldp	x5, x6, [x4, #PCB_SP]
 	mov	sp, x5
@@ -127,6 +158,10 @@ ENTRY(cpu_switch)
 	mrs	x6, tpidr_el0
 	stp	x5, x6, [x4, #PCB_SP]
 
+	/* If we were single stepping, disable it */
+	ldr	w5, [x4, #PCB_FLAGS]
+	clear_step_flag w5, x6
+
 #ifdef VFP
 	mov	x19, x0
 	mov	x20, x1
@@ -174,6 +209,10 @@ ENTRY(cpu_switch)
 	b.eq	1b
 #endif
 
+	/* If we are single stepping, enable it */
+	ldr	w5, [x4, #PCB_FLAGS]
+	set_step_flag w5, x6
+
 	/* Restore the registers */
 	ldp	x5, x6, [x4, #PCB_SP]
 	mov	sp, x5

Modified: head/sys/arm64/arm64/trap.c
==============================================================================
--- head/sys/arm64/arm64/trap.c	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/arm64/trap.c	Tue Feb  2 10:28:56 2016	(r295142)
@@ -138,7 +138,6 @@ svc_handler(struct trapframe *frame)
 	int error;
 
 	td = curthread;
-	td->td_frame = frame;
 
 	error = syscallenter(td, &sa);
 	syscallret(td, error, &sa);
@@ -338,6 +337,9 @@ do_el0_sync(struct trapframe *frame)
 	    ("Invalid pcpu address from userland: %p (tpidr %lx)",
 	     get_pcpu(), READ_SPECIALREG(tpidr_el1)));
 
+	td = curthread;
+	td->td_frame = frame;
+
 	esr = READ_SPECIALREG(esr_el1);
 	exception = ESR_ELx_EXCEPTION(esr);
 	switch (exception) {
@@ -373,15 +375,22 @@ do_el0_sync(struct trapframe *frame)
 		el0_excp_unknown(frame);
 		break;
 	case EXCP_PC_ALIGN:
-		td = curthread;
 		call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr);
 		userret(td, frame);
 		break;
 	case EXCP_BRK:
-		td = curthread;
 		call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr);
 		userret(td, frame);
 		break;
+	case EXCP_SOFTSTP_EL0:
+		td->td_frame->tf_spsr &= ~PSR_SS;
+		td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
+		WRITE_SPECIALREG(MDSCR_EL1,
+		    READ_SPECIALREG(MDSCR_EL1) & ~DBG_MDSCR_SS);
+		call_trapsignal(td, SIGTRAP, TRAP_TRACE,
+		    (void *)frame->tf_elr);
+		userret(td, frame);
+		break;
 	default:
 		print_registers(frame);
 		panic("Unknown userland exception %x esr_el1 %lx\n", exception,

Modified: head/sys/arm64/include/armreg.h
==============================================================================
--- head/sys/arm64/include/armreg.h	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/include/armreg.h	Tue Feb  2 10:28:56 2016	(r295142)
@@ -101,6 +101,7 @@
 #define	 EXCP_SP_ALIGN		0x26	/* SP slignment fault */
 #define	 EXCP_TRAP_FP		0x2c	/* Trapped FP exception */
 #define	 EXCP_SERROR		0x2f	/* SError interrupt */
+#define	 EXCP_SOFTSTP_EL0	0x32	/* Software Step, from lower EL */
 #define	 EXCP_SOFTSTP_EL1	0x33	/* Software Step, from same EL */
 #define	 EXCP_WATCHPT_EL1	0x35	/* Watchpoint, from same EL */
 #define	 EXCP_BRK		0x3c	/* Breakpoint */

Modified: head/sys/arm64/include/pcb.h
==============================================================================
--- head/sys/arm64/include/pcb.h	Tue Feb  2 10:17:51 2016	(r295141)
+++ head/sys/arm64/include/pcb.h	Tue Feb  2 10:28:56 2016	(r295142)
@@ -45,6 +45,10 @@ struct pcb {
 	/* Fault handler, the error value is passed in x0 */
 	vm_offset_t	pcb_onfault;
 
+	u_int		pcb_flags;
+#define	PCB_SINGLE_STEP_SHIFT	0
+#define	PCB_SINGLE_STEP		(1 << PCB_SINGLE_STEP_SHIFT)
+
 	/* Place last to simplify the asm to access the rest if the struct */
 	__uint128_t	pcb_vfp[32];
 	uint32_t	pcb_fpcr;


More information about the svn-src-all mailing list