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; _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"