Date: Sat, 27 Apr 2019 16:28:35 +0000 (UTC) From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r346790 - in head/sys/powerpc: include powerpc Message-ID: <201904271628.x3RGSZh9044693@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904271628.x3RGSZh9044693>