Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc Fill in the alignment trap handler a bit: n...
details: https://anonhg.NetBSD.org/src/rev/056503363286
branches: trunk
changeset: 480747:056503363286
user: danw <danw%NetBSD.org@localhost>
date: Wed Jan 19 03:30:12 2000 +0000
description:
Fill in the alignment trap handler a bit: now it can fix unaligned
floating point loads and stores (to work around a gcc bug), but will
still cause a bus error on other sorts of unaligned accesses.
diffstat:
sys/arch/powerpc/include/trap.h | 20 +++++++++++++-
sys/arch/powerpc/powerpc/trap.c | 59 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 75 insertions(+), 4 deletions(-)
diffs (116 lines):
diff -r da5f81ec11db -r 056503363286 sys/arch/powerpc/include/trap.h
--- a/sys/arch/powerpc/include/trap.h Wed Jan 19 03:28:21 2000 +0000
+++ b/sys/arch/powerpc/include/trap.h Wed Jan 19 03:30:12 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.h,v 1.1 1996/09/30 16:34:35 ws Exp $ */
+/* $NetBSD: trap.h,v 1.2 2000/01/19 03:30:12 danw Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -64,4 +64,22 @@
/* Trap was in user mode */
#define EXC_USER 0x10000
+
+/*
+ * EXC_ALI sets bits in the DSISR and DAR to provide enough
+ * information to recover from the unaligned access without needing to
+ * parse the offending instruction. This includes certain bits of the
+ * opcode, and information about what registers are used. The opcode
+ * indicator values below come from Appendix F of Book III of "The
+ * PowerPC Architecture".
+ */
+
+#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f)
+#define EXC_ALI_LFD 0x09
+#define EXC_ALI_STFD 0x0b
+
+/* Macros to extract register information */
+#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */
+#define EXC_ALI_RA(dsisr) (dsisr & 0x1f)
+
#endif /* _MACHINE_TRAP_H_ */
diff -r da5f81ec11db -r 056503363286 sys/arch/powerpc/powerpc/trap.c
--- a/sys/arch/powerpc/powerpc/trap.c Wed Jan 19 03:28:21 2000 +0000
+++ b/sys/arch/powerpc/powerpc/trap.c Wed Jan 19 03:30:12 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.22 1999/05/03 10:02:20 tsubai Exp $ */
+/* $NetBSD: trap.c,v 1.23 2000/01/19 03:30:13 danw Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -62,6 +62,8 @@
volatile int astpending;
volatile int want_resched;
+static int fix_unaligned __P((struct proc *p, struct trapframe *frame));
+
void
trap(frame)
struct trapframe *frame;
@@ -262,8 +264,10 @@
break;
case EXC_ALI|EXC_USER:
-/* XXX temporarily */
- trapsignal(p, SIGBUS, EXC_ALI);
+ if (fix_unaligned(p, frame) != 0)
+ trapsignal(p, SIGBUS, EXC_ALI);
+ else
+ frame->srr0 += 4;
break;
case EXC_PGM|EXC_USER:
@@ -531,3 +535,52 @@
return 0;
}
+
+/*
+ * For now, this only deals with the particular unaligned access case
+ * that gcc tends to generate. Eventually it should handle all of the
+ * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
+ */
+
+static int
+fix_unaligned(p, frame)
+ struct proc *p;
+ struct trapframe *frame;
+{
+ int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
+
+ switch (indicator) {
+ case EXC_ALI_LFD:
+ case EXC_ALI_STFD:
+ {
+ int reg = EXC_ALI_RST(frame->dsisr);
+ double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg];
+
+ /* Juggle the FPU to ensure that we've initialized
+ * the FPRs, and that their current state is in
+ * the PCB.
+ */
+ if (fpuproc != p) {
+ if (fpuproc)
+ save_fpu(fpuproc);
+ enable_fpu(p);
+ }
+ save_fpu(p);
+
+ if (indicator == EXC_ALI_LFD) {
+ if (copyin((void *)frame->dar, fpr,
+ sizeof(double)) != 0)
+ return -1;
+ enable_fpu(p);
+ } else {
+ if (copyout(fpr, (void *)frame->dar,
+ sizeof(double)) != 0)
+ return -1;
+ }
+ return 0;
+ }
+ break;
+ }
+
+ return -1;
+}
Home |
Main Index |
Thread Index |
Old Index