flush the dcache after accessing pcb_fpregs.

we access it with the DTLB both on and off,
so we need to avoid bad cache aliases.
This commit is contained in:
chs 2004-06-15 16:29:01 +00:00
parent 508451c5cd
commit b7bd18170e
3 changed files with 61 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu.c,v 1.5 2004/03/26 14:11:01 drochner Exp $ */
/* $NetBSD: fpu.c,v 1.6 2004/06/15 16:29:01 chs Exp $ */
/*
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.5 2004/03/26 14:11:01 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.6 2004/06/15 16:29:01 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -87,7 +87,7 @@ u_int fpu_csw;
paddr_t fpu_cur_uspace;
/* In locore.S, this swaps states in and out of the FPU. */
void hppa_fpu_swap(struct user *, struct user *);
void hppa_fpu_swap(struct pcb *, struct pcb *);
/* XXX see trap.c */
void hppa_trapsignal_hack(struct lwp *, int, u_long);
@ -231,10 +231,13 @@ hppa_fpu_flush(struct lwp *l)
* state is currently in it, swap it out.
*/
if (fpu_present &&
fpu_cur_uspace != 0 &&
fpu_cur_uspace == tf->tf_cr30)
hppa_fpu_swap(l->l_addr, NULL);
if (!fpu_present || fpu_cur_uspace == 0 ||
fpu_cur_uspace != tf->tf_cr30) {
return;
}
hppa_fpu_swap(&l->l_addr->u_pcb, NULL);
fpu_cur_uspace = 0;
}
#ifdef FPEMUL
@ -252,7 +255,8 @@ hppa_fpu_ls(struct trapframe *frame, struct lwp *l)
u_int offset, index, im5;
void *fpreg;
u_int r0 = 0;
int error;
/*
* Get the instruction that we're emulating,
* and break it down. Using HP bit notation,
@ -339,9 +343,12 @@ hppa_fpu_ls(struct trapframe *frame, struct lwp *l)
KASSERT(offset == frame->tf_ior);
/* Perform the load or store. */
return (inst & OPCODE_STORE) ?
error = (inst & OPCODE_STORE) ?
copyout(fpreg, (void *) offset, 1 << log2size) :
copyin((const void *) offset, fpreg, 1 << log2size);
fdcache(HPPA_SID_KERNEL, (vaddr_t)fpreg,
sizeof(l->l_addr->u_pcb.pcb_fpregs));
return error;
}
/*
@ -406,6 +413,8 @@ hppa_fpu_emulate(struct trapframe *frame, struct lwp *l)
break;
}
fdcache(HPPA_SID_KERNEL, (vaddr_t)fpregs,
sizeof(l->l_addr->u_pcb.pcb_fpregs));
if (exception)
hppa_trapsignal_hack(l, (exception & UNIMPLEMENTEDEXCEPTION) ?
SIGILL : SIGFPE, frame->tf_iioq_head);

View File

@ -1,4 +1,4 @@
/* $NetBSD: process_machdep.c,v 1.3 2003/08/31 01:26:35 chs Exp $ */
/* $NetBSD: process_machdep.c,v 1.4 2004/06/15 16:29:01 chs Exp $ */
/* $OpenBSD: process_machdep.c,v 1.3 1999/06/18 05:19:52 mickey Exp $ */
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.3 2003/08/31 01:26:35 chs Exp $");
__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.4 2004/06/15 16:29:01 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -41,6 +41,8 @@ __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.3 2003/08/31 01:26:35 chs Exp
#include <sys/ptrace.h>
#include <sys/user.h>
#include <machine/cpufunc.h>
int
process_read_regs(struct lwp *l, struct reg *regs)
{
@ -61,6 +63,8 @@ int
process_read_fpregs(struct lwp *l, struct fpreg *fpregs)
{
bcopy(l->l_addr->u_pcb.pcb_fpregs, fpregs, sizeof(*fpregs));
fdcache(HPPA_SID_KERNEL, (vaddr_t)&l->l_addr->u_pcb.pcb_fpregs,
sizeof(*fpregs));
return 0;
}
@ -68,6 +72,8 @@ int
process_write_fpregs(struct lwp *l, struct fpreg *fpregs)
{
bcopy(fpregs, l->l_addr->u_pcb.pcb_fpregs, sizeof(*fpregs));
fdcache(HPPA_SID_KERNEL, (vaddr_t)&l->l_addr->u_pcb.pcb_fpregs,
sizeof(*fpregs));
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.S,v 1.8 2003/10/10 15:07:43 chs Exp $ */
/* $NetBSD: trap.S,v 1.9 2004/06/15 16:29:01 chs Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -1013,7 +1013,9 @@ $emulate_fpu:
EXIT(TLABEL(emu))
/*
* void hppa_fpu_swap(struct user *user_out, struct user *user_in);
* void hppa_fpu_swap(paddr_t out, paddr_t in);
* or
* void hppa_fpu_swap(struct pcb *out, NULL);
*/
LEAF_ENTRY(hppa_fpu_swap)
@ -1027,18 +1029,17 @@ LEAF_ENTRY(hppa_fpu_swap)
*/
/*
* Assuming that user_out and user_in aren't
* both NULL, we will have to run coprocessor
* instructions, so we'd better enable it.
* Assuming that out and in aren't both NULL,
* we will have to run coprocessor instructions,
* so we'd better enable it.
*
* Also, branch if there's no FPU state
* to swap out.
* Also, branch if there's no FPU state to swap out.
*/
mfctl %ccr, %r1
depi 3, 25, 2, %r1
comb,= %r0, %arg0, $fpu_swap_in
mtctl %r1, %ccr
/*
* Swap out the current FPU state.
*/
@ -1076,6 +1077,19 @@ LEAF_ENTRY(hppa_fpu_swap)
fstds,ma %fr30, 8(%arg0)
fstds %fr31, 0(%arg0)
ldo -248(%arg0), %arg0
ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r1
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
fdc,m %r1(%arg0)
sync
$fpu_swap_in:
/*
@ -1132,6 +1146,19 @@ $fpu_swap_in:
fldds,ma -8(%arg1), %fr1
fldds 0(%arg1), %fr0 /* fr0 must be restored last */
ldo -248(%arg1), %arg1
ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r1
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
fdc,m %r1(%arg1)
sync
$fpu_swap_done:
/* Increment the switch count and return. */