Author: jhibbits
Date: Fri Apr 20 03:19:44 2018
New Revision: 332807
URL: https://svnweb.freebsd.org/changeset/base/332807

Log:
  powerpc64: Add DSCR support
  
  Summary:
  Powerpc64 has support for a register called Data Stream Control Register
  (DSCR), which basically controls how the hardware controls the caching and
  prefetch for stream operations.
  
  Since mfdscr and mtdscr are privileged instructions, we need to emulate them,
  and
  keep the custom DSCR configuration per thread.
  
  The purpose of this feature is to change DSCR depending on the operation, set
  to DSCR Default Prefetch Depth to deepest on string operations, as memcpy.
  
  Submitted by: Breno Leitao
  Differential Revision: https://reviews.freebsd.org/D15081

Modified:
  head/sys/powerpc/include/pcb.h
  head/sys/powerpc/include/spr.h
  head/sys/powerpc/powerpc/exec_machdep.c
  head/sys/powerpc/powerpc/genassym.c
  head/sys/powerpc/powerpc/swtch64.S

Modified: head/sys/powerpc/include/pcb.h
==============================================================================
--- head/sys/powerpc/include/pcb.h      Fri Apr 20 03:11:51 2018        
(r332806)
+++ head/sys/powerpc/include/pcb.h      Fri Apr 20 03:19:44 2018        
(r332807)
@@ -46,14 +46,16 @@ struct pcb {
        register_t      pcb_sp;                 /* stack pointer */
        register_t      pcb_toc;                /* toc pointer */
        register_t      pcb_lr;                 /* link register */
+       register_t      pcb_dscr;               /* dscr value */
        struct          pmap *pcb_pm;           /* pmap of our vmspace */
        jmp_buf         *pcb_onfault;           /* For use during
                                                    copyin/copyout */
        int             pcb_flags;
-#define        PCB_FPU         1       /* Process uses FPU */
-#define        PCB_FPREGS      2       /* Process had FPU registers 
initialized */
-#define        PCB_VEC         4       /* Process had Altivec initialized */
-#define        PCB_VSX         8       /* Process had VSX initialized */
+#define        PCB_FPU         0x1     /* Process uses FPU */
+#define        PCB_FPREGS      0x2     /* Process had FPU registers 
initialized */
+#define        PCB_VEC         0x4     /* Process had Altivec initialized */
+#define        PCB_VSX         0x8     /* Process had VSX initialized */
+#define        PCB_CDSCR       0x10    /* Process had Custom DSCR initialized 
*/
        struct fpu {
                union {
                        double fpr;

Modified: head/sys/powerpc/include/spr.h
==============================================================================
--- head/sys/powerpc/include/spr.h      Fri Apr 20 03:11:51 2018        
(r332806)
+++ head/sys/powerpc/include/spr.h      Fri Apr 20 03:19:44 2018        
(r332807)
@@ -97,6 +97,7 @@
 #define        SPR_RTCL_R              0x005   /* .6. 601 RTC Lower - Read */
 #define        SPR_LR                  0x008   /* 468 Link Register */
 #define        SPR_CTR                 0x009   /* 468 Count Register */
+#define        SPR_DSCR                0x011   /* Data Stream Control Register 
*/
 #define        SPR_DSISR               0x012   /* .68 DSI exception source */
 #define          DSISR_DIRECT            0x80000000 /* Direct-store error 
exception */
 #define          DSISR_NOTFOUND          0x40000000 /* Translation not found */

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c     Fri Apr 20 03:11:51 2018        
(r332806)
+++ head/sys/powerpc/powerpc/exec_machdep.c     Fri Apr 20 03:19:44 2018        
(r332807)
@@ -1021,11 +1021,46 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *
        td->td_retval[1] = 0;
 }
 
+static int
+emulate_mfspr(int spr, int reg, struct trapframe *frame){
+       struct thread *td;
+
+       td = curthread;
+
+       if (spr == SPR_DSCR) {
+               // If DSCR was never set, get the default DSCR
+               if ((td->td_pcb->pcb_flags & PCB_CDSCR) == 0)
+                       td->td_pcb->pcb_dscr = mfspr(SPR_DSCR);
+
+               frame->fixreg[reg] = td->td_pcb->pcb_dscr;
+               frame->srr0 += 4;
+               return 0;
+       } else
+               return SIGILL;
+}
+
+static int
+emulate_mtspr(int spr, int reg, struct trapframe *frame){
+       struct thread *td;
+
+       td = curthread;
+
+       if (spr == SPR_DSCR) {
+               td->td_pcb->pcb_flags |= PCB_CDSCR;
+               td->td_pcb->pcb_dscr = frame->fixreg[reg];
+               frame->srr0 += 4;
+               return 0;
+       } else
+               return SIGILL;
+}
+
+#define XFX 0xFC0007FF
 int
 ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
 {
        uint32_t instr;
        int reg, sig;
+       int rs, spr;
 
        instr = fuword32((void *)frame->srr0);
        sig = SIGILL;
@@ -1035,9 +1070,15 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb 
                frame->fixreg[reg] = mfpvr();
                frame->srr0 += 4;
                return (0);
-       }
-
-       if ((instr & 0xfc000ffe) == 0x7c0004ac) {       /* various sync */
+       } else if ((instr & XFX) == 0x7c0002a6) {       /* mfspr */
+               rs = (instr &  0x3e00000) >> 21;
+               spr = (instr & 0x1ff800) >> 16;
+               return emulate_mfspr(spr, rs, frame);
+       } else if ((instr & XFX) == 0x7c0003a6) {       /* mtspr */
+               rs = (instr &  0x3e00000) >> 21;
+               spr = (instr & 0x1ff800) >> 16;
+               return emulate_mtspr(spr, rs, frame);
+       } else if ((instr & 0xfc000ffe) == 0x7c0004ac) {        /* various sync 
*/
                powerpc_sync(); /* Do a heavy-weight sync */
                frame->srr0 += 4;
                return (0);

Modified: head/sys/powerpc/powerpc/genassym.c
==============================================================================
--- head/sys/powerpc/powerpc/genassym.c Fri Apr 20 03:11:51 2018        
(r332806)
+++ head/sys/powerpc/powerpc/genassym.c Fri Apr 20 03:19:44 2018        
(r332807)
@@ -195,6 +195,7 @@ ASSYM(CF_SIZE, sizeof(struct callframe));
 
 ASSYM(PCB_CONTEXT, offsetof(struct pcb, pcb_context));
 ASSYM(PCB_CR, offsetof(struct pcb, pcb_cr));
+ASSYM(PCB_DSCR, offsetof(struct pcb, pcb_dscr));
 ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
 ASSYM(PCB_TOC, offsetof(struct pcb, pcb_toc));
 ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
@@ -202,6 +203,7 @@ ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
 ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
 ASSYM(PCB_FPU, PCB_FPU);
 ASSYM(PCB_VEC, PCB_VEC);
+ASSYM(PCB_CDSCR, PCB_CDSCR);
 
 ASSYM(PCB_AIM_USR_VSID, offsetof(struct pcb, pcb_cpu.aim.usr_vsid));
 ASSYM(PCB_BOOKE_DBCR0, offsetof(struct pcb, pcb_cpu.booke.dbcr0));

Modified: head/sys/powerpc/powerpc/swtch64.S
==============================================================================
--- head/sys/powerpc/powerpc/swtch64.S  Fri Apr 20 03:11:51 2018        
(r332806)
+++ head/sys/powerpc/powerpc/swtch64.S  Fri Apr 20 03:19:44 2018        
(r332807)
@@ -62,6 +62,7 @@
 #include <sys/syscall.h>
 
 #include <machine/trap.h>
+#include <machine/spr.h>
 #include <machine/param.h>
 #include <machine/asm.h>
 
@@ -124,6 +125,14 @@ ENTRY(cpu_switch)
        
        stdu    %r1,-48(%r1)
 
+       lwz     %r7, PCB_FLAGS(%r17)
+       andi.   %r7, %r7, PCB_CDSCR
+       beq     .L0
+       /* Custom DSCR was set. Reseting it to enter kernel */
+       li      %r7, 0x0
+       mtspr   SPR_DSCR, %r7
+
+.L0:
        lwz     %r7,PCB_FLAGS(%r17)
        /* Save FPU context if needed */
        andi.   %r7, %r7, PCB_FPU
@@ -188,10 +197,18 @@ blocked_loop:
        lwz     %r6, PCB_FLAGS(%r17)
        /* Restore Altivec context if needed */
        andi.   %r6, %r6, PCB_VEC
-       beq     .L4
+       beq     .L31
        mr      %r3,%r13                /* Pass curthread to enable_vec */
        bl      enable_vec
        nop
+
+.L31:
+       lwz     %r6, PCB_FLAGS(%r17)
+       /* Restore Custom DSCR if needed */
+       andi.   %r6, %r6, PCB_CDSCR
+       beq     .L4
+       ld      %r6, PCB_DSCR(%r17)     /* Load the DSCR register*/
+       mtspr   SPR_DSCR, %r6
 
        /* thread to restore is in r3 */
 .L4:
_______________________________________________
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