aboutsummaryrefslogtreecommitdiff
path: root/sys/powerpc/aim
diff options
context:
space:
mode:
authorNathan Whitehorn <nwhitehorn@FreeBSD.org>2009-02-20 17:48:40 +0000
committerNathan Whitehorn <nwhitehorn@FreeBSD.org>2009-02-20 17:48:40 +0000
commit1ac37bcb7740a1a29ff6cb1c8108db1833ba4c1f (patch)
treee0e46945b3ee041129a041566c214b45d4b40994 /sys/powerpc/aim
parent9d13a605d4e53ae9c480dbb2eca2c01ce2f425bf (diff)
downloadsrc-1ac37bcb7740a1a29ff6cb1c8108db1833ba4c1f.tar.gz
src-1ac37bcb7740a1a29ff6cb1c8108db1833ba4c1f.zip
Add Altivec support for supported CPUs. This is derived from the FPU support
code, and also reducing the size of trapcode to fit inside a 32 byte handler slot. Reviewed by: grehan MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=188860
Diffstat (limited to 'sys/powerpc/aim')
-rw-r--r--sys/powerpc/aim/machdep.c32
-rw-r--r--sys/powerpc/aim/swtch.S22
-rw-r--r--sys/powerpc/aim/trap.c17
-rw-r--r--sys/powerpc/aim/trap_subr.S113
4 files changed, 130 insertions, 54 deletions
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 2199cb136c3b..da8f35f7f3b3 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -103,6 +103,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
+#include <machine/altivec.h>
#include <machine/bat.h>
#include <machine/cpu.h>
#include <machine/elf.h>
@@ -238,7 +239,6 @@ extern void *dsitrap, *dsisize;
extern void *decrint, *decrsize;
extern void *extint, *extsize;
extern void *dblow, *dbsize;
-extern void *vectrap, *vectrapsize;
u_int
powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
@@ -340,7 +340,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize);
- bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize);
+ bcopy(&trapcode, (void *)EXC_VEC, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
@@ -647,7 +647,21 @@ grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
}
- /* XXX Altivec context ? */
+ /*
+ * Repeat for Altivec context
+ */
+
+ if (pcb->pcb_flags & PCB_VEC) {
+ KASSERT(td == curthread,
+ ("get_mcontext: fp save not curthread"));
+ critical_enter();
+ save_vec(td);
+ critical_exit();
+ mcp->mc_flags |= _MC_AV_VALID;
+ mcp->mc_vscr = pcb->pcb_vec.vscr;
+ mcp->mc_vrsave = pcb->pcb_vec.vrsave;
+ memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
+ }
mcp->mc_len = sizeof(*mcp);
@@ -701,7 +715,17 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
}
- /* XXX Altivec context? */
+ if (mcp->mc_flags & _MC_AV_VALID) {
+ if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
+ critical_enter();
+ enable_vec(td);
+ critical_exit();
+ }
+ pcb->pcb_vec.vscr = mcp->mc_vscr;
+ pcb->pcb_vec.vrsave = mcp->mc_vrsave;
+ memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
+ }
+
return (0);
}
diff --git a/sys/powerpc/aim/swtch.S b/sys/powerpc/aim/swtch.S
index 0f59e7312e24..672fe6b1161c 100644
--- a/sys/powerpc/aim/swtch.S
+++ b/sys/powerpc/aim/swtch.S
@@ -106,8 +106,16 @@ ENTRY(cpu_switch)
andi. %r6, %r6, PCB_FPU
beq .L1
bl save_fpu
- mr %r3,%r14 /* restore old thread ptr */
+
.L1:
+ lwz %r6,PCB_FLAGS(%r5)
+ /* Save Altivec context if needed */
+ andi. %r6, %r6, PCB_VEC
+ beq .L2
+ bl save_vec
+
+.L2:
+ mr %r3,%r14 /* restore old thread ptr */
bl pmap_deactivate /* Deactivate the current pmap */
cpu_switchin:
@@ -122,12 +130,20 @@ cpu_switchin:
lwz %r6, PCB_FLAGS(%r17)
/* Restore FPU context if needed */
andi. %r6, %r6, PCB_FPU
- beq .L2
+ beq .L3
mr %r3,%r15 /* Pass curthread to enable_fpu */
bl enable_fpu
+.L3:
+ lwz %r6, PCB_FLAGS(%r17)
+ /* Restore Altivec context if needed */
+ andi. %r6, %r6, PCB_VEC
+ beq .L4
+ mr %r3,%r15 /* Pass curthread to enable_vec */
+ bl enable_vec
+
/* thread to restore is in r3 */
-.L2:
+.L4:
mr %r3,%r17 /* Recover PCB ptr */
lmw %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs */
mr %r2,%r12
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index 0a3827d03398..4b540937fa8a 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_map.h>
#include <vm/vm_page.h>
+#include <machine/altivec.h>
#include <machine/cpu.h>
#include <machine/db_machdep.h>
#include <machine/fpu.h>
@@ -188,24 +189,16 @@ trap(struct trapframe *frame)
enable_fpu(td);
break;
-#ifdef ALTIVEC
case EXC_VEC:
- if ((vecthread = PCPU_GET(vecthread)) != NULL) {
- KASSERT(vecthread != td,
- ("altivec already enabled"));
- save_vec(vecthread);
- }
- PCPU_SET(vecthread, td);
- td->td_pcb->pcb_veccpu = PCPU_GET(cpuid);
+ KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
+ ("Altivec already enabled for thread"));
enable_vec(td);
- frame->srr1 |= PSL_VEC;
break;
-#else
- case EXC_VEC:
+
case EXC_VECAST:
+ printf("Vector assist exception!\n");
sig = SIGILL;
break;
-#endif /* ALTIVEC */
case EXC_ALI:
if (fix_unaligned(td, frame) != 0)
diff --git a/sys/powerpc/aim/trap_subr.S b/sys/powerpc/aim/trap_subr.S
index ba72a6557e35..82cdf3237b8d 100644
--- a/sys/powerpc/aim/trap_subr.S
+++ b/sys/powerpc/aim/trap_subr.S
@@ -79,13 +79,13 @@
/*
* FRAME_SETUP assumes:
* SPRG1 SP (1)
+ * SPRG3 trap type
* savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
* r28 LR
* r29 CR
* r30 scratch
* r31 scratch
* r1 kernel stack
- * LR trap type (from calling address, mask with 0xff00)
* SRR0/1 as at start of trap
*/
#define FRAME_SETUP(savearea) \
@@ -146,8 +146,7 @@
lwz %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \
mfxer %r3; \
mfctr %r4; \
- mflr %r5; \
- andi. %r5,%r5,0xff00; /* convert LR to exc # */ \
+ mfsprg3 %r5; \
stw %r3, FRAME_XER+8(1); /* save xer/ctr/exc */ \
stw %r4, FRAME_CTR+8(1); \
stw %r5, FRAME_EXC+8(1); \
@@ -264,18 +263,10 @@ CNAME(rstsize) = . - CNAME(rstcode)
.globl CNAME(trapcode),CNAME(trapsize)
CNAME(trapcode):
mtsprg1 %r1 /* save SP */
- GET_CPUINFO(%r1)
- stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
- stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
- stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
- stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
- mfsprg1 %r1 /* restore SP, in case of branch */
- mflr %r28 /* save LR */
- mfcr %r29 /* save CR */
-/* Test whether we already had PR set */
- mfsrr1 %r31
- mtcr %r31
- bla s_trap /* LR & 0xff00 is exception # */
+ mflr %r1 /* Save the old LR in r1 */
+ mtsprg2 %r1 /* And then in SPRG2 */
+ li %r1, 0x20 /* How to get the vector from LR */
+ bla generictrap /* LR & SPRG3 is exception # */
CNAME(trapsize) = .-CNAME(trapcode)
/*
@@ -296,10 +287,15 @@ CNAME(alitrap):
mfsprg1 %r1 /* restore SP, in case of branch */
mflr %r28 /* save LR */
mfcr %r29 /* save CR */
-/* Test whether we already had PR set */
+
+ /* Put our exception vector in SPRG0 */
+ li %r31, EXC_ALI
+ mtsprg3 %r31
+
+ /* Test whether we already had PR set */
mfsrr1 %r31
mtcr %r31
- bla s_trap /* LR & 0xff00 is exception # */
+ bla s_trap
CNAME(alisize) = .-CNAME(alitrap)
/*
@@ -364,6 +360,11 @@ CNAME(dsisize) = .-CNAME(dsitrap)
* Preamble code for DSI/ISI traps
*/
disitrap:
+ /* Write the trap vector to SPRG0 by computing LR & 0xff00 */
+ mflr %r1
+ andi. %r1,%r1,0xff00
+ mtsprg3 %r1
+
GET_CPUINFO(%r1)
lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
stw %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
@@ -416,6 +417,47 @@ realtrap:
mtcr %r1
mfsprg1 %r1 /* restore SP (might have been
overwritten) */
+ bf 17,k_trap /* branch if PSL_PR is false */
+ GET_CPUINFO(%r1)
+ lwz %r1,PC_CURPCB(%r1)
+ RESTORE_KERN_SRS(%r30,%r31) /* enable kernel mapping */
+ ba s_trap
+
+/*
+ * generictrap does some standard setup for trap handling to minimize
+ * the code that need be installed in the actual vectors. It expects
+ * the following conditions.
+ *
+ * R1 - Trap vector = LR & (0xff00 | R1)
+ * SPRG1 - Original R1 contents
+ * SPRG2 - Original LR
+ */
+
+generictrap:
+ /* Save R1 for computing the exception vector */
+ mtsprg3 %r1
+
+ /* Save interesting registers */
+ GET_CPUINFO(%r1)
+ stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
+ stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+ stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+ stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+ mfsprg1 %r1 /* restore SP, in case of branch */
+ mfsprg2 %r28 /* save LR */
+ mfcr %r29 /* save CR */
+
+ /* Compute the exception vector from the link register */
+ mfsprg3 %r31
+ ori %r31,%r31,0xff00
+ mflr %r30
+ and %r30,%r30,%r31
+ mtsprg3 %r30
+
+ /* Test whether we already had PR set */
+ mfsrr1 %r31
+ mtcr %r31
+
s_trap:
bf 17,k_trap /* branch if PSL_PR is false */
GET_CPUINFO(%r1)
@@ -464,14 +506,6 @@ CNAME(asttrapexit):
FRAME_LEAVE(PC_TEMPSAVE)
rfi
-/*
- * Temporary: vector-unavailable traps are directed to vector-assist traps
- */
- .globl CNAME(vectrap),CNAME(vectrapsize)
-CNAME(vectrap):
- ba EXC_VECAST
-CNAME(vectrapsize) = .-CNAME(vectrap)
-
#if defined(KDB)
/*
* Deliberate entry to dbtrap
@@ -499,6 +533,14 @@ CNAME(breakpoint):
* Now the kdb trap catching code.
*/
dbtrap:
+ /* Write the trap vector to SPRG0 by computing LR & 0xff00 */
+ mflr %r1
+ andi. %r1,%r1,0xff00
+ mtsprg3 %r1
+
+ lis %r1,(tmpstk+TMPSTKSZ-16)@ha /* get new SP */
+ addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
+
FRAME_SETUP(PC_DBSAVE)
/* Call C trap code: */
addi %r3,%r1,8
@@ -536,24 +578,25 @@ CNAME(dblow):
mfcr %r29 /* save CR in r29 */
mfsrr1 %r1
mtcr %r1
- GET_CPUINFO(%r1)
bf 17,1f /* branch if privileged */
- stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28 */
- mfsprg2 %r28 /* r29 holds cr ... */
- stw %r28,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) /* free r29 */
- stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) /* free r30 */
- stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) /* free r31 */
- mflr %r28 /* save LR */
- bla u_trap
+
+ /* Unprivileged case */
+ mtcr %r29 /* put the condition register back */
+ mfsprg2 %r29 /* ... and r29 */
+ mflr %r1 /* save LR */
+ mtsprg2 %r1 /* And then in SPRG2 */
+ li %r1, 0 /* How to get the vector from LR */
+
+ bla generictrap /* and we look like a generic trap */
1:
+ /* Privileged, so drop to KDB */
+ GET_CPUINFO(%r1)
stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */
mfsprg2 %r28 /* r29 holds cr... */
stw %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */
stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */
mflr %r28 /* save LR */
- lis %r1,(tmpstk+TMPSTKSZ-16)@ha /* get new SP */
- addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
bla dbtrap
CNAME(dbsize) = .-CNAME(dblow)
#endif /* KDB */