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"

Reply via email to