svn commit: r346790 - in head/sys/powerpc: include powerpc

Justin Hibbits jhibbits at FreeBSD.org
Sat Apr 27 16:28:37 UTC 2019


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;


More information about the svn-src-all mailing list