Author: jhibbits
Date: Sat Apr 27 16:28:34 2019
New Revision: 346790
URL: https://svnweb.freebsd.org/changeset/base/346790

Log:
  powerpc64: Add the DSCR facility on POWER8 and later
  
  The Data Stream Control Register (DSCR) is privileged on POWER7, but
  unprivileged (different register) on POWER8 and later.  However, it's now
  guarded by a new register, the Facility Status and Control Register, instead 
of
  the MSR like other pre-existing facilities (FPU, Altivec).  The FSCR must be
  managed explicitly, since it's effectively an extension of the MSR.
  
  Tested by:    Brandon Bergren

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
  head/sys/powerpc/powerpc/trap.c

Modified: head/sys/powerpc/include/pcb.h
==============================================================================
--- head/sys/powerpc/include/pcb.h      Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/include/pcb.h      Sat Apr 27 16:28:34 2019        
(r346790)
@@ -47,6 +47,7 @@ struct pcb {
        register_t      pcb_toc;                /* toc pointer */
        register_t      pcb_lr;                 /* link register */
        register_t      pcb_dscr;               /* dscr value */
+       register_t      pcb_fscr;               
        struct          pmap *pcb_pm;           /* pmap of our vmspace */
        jmp_buf         *pcb_onfault;           /* For use during
                                                    copyin/copyout */
@@ -57,6 +58,7 @@ struct pcb {
 #define        PCB_VSX         0x8     /* Process had VSX initialized */
 #define        PCB_CDSCR       0x10    /* Process had Custom DSCR initialized 
*/
 #define        PCB_HTM         0x20    /* Process had HTM initialized */
+#define        PCB_CFSCR       0x40    /* Process had FSCR updated */
        struct fpu {
                union {
                        double fpr;

Modified: head/sys/powerpc/include/spr.h
==============================================================================
--- head/sys/powerpc/include/spr.h      Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/include/spr.h      Sat Apr 27 16:28:34 2019        
(r346790)
@@ -93,11 +93,12 @@
 
 #define        SPR_MQ                  0x000   /* .6. 601 MQ register */
 #define        SPR_XER                 0x001   /* 468 Fixed Point Exception 
Register */
+#define        SPR_DSCR                0x003   /* .6. Data Stream Control 
Register (Unprivileged) */
 #define        SPR_RTCU_R              0x004   /* .6. 601 RTC Upper - Read */
 #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_DSCRP               0x011   /* Data Stream Control Register 
(Privileged) */
 #define        SPR_DSISR               0x012   /* .68 DSI exception source */
 #define          DSISR_DIRECT            0x80000000 /* Direct-store error 
exception */
 #define          DSISR_NOTFOUND          0x40000000 /* Translation not found */
@@ -135,6 +136,7 @@
 #define          FSCR_IC_STOP            0x0900000000000000ULL /* Access to 
the 'stop' instruction in privileged non-hypervisor state */
 #define          FSCR_IC_MSG             0x0A00000000000000ULL /* Access to 
'msgsndp' or 'msgclrp' instructions */
 #define          FSCR_IC_SCV             0x0C00000000000000ULL /* Execution of 
a 'scv' instruction */
+#define          FSCR_DSCR               0x0000000000000004ULL /* DSCR 
available in PR state */
 #define        SPR_USPRG0              0x100   /* 4.. User SPR General 0 */
 #define        SPR_VRSAVE              0x100   /* .6. AltiVec VRSAVE */
 #define        SPR_SPRG0               0x110   /* 468 SPR General 0 */

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c     Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/powerpc/exec_machdep.c     Sat Apr 27 16:28:34 2019        
(r346790)
@@ -124,6 +124,8 @@ static int  grab_mcontext32(struct thread *td, mcontext
 
 static int     grab_mcontext(struct thread *, mcontext_t *, int);
 
+static void    cleanup_power_extras(struct thread *);
+
 #ifdef __powerpc64__
 extern struct sysentvec elf64_freebsd_sysvec_v2;
 #endif
@@ -506,6 +508,30 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
 }
 
 /*
+ * Clean up extra POWER state.  Some per-process registers and states are not
+ * managed by the MSR, so must be cleaned up explicitly on thread exit.
+ *
+ * Currently this includes:
+ * DSCR -- Data stream control register (PowerISA 2.06+)
+ * FSCR -- Facility Status and Control Register (PowerISA 2.07+)
+ */
+static void
+cleanup_power_extras(struct thread *td)
+{
+       uint32_t pcb_flags;
+
+       if (td != curthread)
+               return;
+
+       pcb_flags = td->td_pcb->pcb_flags;
+       /* Clean up registers not managed by MSR. */
+       if (pcb_flags & PCB_CFSCR)
+               mtspr(SPR_FSCR, 0);
+       if (pcb_flags & PCB_CDSCR) 
+               mtspr(SPR_DSCRP, 0);
+}
+
+/*
  * Set set up registers on exec.
  */
 void
@@ -549,6 +575,7 @@ exec_setregs(struct thread *td, struct image_params *i
        tf->fixreg[12] = imgp->entry_addr;
        #endif
        tf->srr1 = psl_userset | PSL_FE_DFLT;
+       cleanup_power_extras(td);
        td->td_pcb->pcb_flags = 0;
 }
 
@@ -574,6 +601,7 @@ ppc32_setregs(struct thread *td, struct image_params *
 
        tf->srr0 = imgp->entry_addr;
        tf->srr1 = psl_userset32 | PSL_FE_DFLT;
+       cleanup_power_extras(td);
        td->td_pcb->pcb_flags = 0;
 }
 #endif
@@ -912,6 +940,7 @@ cpu_set_syscall_retval(struct thread *td, int error)
 void
 cpu_thread_exit(struct thread *td)
 {
+       cleanup_power_extras(td);
 }
 
 void
@@ -1052,10 +1081,10 @@ emulate_mfspr(int spr, int reg, struct trapframe *fram
 
        td = curthread;
 
-       if (spr == SPR_DSCR) {
+       if (spr == SPR_DSCR || spr == SPR_DSCRP) {
                // 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);
+                       td->td_pcb->pcb_dscr = mfspr(SPR_DSCRP);
 
                frame->fixreg[reg] = td->td_pcb->pcb_dscr;
                frame->srr0 += 4;
@@ -1070,9 +1099,10 @@ emulate_mtspr(int spr, int reg, struct trapframe *fram
 
        td = curthread;
 
-       if (spr == SPR_DSCR) {
+       if (spr == SPR_DSCR || spr == SPR_DSCRP) {
                td->td_pcb->pcb_flags |= PCB_CDSCR;
                td->td_pcb->pcb_dscr = frame->fixreg[reg];
+               mtspr(SPR_DSCRP, frame->fixreg[reg]);
                frame->srr0 += 4;
                return 0;
        } else

Modified: head/sys/powerpc/powerpc/genassym.c
==============================================================================
--- head/sys/powerpc/powerpc/genassym.c Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/powerpc/genassym.c Sat Apr 27 16:28:34 2019        
(r346790)
@@ -196,6 +196,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_FSCR, offsetof(struct pcb, pcb_fscr));
 ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
 ASSYM(PCB_TOC, offsetof(struct pcb, pcb_toc));
 ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
@@ -204,6 +205,7 @@ 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_CFSCR, PCB_CFSCR);
 
 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  Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/powerpc/swtch64.S  Sat Apr 27 16:28:34 2019        
(r346790)
@@ -87,6 +87,10 @@ ENTRY(cpu_throw)
  *                struct mutex *mtx); 
  *
  * Switch to a new thread saving the current state in the old thread.
+ *
+ * Internally clobbers (not visible outside of this file):
+ * r18 - old thread pcb_flags
+ * r19 - new thread pcb_flags
  */
 ENTRY(cpu_switch)
        ld      %r6,TD_PCB(%r3)         /* Get the old thread's PCB ptr */
@@ -126,11 +130,15 @@ ENTRY(cpu_switch)
        stdu    %r1,-48(%r1)
 
        lwz     %r18, PCB_FLAGS(%r17)
+       andi.   %r7, %r18, PCB_CFSCR
+       beq     1f
+       mfspr   %r6, SPR_FSCR
+       std     %r6, PCB_FSCR(%r17)
+1:
        andi.   %r7, %r18, PCB_CDSCR
        beq     .L0
-       /* Custom DSCR was set. Reseting it to enter kernel */
-       li      %r6, 0x0
-       mtspr   SPR_DSCR, %r6
+       mfspr   %r6, SPR_DSCRP
+       std     %r6, PCB_DSCR(%r17)
 
 .L0:
        /* Save FPU context if needed */
@@ -201,11 +209,20 @@ blocked_loop:
        nop
 
 .L31:
-       /* Restore Custom DSCR if needed */
-       andi.   %r6, %r19, PCB_CDSCR
-       beq     .L4
+       /* Load custom DSCR on PowerISA 2.06+ CPUs. */
+       /* Load changed FSCR on PowerISA 2.07+ CPUs. */
+       or      %r18,%r18,%r19
+       /* Restore Custom DSCR if needed (zeroes if in old but not new) */
+       andi.   %r6, %r18, PCB_CDSCR
+       beq     .L32
        ld      %r7, PCB_DSCR(%r17)     /* Load the DSCR register*/
-       mtspr   SPR_DSCR, %r7
+       mtspr   SPR_DSCRP, %r7
+.L32:
+       /* Restore FSCR if needed (zeroes if in old but not new) */
+       andi.   %r6, %r18, PCB_CFSCR
+       beq     .L4
+       ld      %r7, PCB_FSCR(%r17)     /* Load the FSCR register*/
+       mtspr   SPR_FSCR, %r7
 
        /* thread to restore is in r3 */
 .L4:

Modified: head/sys/powerpc/powerpc/trap.c
==============================================================================
--- head/sys/powerpc/powerpc/trap.c     Sat Apr 27 14:59:08 2019        
(r346789)
+++ head/sys/powerpc/powerpc/trap.c     Sat Apr 27 16:28:34 2019        
(r346790)
@@ -307,6 +307,12 @@ trap(struct trapframe *frame)
                        fscr = mfspr(SPR_FSCR);
                        if ((fscr & FSCR_IC_MASK) == FSCR_IC_HTM) {
                                CTR0(KTR_TRAP, "Hardware Transactional Memory 
subsystem disabled");
+                       } else if ((fscr & FSCR_IC_MASK) == FSCR_IC_DSCR) {
+                               td->td_pcb->pcb_flags |= PCB_CFSCR | PCB_CDSCR;
+                               fscr &= ~FSCR_IC_MASK;
+                               mtspr(SPR_FSCR, fscr | FSCR_DSCR);
+                               mtspr(SPR_DSCR, 0);
+                               break;
                        }
                        sig = SIGILL;
                        ucode = ILL_ILLOPC;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to