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