Module Name: src Committed By: matt Date: Tue Aug 16 06:58:16 UTC 2011
Modified Files: src/sys/arch/mips/conf: files.mips src/sys/arch/mips/include: cpu.h mipsNN.h pcb.h reg.h regnum.h trap.h types.h src/sys/arch/mips/mips: cpu_subr.c mips_fpu.c mips_machdep.c trap.c Added Files: src/sys/arch/mips/mips: mips_dsp.c Log Message: Add support for the MIPS DSP ASE (as a second PCU). To generate a diff of this commit: cvs rdiff -u -r1.71 -r1.72 src/sys/arch/mips/conf/files.mips cvs rdiff -u -r1.104 -r1.105 src/sys/arch/mips/include/cpu.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/mips/include/mipsNN.h cvs rdiff -u -r1.23 -r1.24 src/sys/arch/mips/include/pcb.h cvs rdiff -u -r1.14 -r1.15 src/sys/arch/mips/include/reg.h cvs rdiff -u -r1.10 -r1.11 src/sys/arch/mips/include/regnum.h cvs rdiff -u -r1.17 -r1.18 src/sys/arch/mips/include/trap.h cvs rdiff -u -r1.52 -r1.53 src/sys/arch/mips/include/types.h cvs rdiff -u -r1.13 -r1.14 src/sys/arch/mips/mips/cpu_subr.c cvs rdiff -u -r0 -r1.1 src/sys/arch/mips/mips/mips_dsp.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/mips/mips/mips_fpu.c cvs rdiff -u -r1.245 -r1.246 src/sys/arch/mips/mips/mips_machdep.c cvs rdiff -u -r1.231 -r1.232 src/sys/arch/mips/mips/trap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/conf/files.mips diff -u src/sys/arch/mips/conf/files.mips:1.71 src/sys/arch/mips/conf/files.mips:1.72 --- src/sys/arch/mips/conf/files.mips:1.71 Sun Jul 31 15:39:28 2011 +++ src/sys/arch/mips/conf/files.mips Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -# $NetBSD: files.mips,v 1.71 2011/07/31 15:39:28 matt Exp $ +# $NetBSD: files.mips,v 1.72 2011/08/16 06:58:15 matt Exp $ # defflag opt_cputype.h NOFPU FPEMUL @@ -47,6 +47,7 @@ file arch/mips/mips/pmap_tlb.c file arch/mips/mips/trap.c # trap handlers file arch/mips/mips/syscall.c # syscall entries +file arch/mips/mips/mips_dsp.c mips32r2 | mips64r2 file arch/mips/mips/mips_fixup.c file arch/mips/mips/mips_fpu.c file arch/mips/mips/mips_machdep.c Index: src/sys/arch/mips/include/cpu.h diff -u src/sys/arch/mips/include/cpu.h:1.104 src/sys/arch/mips/include/cpu.h:1.105 --- src/sys/arch/mips/include/cpu.h:1.104 Sun Jul 31 15:36:28 2011 +++ src/sys/arch/mips/include/cpu.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.104 2011/07/31 15:36:28 matt Exp $ */ +/* $NetBSD: cpu.h,v 1.105 2011/08/16 06:58:15 matt Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -104,6 +104,8 @@ volatile u_int ci_softints; struct evcnt ci_ev_fpu_loads; /* fpu load counter */ struct evcnt ci_ev_fpu_saves; /* fpu save counter */ + struct evcnt ci_ev_dsp_loads; /* dsp load counter */ + struct evcnt ci_ev_dsp_saves; /* dsp save counter */ struct evcnt ci_ev_tlbmisses; /* @@ -282,6 +284,7 @@ #define CPU_MIPS_HAVE_MxCR 0x2000 /* have mfcr, mtcr insns */ #define CPU_MIPS_LOONGSON2 0x4000 #define MIPS_NOT_SUPP 0x8000 +#define CPU_MIPS_HAVE_DSP 0x10000 #endif /* !_LOCORE */ @@ -300,6 +303,7 @@ # define MIPS_HAS_CLOCK 0 # define MIPS_HAS_LLSC 0 # define MIPS_HAS_LLADDR 0 +# define MIPS_HAS_DSP 0 #elif defined(MIPS3) || defined(MIPS4) @@ -322,6 +326,7 @@ # define MIPS_HAS_LLSC (mips_options.mips_has_llsc) # endif /* _LOCORE */ # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP 0 #elif defined(MIPS32) @@ -336,6 +341,7 @@ # define MIPS_HAS_CLOCK 1 # define MIPS_HAS_LLSC 1 # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP 0 #elif defined(MIPS32R2) @@ -350,6 +356,7 @@ # define MIPS_HAS_CLOCK 1 # define MIPS_HAS_LLSC 1 # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) #elif defined(MIPS64) @@ -364,6 +371,7 @@ # define MIPS_HAS_CLOCK 1 # define MIPS_HAS_LLSC 1 # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP 0 #elif defined(MIPS64R2) @@ -378,6 +386,7 @@ # define MIPS_HAS_CLOCK 1 # define MIPS_HAS_LLSC 1 # define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) #endif @@ -388,6 +397,7 @@ #define MIPS_HAS_R4K_MMU (mips_options.mips_has_r4k_mmu) #define MIPS_HAS_LLSC (mips_options.mips_has_llsc) #define MIPS_HAS_LLADDR ((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0) +# define MIPS_HAS_DSP (mips_options.mips_cpu_flags & CPU_MIPS_HAVE_DSP) /* This test is ... rather bogus */ #define CPUISMIPS3 ((mips_options.mips_cpu_arch & \ @@ -621,12 +631,21 @@ void netintr(void); int kdbpeek(vaddr_t); +/* mips_dsp.c */ +void dsp_init(void); +void dsp_discard(void); +void dsp_load(void); +void dsp_save(void); +bool dsp_used_p(void); +extern const pcu_ops_t mips_dsp_ops; + /* mips_fpu.c */ void fpu_init(void); void fpu_discard(void); void fpu_load(void); void fpu_save(void); bool fpu_used_p(void); +extern const pcu_ops_t mips_fpu_ops; /* mips_machdep.c */ void dumpsys(void); Index: src/sys/arch/mips/include/mipsNN.h diff -u src/sys/arch/mips/include/mipsNN.h:1.4 src/sys/arch/mips/include/mipsNN.h:1.5 --- src/sys/arch/mips/include/mipsNN.h:1.4 Mon Mar 20 18:31:29 2006 +++ src/sys/arch/mips/include/mipsNN.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mipsNN.h,v 1.4 2006/03/20 18:31:29 gdamore Exp $ */ +/* $NetBSD: mipsNN.h,v 1.5 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright 2000, 2001 @@ -233,7 +233,13 @@ /* "M" (R): Configuration Register 4 present. */ #define MIPSNN_CFG3_M 0x80000000 -/* "DSPP" (R): DSPP ASE extension present. */ +/* "ULRP" (R): UserLocal register is implemented. */ +#define MIPSNN_CFG3_ULRP 0x00002000 + +/* "DSP2P" (R): DSP v2 ASE extension present. */ +#define MIPSNN_CFG3_DSP2P 0x00000800 + +/* "DSPP" (R): DSP ASE extension present. */ #define MIPSNN_CFG3_DSPP 0x00000400 /* "LPA" (R): Large physical addresses implemented. (MIPS64 rev 2 only). */ Index: src/sys/arch/mips/include/pcb.h diff -u src/sys/arch/mips/include/pcb.h:1.23 src/sys/arch/mips/include/pcb.h:1.24 --- src/sys/arch/mips/include/pcb.h:1.23 Sun Feb 20 07:45:47 2011 +++ src/sys/arch/mips/include/pcb.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pcb.h,v 1.23 2011/02/20 07:45:47 matt Exp $ */ +/* $NetBSD: pcb.h,v 1.24 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -60,6 +60,7 @@ void * pcb_onfault; /* for copyin/copyout faults */ uint32_t pcb_ppl; /* previous priority level */ struct fpreg pcb_fpregs; /* saved floating point registers */ + struct dspreg pcb_dspregs; /* saved DSP registers */ struct pcb_faultinfo pcb_faultinfo; }; Index: src/sys/arch/mips/include/reg.h diff -u src/sys/arch/mips/include/reg.h:1.14 src/sys/arch/mips/include/reg.h:1.15 --- src/sys/arch/mips/include/reg.h:1.14 Tue Feb 8 20:20:19 2011 +++ src/sys/arch/mips/include/reg.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: reg.h,v 1.14 2011/02/08 20:20:19 rmind Exp $ */ +/* $NetBSD: reg.h,v 1.15 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -50,6 +50,10 @@ mips_fpreg_t r_regs[33]; }; +struct dspreg { + mips_reg_t r_regs[8]; +}; + #if defined(__mips_n32) || defined(__mips_n64) struct fpreg_oabi { int32_t r_regs[33]; Index: src/sys/arch/mips/include/regnum.h diff -u src/sys/arch/mips/include/regnum.h:1.10 src/sys/arch/mips/include/regnum.h:1.11 --- src/sys/arch/mips/include/regnum.h:1.10 Tue Feb 8 20:20:19 2011 +++ src/sys/arch/mips/include/regnum.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: regnum.h,v 1.10 2011/02/08 20:20:19 rmind Exp $ */ +/* $NetBSD: regnum.h,v 1.11 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -108,7 +108,7 @@ #define _R_CAUSE 36 #define _R_PC 37 -#define _FPBASE 38 +#define _FPBASE (_R_PC + 1) #define _R_F0 (_FPBASE+0) #define _R_F1 (_FPBASE+1) #define _R_F2 (_FPBASE+2) @@ -142,3 +142,12 @@ #define _R_F30 (_FPBASE+30) #define _R_F31 (_FPBASE+31) #define _R_FSR (_FPBASE+32) + +#define _R_DSPBASE (_R_FSR + 1) +#define _R_MULLO1 (_R_DSPBASE + 0) +#define _R_MULHI1 (_R_DSPBASE + 1) +#define _R_MULLO2 (_R_DSPBASE + 2) +#define _R_MULHI2 (_R_DSPBASE + 3) +#define _R_MULLO3 (_R_DSPBASE + 4) +#define _R_MULHI3 (_R_DSPBASE + 5) +#define _R_DSPCTL (_R_DSPBASE + 6) Index: src/sys/arch/mips/include/trap.h diff -u src/sys/arch/mips/include/trap.h:1.17 src/sys/arch/mips/include/trap.h:1.18 --- src/sys/arch/mips/include/trap.h:1.17 Sun Feb 20 07:45:47 2011 +++ src/sys/arch/mips/include/trap.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.h,v 1.17 2011/02/20 07:45:47 matt Exp $ */ +/* $NetBSD: trap.h,v 1.18 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -66,6 +66,7 @@ #define T_VCEI 14 /* Virtual coherency exception */ #define T_FPE 15 /* Floating point exception */ #define T_WATCH 23 /* Watch address reference */ +#define T_DSP 26 /* DSP exception */ #define T_VCED 31 /* Virtual coherency data */ #define T_USER 0x20 /* user-mode flag or'ed with type */ Index: src/sys/arch/mips/include/types.h diff -u src/sys/arch/mips/include/types.h:1.52 src/sys/arch/mips/include/types.h:1.53 --- src/sys/arch/mips/include/types.h:1.52 Sun Jun 12 03:35:44 2011 +++ src/sys/arch/mips/include/types.h Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: types.h,v 1.52 2011/06/12 03:35:44 rmind Exp $ */ +/* $NetBSD: types.h,v 1.53 2011/08/16 06:58:15 matt Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -127,7 +127,8 @@ #if defined(_KERNEL) || defined(_KMEMUSER) #define PCU_FPU 0 -#define PCU_UNIT_COUNT 1 +#define PCU_DSP 1 +#define PCU_UNIT_COUNT 2 #endif typedef __uint64_t __cpuset_t; Index: src/sys/arch/mips/mips/cpu_subr.c diff -u src/sys/arch/mips/mips/cpu_subr.c:1.13 src/sys/arch/mips/mips/cpu_subr.c:1.14 --- src/sys/arch/mips/mips/cpu_subr.c:1.13 Mon May 2 00:29:54 2011 +++ src/sys/arch/mips/mips/cpu_subr.c Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu_subr.c,v 1.13 2011/05/02 00:29:54 rmind Exp $ */ +/* $NetBSD: cpu_subr.c,v 1.14 2011/08/16 06:58:15 matt Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.13 2011/05/02 00:29:54 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.14 2011/08/16 06:58:15 matt Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -90,6 +90,13 @@ #endif }; +const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = { + [PCU_FPU] = &mips_fpu_ops, +#if (MIPS32R2 + MIPS64R2) > 0 + [PCU_DSP] = &mips_dsp_ops, +#endif +}; + #ifdef MULTIPROCESSOR volatile __cpuset_t cpus_running = 1; @@ -231,6 +238,12 @@ evcnt_attach_dynamic(&ci->ci_ev_fpu_saves, EVCNT_TYPE_MISC, NULL, xname, "fpu saves"); + evcnt_attach_dynamic(&ci->ci_ev_dsp_loads, + EVCNT_TYPE_MISC, NULL, xname, + "dsp loads"); + evcnt_attach_dynamic(&ci->ci_ev_dsp_saves, + EVCNT_TYPE_MISC, NULL, xname, + "dsp saves"); evcnt_attach_dynamic(&ci->ci_ev_tlbmisses, EVCNT_TYPE_TRAP, NULL, xname, "tlb misses"); Index: src/sys/arch/mips/mips/mips_fpu.c diff -u src/sys/arch/mips/mips/mips_fpu.c:1.5 src/sys/arch/mips/mips/mips_fpu.c:1.6 --- src/sys/arch/mips/mips/mips_fpu.c:1.5 Mon May 2 00:29:54 2011 +++ src/sys/arch/mips/mips/mips_fpu.c Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mips_fpu.c,v 1.5 2011/05/02 00:29:54 rmind Exp $ */ +/* $NetBSD: mips_fpu.c,v 1.6 2011/08/16 06:58:15 matt Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mips_fpu.c,v 1.5 2011/05/02 00:29:54 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_fpu.c,v 1.6 2011/08/16 06:58:15 matt Exp $"); #include "opt_multiprocessor.h" @@ -50,18 +50,13 @@ static void mips_fpu_state_load(lwp_t *, bool); static void mips_fpu_state_release(lwp_t *); -static const pcu_ops_t mips_fpu_ops = { +const pcu_ops_t mips_fpu_ops = { .pcu_id = PCU_FPU, .pcu_state_save = mips_fpu_state_save, .pcu_state_load = mips_fpu_state_load, .pcu_state_release = mips_fpu_state_release }; -/* XXX */ -const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = { - [PCU_FPU] = &mips_fpu_ops -}; - void fpu_discard(void) { Index: src/sys/arch/mips/mips/mips_machdep.c diff -u src/sys/arch/mips/mips/mips_machdep.c:1.245 src/sys/arch/mips/mips/mips_machdep.c:1.246 --- src/sys/arch/mips/mips/mips_machdep.c:1.245 Sun Jul 31 15:39:29 2011 +++ src/sys/arch/mips/mips/mips_machdep.c Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mips_machdep.c,v 1.245 2011/07/31 15:39:29 matt Exp $ */ +/* $NetBSD: mips_machdep.c,v 1.246 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -112,7 +112,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.245 2011/07/31 15:39:29 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.246 2011/08/16 06:58:15 matt Exp $"); #define __INTR_PRIVATE #include "opt_cputype.h" @@ -883,10 +883,23 @@ mips32r2_intr_end - mips32r2_tlb_miss); /* + * Let see if this cpu has DSP V2 ASE... + */ + uint32_t cp0flags = mips_options.mips_cpu->cpu_cp0flags; + if (mipsNN_cp0_config2_read() & MIPSNN_CFG2_M) { + const uint32_t cfg3 = mipsNN_cp0_config3_read(); + if (cfg3 & MIPSNN_CFG3_ULRP) { + cp0flags |= MIPS_CP0FL_USERLOCAL; + } + if (cfg3 & MIPSNN_CFG3_DSP2P) { + mips_options.mips_cpu_flags |= CPU_MIPS_HAVE_DSP; + } + } + /* * If this CPU doesn't have a COP0 USERLOCAL register, at the end * of cpu_switch resume overwrite the instructions which update it. */ - if (!(mips_options.mips_cpu->cpu_cp0flags & MIPS_CP0FL_USERLOCAL)) { + if (!(cp0flags & MIPS_CP0FL_USERLOCAL)) { extern uint32_t mips32r2_cpu_switch_resume[]; for (uint32_t *insnp = mips32r2_cpu_switch_resume;; insnp++) { KASSERT(insnp[0] != JR_RA); @@ -1010,10 +1023,24 @@ mips64r2_intr_end - mips64r2_tlb_miss); /* + * Let see if this cpu has DSP V2 ASE... + */ + uint32_t cp0flags = mips_options.mips_cpu->cpu_cp0flags; + if (mipsNN_cp0_config2_read() & MIPSNN_CFG2_M) { + const uint32_t cfg3 = mipsNN_cp0_config3_read(); + if (cfg3 & MIPSNN_CFG3_ULRP) { + cp0flags |= MIPS_CP0FL_USERLOCAL; + } + if (cfg3 & MIPSNN_CFG3_DSP2P) { + mips_options.mips_cpu_flags |= CPU_MIPS_HAVE_DSP; + } + } + + /* * If this CPU doesn't have a COP0 USERLOCAL register, at the end * of cpu_switch resume overwrite the instructions which update it. */ - if (!(mips_options.mips_cpu->cpu_cp0flags & MIPS_CP0FL_USERLOCAL)) { + if (!(cp0flags & MIPS_CP0FL_USERLOCAL)) { extern uint32_t mips64r2_cpu_switch_resume[]; for (uint32_t *insnp = mips64r2_cpu_switch_resume;; insnp++) { KASSERT(insnp[0] != JR_RA); @@ -1409,6 +1436,9 @@ else aprint_normal(" Rev. %d", MIPS_PRID_REV(fpu_id)); } + if (opts->mips_cpu_flags & MIPS_HAS_DSP) { + aprint_normal(" and DSPv2"); + } aprint_normal("\n"); if (MIPS_PRID_CID(cpu_id) == MIPS_PRID_CID_PREHISTORIC && Index: src/sys/arch/mips/mips/trap.c diff -u src/sys/arch/mips/mips/trap.c:1.231 src/sys/arch/mips/mips/trap.c:1.232 --- src/sys/arch/mips/mips/trap.c:1.231 Fri Apr 29 22:08:17 2011 +++ src/sys/arch/mips/mips/trap.c Tue Aug 16 06:58:15 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.231 2011/04/29 22:08:17 matt Exp $ */ +/* $NetBSD: trap.c,v 1.232 2011/08/16 06:58:15 matt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.231 2011/04/29 22:08:17 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.232 2011/08/16 06:58:15 matt Exp $"); #include "opt_cputype.h" /* which mips CPU levels do we support? */ #include "opt_ddb.h" @@ -111,7 +111,7 @@ "r4k watch", "mipsNN machine check", "reserved 25", - "reserved 26", + "DSP exception", "reserved 27", "reserved 28", "reserved 29", @@ -599,6 +599,15 @@ ksi.ksi_code = TRAP_BRKPT; break; /* SIGNAL */ } + case T_DSP+T_USER: +#if (MIPS32R2 + MIPS64R2) > 0 + if (MIPS_HAS_DSP) { + dsp_load(); + userret(l); + return; /* GEN */ + } +#endif /* (MIPS32R3 + MIPS64R2) > 0 */ + /* FALLTHROUGH */ case T_RES_INST+T_USER: case T_COP_UNUSABLE+T_USER: #if !defined(FPEMUL) && !defined(NOFPU) Added files: Index: src/sys/arch/mips/mips/mips_dsp.c diff -u /dev/null src/sys/arch/mips/mips/mips_dsp.c:1.1 --- /dev/null Tue Aug 16 06:58:16 2011 +++ src/sys/arch/mips/mips/mips_dsp.c Tue Aug 16 06:58:15 2011 @@ -0,0 +1,200 @@ +/* $NetBSD: mips_dsp.c,v 1.1 2011/08/16 06:58:15 matt Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: mips_dsp.c,v 1.1 2011/08/16 06:58:15 matt Exp $"); + +#include "opt_multiprocessor.h" + +#include <sys/param.h> +#include <sys/mutex.h> +#include <sys/condvar.h> +#include <sys/cpu.h> +#include <sys/proc.h> +#include <sys/lwp.h> +#include <sys/pcu.h> + +#include <mips/locore.h> +#include <mips/regnum.h> +#include <mips/pcb.h> + +static void mips_dsp_state_save(lwp_t *); +static void mips_dsp_state_load(lwp_t *, bool); +static void mips_dsp_state_release(lwp_t *); + +const pcu_ops_t mips_dsp_ops = { + .pcu_id = PCU_DSP, + .pcu_state_save = mips_dsp_state_save, + .pcu_state_load = mips_dsp_state_load, + .pcu_state_release = mips_dsp_state_release +}; + +void +dsp_discard(void) +{ + pcu_discard(&mips_dsp_ops); +} + +void +dsp_load(void) +{ + pcu_load(&mips_dsp_ops); +} + +void +dsp_save(void) +{ + pcu_save(&mips_dsp_ops); +} + +bool +dsp_used_p(void) +{ + return pcu_used_p(&mips_dsp_ops); +} + +void +mips_dsp_state_save(lwp_t *l) +{ + struct trapframe * const tf = l->l_md.md_utf; + struct pcb * const pcb = lwp_getpcb(l); + mips_reg_t * const dsp = pcb->pcb_dspregs.r_regs; + uint32_t status; + + /* + * Don't do anything if the DSP is already off. + */ + if ((tf->tf_regs[_R_SR] & MIPS_SR_MX) == 0) + return; + + l->l_cpu->ci_ev_dsp_saves.ev_count++; + + /* + * load DSP registers and establish lwp's DSP context. + */ + __asm volatile ( + ".set push" "\n\t" + ".set mips32r2" "\n\t" + ".set dspr2" "\n\t" + ".set noat" "\n\t" + ".set noreorder" "\n\t" + "mfc0 %[status], $%[cp0_status]" "\n\t" + "or %[status], %[mips_sr_mx]" "\n\t" + "mtc0 %[status], $%[cp0_status]" "\n\t" + "ehb" "\n\t" + "mflo %[mullo1], $ac1" "\n\t" + "mfhi %[mulhi1], $ac1" "\n\t" + "mflo %[mullo2], $ac2" "\n\t" + "mfhi %[mulhi2], $ac2" "\n\t" + "mflo %[mullo3], $ac3" "\n\t" + "mfhi %[mulhi3], $ac3" "\n\t" + "rddsp %[dspctl]" "\n\t" + "xor %[status], %[mips_sr_mx]" "\n\t" + "mtc0 %[status], $%[cp0_status]" "\n\t" + "ehb" "\n\t" + ".set pop" + : [status] "=&r" (status), + [mullo1] "=r"(dsp[_R_MULLO1 - _R_DSPBASE]), + [mulhi1] "=r"(dsp[_R_MULHI1 - _R_DSPBASE]), + [mullo2] "=r"(dsp[_R_MULLO2 - _R_DSPBASE]), + [mulhi2] "=r"(dsp[_R_MULHI2 - _R_DSPBASE]), + [mullo3] "=r"(dsp[_R_MULLO3 - _R_DSPBASE]), + [mulhi3] "=r"(dsp[_R_MULHI3 - _R_DSPBASE]), + [dspctl] "=r"(dsp[_R_DSPCTL - _R_DSPBASE]) + : [mips_sr_mx] "r"(MIPS_SR_MX), + [cp0_status] "n"(MIPS_COP_0_STATUS)); +} + +void +mips_dsp_state_load(lwp_t *l, bool used) +{ + struct trapframe * const tf = l->l_md.md_utf; + struct pcb * const pcb = lwp_getpcb(l); + mips_reg_t * const dsp = pcb->pcb_dspregs.r_regs; + uint32_t status; + + l->l_cpu->ci_ev_dsp_loads.ev_count++; + + /* + * If this is the first time the state is being loaded, zero it first. + */ + if (__predict_false(!used)) { + memset(&pcb->pcb_dspregs, 0, sizeof(pcb->pcb_dspregs)); + } + + /* + * Enable the DSP when this lwp return to userspace. + */ + tf->tf_regs[_R_SR] |= MIPS_SR_MX; + + /* + * load DSP registers and establish lwp's DSP context. + */ + __asm volatile ( + ".set push" "\n\t" + ".set mips32r2" "\n\t" + ".set dspr2" "\n\t" + ".set noat" "\n\t" + ".set noreorder" "\n\t" + "mfc0 %[status], $%[cp0_status]" "\n\t" + "or %[status], %[mips_sr_mx]" "\n\t" + "mtc0 %[status], $%[cp0_status]" "\n\t" + "ehb" "\n\t" + "mtlo %[mullo1], $ac1" "\n\t" + "mthi %[mulhi1], $ac1" "\n\t" + "mtlo %[mullo2], $ac2" "\n\t" + "mthi %[mulhi2], $ac2" "\n\t" + "mtlo %[mullo3], $ac3" "\n\t" + "mthi %[mulhi3], $ac3" "\n\t" + "wrdsp %[dspctl]" "\n\t" + "xor %[status], %[mips_sr_mx]" "\n\t" + "mtc0 %[status], $%[cp0_status]" "\n\t" + "ehb" "\n\t" + ".set pop" + : [status] "=&r" (status) + : [mullo1] "r"(dsp[_R_MULLO1 - _R_DSPBASE]), + [mulhi1] "r"(dsp[_R_MULHI1 - _R_DSPBASE]), + [mullo2] "r"(dsp[_R_MULLO2 - _R_DSPBASE]), + [mulhi2] "r"(dsp[_R_MULHI2 - _R_DSPBASE]), + [mullo3] "r"(dsp[_R_MULLO3 - _R_DSPBASE]), + [mulhi3] "r"(dsp[_R_MULHI3 - _R_DSPBASE]), + [dspctl] "r"(dsp[_R_DSPCTL - _R_DSPBASE]), + [mips_sr_mx] "r"(MIPS_SR_MX), + [cp0_status] "n"(MIPS_COP_0_STATUS)); +} + +void +mips_dsp_state_release(lwp_t *l) +{ + + KASSERT(l == curlwp); + l->l_md.md_utf->tf_regs[_R_SR] &= ~MIPS_SR_MX; +}