summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sparc/sparc/cpu.c53
-rw-r--r--sys/arch/sparc/sparc/cpuvar.h20
-rw-r--r--sys/arch/sparc/sparc/genassym.cf7
-rw-r--r--sys/arch/sparc/sparc/intr.c65
-rw-r--r--sys/arch/sparc/sparc/intreg.h7
-rw-r--r--sys/arch/sparc/sparc/locore.s178
-rw-r--r--sys/arch/sparc/sparc/memreg.c93
-rw-r--r--sys/arch/sparc/sparc/memreg.h8
-rw-r--r--sys/arch/sparc/sparc/pmap.c4
-rw-r--r--sys/arch/sparc/sparc/trap.c17
10 files changed, 273 insertions, 179 deletions
diff --git a/sys/arch/sparc/sparc/cpu.c b/sys/arch/sparc/sparc/cpu.c
index fa0a1883eb0..480f8fb358a 100644
--- a/sys/arch/sparc/sparc/cpu.c
+++ b/sys/arch/sparc/sparc/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.28 2000/02/21 14:58:17 art Exp $ */
+/* $OpenBSD: cpu.c,v 1.29 2000/02/21 17:08:36 art Exp $ */
/* $NetBSD: cpu.c,v 1.56 1997/09/15 20:52:36 pk Exp $ */
/*
@@ -381,13 +381,18 @@ void viking_mmu_enable __P((void));
void swift_mmu_enable __P((void));
void hypersparc_mmu_enable __P((void));
-void srmmu_get_fltstatus __P((void));
-void ms1_get_fltstatus __P((void));
-void viking_get_fltstatus __P((void));
-void swift_get_fltstatus __P((void));
-void turbosparc_get_fltstatus __P((void));
-void hypersparc_get_fltstatus __P((void));
-void cypress_get_fltstatus __P((void));
+void srmmu_get_syncflt __P((void));
+void ms1_get_syncflt __P((void));
+void viking_get_syncflt __P((void));
+void swift_get_syncflt __P((void));
+void turbosparc_get_syncflt __P((void));
+void hypersparc_get_syncflt __P((void));
+void cypress_get_syncflt __P((void));
+
+int srmmu_get_asyncflt __P((u_int *, u_int *));
+int hypersparc_get_asyncflt __P((u_int *, u_int *));
+int cypress_get_asyncflt __P((u_int *, u_int *));
+int no_asyncflt_regs __P((u_int *, u_int *));
struct module_info module_unknown = {
CPUTYP_UNKNOWN,
@@ -418,7 +423,8 @@ struct module_info module_sun4 = {
0,
sun4_cache_enable,
0, /* ncontext set in `match' function */
- 0, /* get fault regs: unused */
+ 0, /* get_syncflt(); unused in sun4 */
+ 0, /* get_asyncflt(); unused in sun4 */
sun4_cache_flush,
sun4_vcache_flush_page,
sun4_vcache_flush_segment,
@@ -543,7 +549,8 @@ struct module_info module_sun4c = {
0,
sun4_cache_enable,
0, /* ncontext set in `match' function */
- 0,
+ 0, /* get_syncflt(); unused in sun4c */
+ 0, /* get_asyncflt(); unused in sun4c */
sun4_cache_flush,
sun4_vcache_flush_page,
sun4_vcache_flush_segment,
@@ -740,7 +747,8 @@ struct module_info module_ms1 = {
ms1_mmu_enable,
ms1_cache_enable,
64,
- ms1_get_fltstatus,
+ ms1_get_syncflt,
+ no_asyncflt_regs,
ms1_cache_flush,
noop_vcache_flush_page,
noop_vcache_flush_segment,
@@ -767,7 +775,8 @@ struct module_info module_ms2 = { /* UNTESTED */
0,
swift_cache_enable,
256,
- srmmu_get_fltstatus,
+ srmmu_get_syncflt,
+ srmmu_get_asyncflt,
srmmu_cache_flush,
srmmu_vcache_flush_page,
srmmu_vcache_flush_segment,
@@ -789,7 +798,8 @@ struct module_info module_swift = { /* UNTESTED */
0,
swift_cache_enable,
256,
- swift_get_fltstatus,
+ swift_get_syncflt,
+ no_asyncflt_regs,
srmmu_cache_flush,
srmmu_vcache_flush_page,
srmmu_vcache_flush_segment,
@@ -835,7 +845,8 @@ struct module_info module_viking = { /* UNTESTED */
viking_mmu_enable,
viking_cache_enable,
4096,
- viking_get_fltstatus,
+ viking_get_syncflt,
+ no_asyncflt_regs,
/* supersparcs use cached DVMA, no need to flush */
noop_cache_flush,
noop_vcache_flush_page,
@@ -918,7 +929,8 @@ struct module_info module_hypersparc = { /* UNTESTED */
hypersparc_mmu_enable,
hypersparc_cache_enable,
4096,
- hypersparc_get_fltstatus,
+ hypersparc_get_syncflt,
+ hypersparc_get_asyncflt,
srmmu_cache_flush,
srmmu_vcache_flush_page,
srmmu_vcache_flush_segment,
@@ -968,7 +980,8 @@ struct module_info module_cypress = { /* UNTESTED */
0,
cypress_cache_enable,
4096,
- cypress_get_fltstatus,
+ cypress_get_syncflt,
+ cypress_get_asyncflt,
srmmu_cache_flush,
srmmu_vcache_flush_page,
srmmu_vcache_flush_segment,
@@ -990,7 +1003,8 @@ struct module_info module_turbosparc = { /* UNTESTED */
0,
turbosparc_cache_enable,
256,
- turbosparc_get_fltstatus,
+ turbosparc_get_syncflt,
+ no_asyncflt_regs,
srmmu_cache_flush,
srmmu_vcache_flush_page,
srmmu_vcache_flush_segment,
@@ -1028,7 +1042,7 @@ cpumatch_turbosparc(sc, mp, node)
sc->hotfix = 0;
sc->mmu_enable = 0;
sc->cache_enable = 0;
- sc->get_faultstatus = 0;
+ sc->get_syncflt = 0;
sc->cache_flush = 0;
sc->vcache_flush_page = 0;
sc->vcache_flush_segment = 0;
@@ -1214,7 +1228,8 @@ getcpuinfo(sc, node)
MPCOPY(hotfix);
MPCOPY(mmu_enable);
MPCOPY(cache_enable);
- MPCOPY(get_faultstatus);
+ MPCOPY(get_syncflt);
+ MPCOPY(get_asyncflt);
MPCOPY(cache_flush);
MPCOPY(vcache_flush_page);
MPCOPY(vcache_flush_segment);
diff --git a/sys/arch/sparc/sparc/cpuvar.h b/sys/arch/sparc/sparc/cpuvar.h
index 6585ddec3b9..2f430f1711e 100644
--- a/sys/arch/sparc/sparc/cpuvar.h
+++ b/sys/arch/sparc/sparc/cpuvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpuvar.h,v 1.3 2000/02/19 21:45:56 art Exp $ */
+/* $OpenBSD: cpuvar.h,v 1.4 2000/02/21 17:08:36 art Exp $ */
/* $NetBSD: cpuvar.h,v 1.4 1997/07/06 21:14:25 pk Exp $ */
/*
@@ -63,7 +63,8 @@ struct module_info {
void (*cache_enable) __P((void));
int ncontext; /* max. # of contexts (we use) */
- void (*get_faultstatus) __P((void));
+ void (*get_syncflt) __P((void));
+ int (*get_asyncflt) __P((u_int *, u_int *));
void (*cache_flush) __P((caddr_t, u_int));
void (*vcache_flush_page) __P((int));
void (*vcache_flush_segment) __P((int, int));
@@ -72,8 +73,7 @@ struct module_info {
void (*pcache_flush_line) __P((int, int));
void (*pure_vcache_flush) __P((void));
void (*cache_flush_all)__P((void));
- void (*memerr) __P((unsigned, u_int, u_int, u_int, u_int,
- struct trapframe *));
+ void (*memerr) __P((unsigned, u_int, u_int, struct trapframe *));
};
@@ -167,7 +167,14 @@ struct cpu_softc {
void (*hotfix) __P((struct cpu_softc *));
/* locore defined: */
- void (*get_faultstatus) __P((void));
+ void (*get_syncflt) __P((void)); /* Not C-callable */
+ int (*get_asyncflt) __P((u_int *, u_int *));
+
+ /* Synchronous Fault Status; temporary storage */
+ struct {
+ int sfsr;
+ int sfva;
+ } syncfltdump;
/* Cache handling functions */
void (*cache_enable) __P((void));
@@ -194,8 +201,7 @@ struct cpu_softc {
* Memory error handler; parity errors, unhandled NMIs and other
* unrecoverable faults end up here.
*/
- void (*memerr)__P((unsigned, u_int, u_int, u_int, u_int,
- struct trapframe *));
+ void (*memerr)__P((unsigned, u_int, u_int, struct trapframe *));
/* XXX: Add more here! */
};
diff --git a/sys/arch/sparc/sparc/genassym.cf b/sys/arch/sparc/sparc/genassym.cf
index 1b20a67064b..89bb88ab246 100644
--- a/sys/arch/sparc/sparc/genassym.cf
+++ b/sys/arch/sparc/sparc/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.5 2000/02/19 22:00:34 art Exp $
+# $OpenBSD: genassym.cf,v 1.6 2000/02/21 17:08:36 art Exp $
# $NetBSD: genassym.cf,v 1.2 1997/06/28 19:59:04 pk Exp $
#
@@ -112,8 +112,9 @@ define V_FAULTS offsetof(struct vmmeter, v_faults)
endif
# CPU info structure
-define CPUINFO_FAULTSTATUS offsetof(struct cpu_softc, get_faultstatus)
-define CPUINFO_MEMERR offsetof(struct cpu_softc, memerr)
+define CPUINFO_GETSYNCFLT offsetof(struct cpu_softc, get_syncflt)
+define CPUINFO_GETASYNCFLT offsetof(struct cpu_softc, get_asyncflt)
+define CPUINFO_SYNCFLTDUMP offsetof(struct cpu_softc, syncfltdump)
define CPUINFO_PURE_VCACHE_FLS offsetof(struct cpu_softc, pure_vcache_flush)
# PTE bits and related information
diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c
index 8c01dd3ab5d..8d71cef2b3f 100644
--- a/sys/arch/sparc/sparc/intr.c
+++ b/sys/arch/sparc/sparc/intr.c
@@ -61,6 +61,8 @@
#include <machine/instr.h>
#include <machine/trap.h>
+#include <sparc/sparc/cpuvar.h>
+
#ifdef INET
#include <netinet/in.h>
#include <netinet/if_ether.h>
@@ -179,6 +181,69 @@ soft01intr(fp)
return (1);
}
+#if defined(SUN4M)
+void nmi_hard __P((void));
+void
+nmi_hard()
+{
+ /*
+ * A level 15 hard interrupt.
+ */
+#ifdef noyet
+ int fatal = 0;
+#endif
+ u_int32_t si;
+ u_int afsr, afva;
+
+ afsr = afva = 0;
+ if ((*cpuinfo.get_asyncflt)(&afsr, &afva) == 0) {
+ printf("Async registers (mid %d): afsr=%b; afva=0x%x%x\n",
+ cpuinfo.mid, afsr, AFSR_BITS,
+ (afsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, afva);
+ }
+
+ if (cpuinfo.master == 0) {
+ /*
+ * For now, just return.
+ * Should wait on damage analysis done by the master.
+ */
+ return;
+ }
+
+ /*
+ * Examine pending system interrupts.
+ */
+ si = *((u_int32_t *)ICR_SI_PEND);
+ printf("NMI: system interrupts: %b\n", si, SINTR_BITS);
+
+#ifdef notyet
+ if ((si & SINTR_M) != 0) {
+ /* ECC memory error */
+ if (memerr_handler != NULL)
+ fatal |= (*memerr_handler)();
+ }
+ if ((si & SINTR_I) != 0) {
+ /* MBus/SBus async error */
+ if (sbuserr_handler != NULL)
+ fatal |= (*sbuserr_handler)();
+ }
+ if ((si & SINTR_V) != 0) {
+ /* VME async error */
+ if (vmeerr_handler != NULL)
+ fatal |= (*vmeerr_handler)();
+ }
+ if ((si & SINTR_ME) != 0) {
+ /* Module async error */
+ if (moduleerr_handler != NULL)
+ fatal |= (*moduleerr_handler)();
+ }
+
+ if (fatal)
+#endif
+ panic("nmi");
+}
+#endif
+
static struct intrhand level01 = { soft01intr };
/*
diff --git a/sys/arch/sparc/sparc/intreg.h b/sys/arch/sparc/sparc/intreg.h
index e74859f6327..2c619934ee8 100644
--- a/sys/arch/sparc/sparc/intreg.h
+++ b/sys/arch/sparc/sparc/intreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intreg.h,v 1.3 1997/08/08 08:27:19 downsj Exp $ */
+/* $OpenBSD: intreg.h,v 1.4 2000/02/21 17:08:36 art Exp $ */
/* $NetBSD: intreg.h,v 1.6 1997/07/22 20:19:10 pk Exp $ */
/*
@@ -137,5 +137,10 @@ void ienab_bic __P((int bic)); /* clear given bits */
#define SINTR_SBUS(n) (1 << (7+(n)-1))
#define SINTR_VMEMASK 0x0000007f /* VME */
#define SINTR_VME(n) (1 << ((n)-1))
+#define SINTR_BITS "\177\020" \
+ "f\0\7VME\0f\7\7SBUS\0b\16K\0b\17S\0b\20E\0" \
+ "b\21A\0b\22SC\0b\23T\0b\24VI\0b\25MI\0" \
+ "b\26F\0b\33V\0b\34M\0b\35I\0b\36ME\0b\37MA\0"
+
#endif
diff --git a/sys/arch/sparc/sparc/locore.s b/sys/arch/sparc/sparc/locore.s
index 326c72e3cd6..21bce05f5e9 100644
--- a/sys/arch/sparc/sparc/locore.s
+++ b/sys/arch/sparc/sparc/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.33 2000/02/19 22:08:50 art Exp $ */
+/* $OpenBSD: locore.s,v 1.34 2000/02/21 17:08:36 art Exp $ */
/* $NetBSD: locore.s,v 1.73 1997/09/13 20:36:48 pk Exp $ */
/*
@@ -1264,21 +1264,31 @@ Lpanic_red:
#define PTE_OF_ADDR4M(addr, pte, bad, page_offset) \
andn addr, page_offset, pte
+/*
+ * After obtaining the PTE through ASI_SRMMUFP, we read the Sync Fault
+ * Status register. This is necessary on Hypersparcs which stores and
+ * locks the fault address and status registers if the translation
+ * fails (thanks to Chris Torek for finding this quirk).
+ */
/* note: pmap currently does not use the PPROT_R_R and PPROT_RW_RW cases */
-#define CMP_PTE_USER_READ4M(pte) \
+#define CMP_PTE_USER_READ4M(pte, tmp) \
or pte, ASI_SRMMUFP_L3, pte; \
lda [pte] ASI_SRMMUFP, pte; \
+ set SRMMU_SFSR, tmp; \
and pte, (SRMMU_TETYPE | SRMMU_PROT_MASK), pte; \
cmp pte, (SRMMU_TEPTE | PPROT_RWX_RWX); \
- be 8f; nop; \
+ be 8f; \
+ lda [tmp] ASI_SRMMU, %g0; \
cmp pte, (SRMMU_TEPTE | PPROT_RX_RX); \
8:
/* note: PTE bit 4 set implies no user writes */
-#define CMP_PTE_USER_WRITE4M(pte) \
+#define CMP_PTE_USER_WRITE4M(pte, tmp) \
or pte, ASI_SRMMUFP_L3, pte; \
lda [pte] ASI_SRMMUFP, pte; \
+ set SRMMU_SFSR, tmp; \
+ lda [tmp] ASI_SRMMU, %g0; \
and pte, (SRMMU_TETYPE | 0x14), pte; \
cmp pte, (SRMMU_TEPTE | PPROT_WRITE)
#endif /* 4m */
@@ -1287,8 +1297,8 @@ Lpanic_red:
#define PTE_OF_ADDR(addr, pte, bad, page_offset, label) \
PTE_OF_ADDR4M(addr, pte, bad, page_offset)
-#define CMP_PTE_USER_WRITE(pte, tmp, label) CMP_PTE_USER_WRITE4M(pte)
-#define CMP_PTE_USER_READ(pte, tmp, label) CMP_PTE_USER_READ4M(pte)
+#define CMP_PTE_USER_WRITE(pte, tmp, label) CMP_PTE_USER_WRITE4M(pte,tmp)
+#define CMP_PTE_USER_READ(pte, tmp, label) CMP_PTE_USER_READ4M(pte,tmp)
#elif (defined(SUN4C) || defined(SUN4)) && !defined(SUN4M)
@@ -1309,7 +1319,7 @@ label: b,a 2f; \
#define CMP_PTE_USER_READ(pte, tmp, label) \
label: b,a 1f; \
- CMP_PTE_USER_READ4M(pte); \
+ CMP_PTE_USER_READ4M(pte,tmp); \
b,a 2f; \
1: \
CMP_PTE_USER_READ4_4C(pte); \
@@ -1317,7 +1327,7 @@ label: b,a 1f; \
#define CMP_PTE_USER_WRITE(pte, tmp, label) \
label: b,a 1f; \
- CMP_PTE_USER_WRITE4M(pte); \
+ CMP_PTE_USER_WRITE4M(pte,tmp); \
b,a 2f; \
1: \
CMP_PTE_USER_WRITE4_4C(pte); \
@@ -1869,6 +1879,14 @@ memfault_sun4c:
#if defined(SUN4M)
memfault_sun4m:
+ ! DANGER: we use the fact that %lo(CPUINFO_VA) is zero
+.if CPUINFO_VA & 0x1fff
+BARF
+.endif
+ sethi %hi(CPUINFO_VA), %l4
+ ld [%l4 + %lo(CPUINFO_VA+CPUINFO_GETSYNCFLT)], %l5
+ jmpl %l5, %l7
+ or %l4, %lo(CPUINFO_SYNCFLTDUMP), %l4
TRAP_SETUP(-CCFSZ-80)
#if defined(UVM)
INCR(_uvmexp+V_FAULTS) ! cnt.v_faults++ (clobbers %o0,%o1)
@@ -1881,12 +1899,12 @@ memfault_sun4m:
std %g2, [%sp + CCFSZ + 24] ! save g2, g3
std %g4, [%sp + CCFSZ + 32] ! save g4, g5
+ std %g6, [%sp + CCFSZ + 40] ! save g6, g7
- ! get fault status/address
- set CPUINFO_VA+CPUINFO_FAULTSTATUS, %o0
- ld [%o0], %o0
- jmpl %o0, %o7
- std %g6, [%sp + CCFSZ + 40] ! sneak in g6, g7
+ ! retrieve sync fault status/address
+ sethi %hi(CPUINFO_VA+CPUINFO_SYNCFLTDUMP), %o0
+ ld [%o0 + %lo(CPUINFO_VA+CPUINFO_SYNCFLTDUMP)], %o1
+ ld [%o0 + %lo(CPUINFO_VA+CPUINFO_SYNCFLTDUMP+4)], %o2
wr %l0, PSR_ET, %psr ! reenable traps
@@ -1899,9 +1917,8 @@ memfault_sun4m:
std %i2, [%sp + CCFSZ + 56]
std %i4, [%sp + CCFSZ + 64]
std %i6, [%sp + CCFSZ + 72]
- call _mem_access_fault4m ! mem_access_fault(type, sfsr, sfva,
- ! afsr, afva, &tf);
- add %sp, CCFSZ, %o5 ! (argument: &tf)
+ call _mem_access_fault4m ! mem_access_fault(type,sfsr,sfva,&tf);
+ add %sp, CCFSZ, %o3 ! (argument: &tf)
ldd [%sp + CCFSZ + 0], %l0 ! load new values
ldd [%sp + CCFSZ + 8], %l2
@@ -2586,6 +2603,9 @@ nmi_sun4m:
INCR(_cnt+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1)
#endif
/*
+ * XXX - we don't handle soft nmi, yet.
+ */
+ /*
* Level 15 interrupts are nonmaskable, so with traps off,
* disable all interrupts to prevent recursion.
*/
@@ -2603,23 +2623,15 @@ nmi_sun4m:
std %g2, [%sp + CCFSZ + 0] ! save g2, g3
rd %y, %l4 ! save y
-
- ! now read sync error registers
- set CPUINFO_VA+CPUINFO_FAULTSTATUS, %o0
- ld [%o0], %o0
- jmpl %o0, %o7
- std %g4, [%sp + CCFSZ + 8] ! save g4,g5
+ std %g4, [%sp + CCFSZ + 8] ! save g4,g5
/* Finish stackframe, call C trap handler */
mov %g1, %l5 ! save g1,g6,g7
mov %g6, %l6
mov %g7, %l7
- clr %o5
- set CPUINFO_VA+CPUINFO_MEMERR, %o0
- ld [%o0], %o0
- jmpl %o0, %o7 ! memerr(0, ser, sva, 0, 0)
- clr %o0
+ call _nmi_hard
+ clr %o5
mov %l5, %g1 ! restore g1 through g7
ldd [%sp + CCFSZ + 0], %g2
@@ -5762,81 +5774,75 @@ ENTRY(raise)
/*
- * Read Fault Status registers.
- * On entry: %l1 == PC, %l3 == fault type
- * On exit: %o1 == sync fault status, %o2 == sync fault address
- * %o3 == async fault status, %o4 == async fault address
+ * Read Synchronous Fault Status registers.
+ * On entry: %l1 == PC, %l3 == fault type, %l4 == storage, %l7 == return address
+ * Only use %l5 and %l6.
+ * Note: not C callable.
*/
-ALTENTRY(srmmu_get_fltstatus)
- set SRMMU_SFAR, %o2
- lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first
- set SRMMU_SFSR, %o1
- lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register
-
- clr %o3 ! clear %o3 and %o4
- retl
- clr %o4
-
-ALTENTRY(viking_get_fltstatus)
+ALTENTRY(srmmu_get_syncflt)
+ALTENTRY(hypersparc_get_syncflt)
+ set SRMMU_SFAR, %l5
+ lda [%l5] ASI_SRMMU, %l5 ! sync virt addr; must be read first
+ st %l5, [%l4 + 4] ! => dump.sfva
+ set SRMMU_SFSR, %l5
+ lda [%l5] ASI_SRMMU, %l5 ! get sync fault status register
+ jmp %l7 + 8 ! return to caller
+ st %l5, [%l4] ! => dump.sfsr
+
+ALTENTRY(viking_get_syncflt)
+ALTENTRY(ms1_get_syncflt)
+ALTENTRY(swift_get_syncflt)
+ALTENTRY(turbosparc_get_syncflt)
+ALTENTRY(cypress_get_syncflt)
cmp %l3, T_TEXTFAULT
be,a 1f
- mov %l1, %o2 ! use PC if type == T_TEXTFAULT
+ mov %l1, %l5 ! use PC if type == T_TEXTFAULT
- set SRMMU_SFAR, %o2
- lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first
+ set SRMMU_SFAR, %l5
+ lda [%l5] ASI_SRMMU, %l5 ! sync virt addr; must be read first
1:
- set SRMMU_SFSR, %o1
- lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register
-
- clr %o3 ! clear %o3 and %o4
- retl
- clr %o4
+ st %l5, [%l4 + 4] ! => dump.sfva
-ALTENTRY(ms1_get_fltstatus)
-ALTENTRY(swift_get_fltstatus)
-ALTENTRY(turbosparc_get_fltstatus)
- cmp %l3, T_TEXTFAULT
- be,a 1f
- mov %l1, %o2 ! use PC if type == T_TEXTFAULT
+ set SRMMU_SFSR, %l5
+ lda [%l5] ASI_SRMMU, %l5 ! get sync fault status register
+ jmp %l7 + 8 ! return to caller
+ st %l5, [%l4] ! => dump.sfsr
- set SRMMU_SFAR, %o2
- lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first
-1:
- set SRMMU_SFSR, %o1
- lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register
- clr %o3 ! clear %o3 and %o4
+/*
+ * Read Asynchronous Fault Status registers.
+ * On entry: %o0 == &afsr, %o1 == &afar
+ * Return 0 if async register are present.
+ */
+ALTENTRY(srmmu_get_asyncflt)
+ set SRMMU_AFAR, %o4
+ lda [%o4] ASI_SRMMU, %o4 ! get async fault address
+ set SRMMU_AFSR, %o3 !
+ st %o4, [%o1]
+ lda [%o3] ASI_SRMMU, %o3 ! get async fault status
+ st %o3, [%o0]
retl
- clr %o4
-
-ALTENTRY(cypress_get_fltstatus)
- cmp %l3, T_TEXTFAULT
- be,a 1f
- mov %l1, %o2 ! use PC if type == T_TEXTFAULT
-
- set SRMMU_SFAR, %o2
- lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first
-1:
- set SRMMU_SFSR, %o1
- lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register
+ clr %o0 ! return value
+ALTENTRY(cypress_get_asyncflt)
+ALTENTRY(hypersparc_get_asyncflt)
set SRMMU_AFSR, %o3 ! must read status before fault on HS
lda [%o3] ASI_SRMMU, %o3 ! get async fault status
+ st %o3, [%o0]
+ btst AFSR_AFO, %o3 ! and only read fault address
+ bz 1f ! if valid.
set SRMMU_AFAR, %o4
+ lda [%o4] ASI_SRMMU, %o4 ! get async fault address
+ clr %o0 ! return value
retl
- lda [%o4] ASI_SRMMU, %o4 ! get async fault address
-
-ALTENTRY(hypersparc_get_fltstatus)
- set SRMMU_SFAR, %o2
- lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first
- set SRMMU_SFSR, %o1
- lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register
+ st %o4, [%o1]
+1:
+ retl
+ clr %o0 ! return value
- set SRMMU_AFSR, %o3 ! must read status before fault on HS
- lda [%o3] ASI_SRMMU, %o3 ! get async fault status
- set SRMMU_AFAR, %o4
+ALTENTRY(no_asyncflt_regs)
retl
- lda [%o4] ASI_SRMMU, %o4 ! get async fault address
+ mov 1, %o0 ! return value
ALTENTRY(hypersparc_pure_vcache_flush)
/*
diff --git a/sys/arch/sparc/sparc/memreg.c b/sys/arch/sparc/sparc/memreg.c
index 263b86c7b4b..4d186cd2b5c 100644
--- a/sys/arch/sparc/sparc/memreg.c
+++ b/sys/arch/sparc/sparc/memreg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: memreg.c,v 1.8 2000/01/31 16:06:59 art Exp $ */
+/* $OpenBSD: memreg.c,v 1.9 2000/02/21 17:08:37 art Exp $ */
/* $NetBSD: memreg.c,v 1.21 1997/07/29 09:42:08 fair Exp $ */
/*
@@ -74,7 +74,7 @@ struct cfdriver memreg_cd = {
};
#if defined(SUN4M)
-void hardmemerr4m __P((u_int, u_int, u_int, u_int));
+void hardmemerr4m __P((unsigned int, u_int, u_int, u_int, u_int));
#endif
/*
@@ -142,22 +142,20 @@ memerr4_4c(issync, ser, sva, aer, ava, tf)
#if defined(SUN4M)
/*
* hardmemerr4m: called upon fatal memory error. Print a message and panic.
- * Note that issync is not really an indicator of whether or not the error
- * was synchronous; if it is set, it means that the fsr/faddr pair correspond
- * to the MMU's fault status register; if clear, they correspond to the
- * HyperSPARC asynchronous error register. If issync==2, then both decodings
- * of the error register are printed.
*/
void
-hardmemerr4m(sfsr, sfva, afsr, afva)
+hardmemerr4m(type, sfsr, sfva, afsr, afva)
+ unsigned int type;
u_int sfsr, sfva, afsr, afva;
{
printf("memory error:");
printf("sfsr=%b sfva=0x%x", sfsr, SFSR_BITS, sfva);
printf("afsr=%b afva=0x%x", afsr, AFSR_BITS, afva);
+
if ((sfsr & SFSR_FT) == SFSR_FT_NONE && (afsr & AFSR_AFO) == 0)
return;
+
panic("hard memory error");
}
@@ -173,40 +171,43 @@ static int addroldtop = (int)0xdeadbeef;
static int oldtype = -1;
void
-hypersparc_memerr(type, sfsr, sfva, afsr, afva, tf)
+hypersparc_memerr(type, sfsr, sfva, tf)
unsigned int type;
u_int sfsr;
u_int sfva;
- u_int afsr;
- u_int afva;
struct trapframe *tf;
{
+ u_int afsr;
+ u_int afva;
+
+ (*cpuinfo.get_asyncflt)(&afsr, &afva);
if ((afsr & AFSR_AFO) != 0) { /* HS async fault! */
- printf("HyperSPARC async cache memory failure at phys 0x%x%x. "
- "Ignoring.\n", (afsr & AFSR_AFA) >> AFSR_AFA_RSHIFT,
- afva);
+ printf("HyperSPARC async cache memory failure at phys 0x%x%x\n",
+ (afsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, afva);
if (afva == addrold && (afsr & AFSR_AFA) == addroldtop)
- hardmemerr4m(sfsr, sfva, afsr, afva);
+ goto hard;
oldtype = -1;
addrold = afva;
addroldtop = afsr & AFSR_AFA;
return;
}
- memerr4m(type, sfsr, sfva, afsr, afva, tf);
+hard:
+ hardmemerr4m(type, sfsr, sfva, afsr, afva);
}
void
-viking_memerr(type, sfsr, sfva, afsr, afva, tf)
+viking_memerr(type, sfsr, sfva, tf)
unsigned int type;
u_int sfsr;
u_int sfva;
- u_int afsr;
- u_int afva;
struct trapframe *tf;
{
+ u_int afsr = 0;
+ u_int afva = 0;
+
if (type == T_STOREBUFFAULT) {
/*
* On Supersparc, we try to reenable the store buffers
@@ -216,8 +217,7 @@ viking_memerr(type, sfsr, sfva, afsr, afva, tf)
sfva);
if (oldtype == T_STOREBUFFAULT || addrold == sfva)
- hardmemerr4m(sfsr, sfva, afsr, afva);
- /* NOTREACHED */
+ goto hard;
oldtype = T_STOREBUFFAULT;
addrold = sfva;
@@ -226,45 +226,40 @@ viking_memerr(type, sfsr, sfva, afsr, afva, tf)
sta(SRMMU_PCR, ASI_SRMMU,
lda(SRMMU_PCR, ASI_SRMMU) | VIKING_PCR_SB);
- } else if (type == T_DATAFAULT && !(sfsr & SFSR_FAV)) {
+ } else if (type == T_DATAFAULT && (sfsr & SFSR_FAV) == 0) {
+ /*
+ * bizarre.
+ * XXX: Should handle better. See SuperSPARC manual pg. 9-35
+ */
+ printf("warning: got data fault with no faulting address."
+ " Ignoring.\n");
+
+ if (oldtype == T_DATAFAULT)
+ goto hard;
+ oldtype = T_DATAFAULT;
return;
}
- memerr4m(type, sfsr, sfva, afsr, afva, tf);
+hard:
+ hardmemerr4m(type, sfsr, sfva, afsr, afva);
}
void
-memerr4m(type, sfsr, sfva, afsr, afva, tf)
+memerr4m(type, sfsr, sfva, tf)
unsigned int type;
u_int sfsr;
u_int sfva;
- u_int afsr;
- u_int afva;
struct trapframe *tf;
{
- if (type == T_DATAFAULT && !(sfsr & SFSR_FAV)) { /* bizarre */
- /* XXX: Should handle better. See SuperSPARC manual pg. 9-35 */
- printf("warning: got data fault with no faulting address."
- " Ignoring.\n");
+ u_int afsr;
+ u_int afva;
- if (oldtype == T_DATAFAULT)
- hardmemerr4m(sfsr, sfva, afsr, afva);
- oldtype = T_DATAFAULT;
-
- } else if (type == 0) { /* NMI */
- printf("ERROR: got NMI with sfsr=0x%b, sfva=0x%x, ",
- sfsr, SFSR_BITS, sfva);
- printf("afsr=0x%b, afaddr=0x%x. Retrying...\n",
- afsr, AFSR_BITS, afva);
- if (oldtype == 0 || addrold == sfva)
- hardmemerr4m(sfsr, sfva, afsr, afva);
-
- oldtype = 0;
- addrold = sfva;
- } else {
- /* something we don't know about?!? */
- hardmemerr4m(sfsr, sfva, afsr, afva);
- }
+ /*
+ * No known special cases.
+ * Just get async registers, if any, and report the unhandled case.
+ */
+ if ((*cpuinfo.get_asyncflt)(&afsr, &afva) != 0)
+ afsr = afva = 0;
- return;
+ hardmemerr4m(type, sfsr, sfva, afsr, afva);
}
#endif /* 4m */
diff --git a/sys/arch/sparc/sparc/memreg.h b/sys/arch/sparc/sparc/memreg.h
index d0efa4591ce..e2e63df8cfd 100644
--- a/sys/arch/sparc/sparc/memreg.h
+++ b/sys/arch/sparc/sparc/memreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: memreg.h,v 1.4 2000/01/31 16:06:59 art Exp $ */
+/* $OpenBSD: memreg.h,v 1.5 2000/02/21 17:08:37 art Exp $ */
/* $NetBSD: memreg.h,v 1.4 1996/03/31 22:52:13 pk Exp $ */
/*
@@ -73,6 +73,6 @@ volatile u_int *par_err_reg; /* virtual address; NULL if not yet mapped */
*/
struct trapframe;
void memerr4_4c __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
-void memerr4m __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
-void viking_memerr __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
-void hypersparc_memerr __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
+void memerr4m __P((unsigned, u_int, u_int, struct trapframe *));
+void viking_memerr __P((unsigned, u_int, u_int, struct trapframe *));
+void hypersparc_memerr __P((unsigned, u_int, u_int, struct trapframe *));
diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c
index 4c1b4f7774b..1578c18c957 100644
--- a/sys/arch/sparc/sparc/pmap.c
+++ b/sys/arch/sparc/sparc/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.77 2000/02/19 22:08:51 art Exp $ */
+/* $OpenBSD: pmap.c,v 1.78 2000/02/21 17:08:37 art Exp $ */
/* $NetBSD: pmap.c,v 1.118 1998/05/19 19:00:18 thorpej Exp $ */
/*
@@ -673,6 +673,8 @@ VA2PA(addr)
/* Try each level in turn until we find a valid pte. Otherwise panic */
pte = lda(((u_int)addr & ~0xfff) | ASI_SRMMUFP_L3, ASI_SRMMUFP);
+ /* Unlock fault status; required on Hypersparc modules */
+ (void)lda(SRMMU_SFSR, ASI_SRMMU);
if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE)
return (((pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT) |
((u_int)addr & 0xfff));
diff --git a/sys/arch/sparc/sparc/trap.c b/sys/arch/sparc/sparc/trap.c
index 85d15bb8db0..d2e45119f44 100644
--- a/sys/arch/sparc/sparc/trap.c
+++ b/sys/arch/sparc/sparc/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.21 2000/01/31 16:06:59 art Exp $ */
+/* $OpenBSD: trap.c,v 1.22 2000/02/21 17:08:37 art Exp $ */
/* $NetBSD: trap.c,v 1.58 1997/09/12 08:55:01 pk Exp $ */
/*
@@ -200,7 +200,7 @@ static __inline void userret __P((struct proc *, int, u_quad_t));
void trap __P((unsigned, int, int, struct trapframe *));
static __inline void share_fpu __P((struct proc *, struct trapframe *));
void mem_access_fault __P((unsigned, int, u_int, int, int, struct trapframe *));
-void mem_access_fault4m __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
+void mem_access_fault4m __P((unsigned, u_int, u_int, struct trapframe *));
void syscall __P((register_t, struct trapframe *, register_t));
int ignore_bogus_traps = 0;
@@ -815,12 +815,10 @@ int dfdebug = 0;
#endif
void
-mem_access_fault4m(type, sfsr, sfva, afsr, afva, tf)
+mem_access_fault4m(type, sfsr, sfva, tf)
unsigned type;
u_int sfsr;
u_int sfva;
- u_int afsr;
- u_int afva;
struct trapframe *tf;
{
int pc, psr;
@@ -857,9 +855,9 @@ mem_access_fault4m(type, sfsr, sfva, afsr, afva, tf)
* user's guide for more info, and for a possible solution which we
* don't implement here.
*/
- if ((afsr & AFSR_AFO) != 0 || type == T_STOREBUFFAULT ||
+ if (type == T_STOREBUFFAULT ||
(type == T_DATAFAULT && !(sfsr & SFSR_FAV))) {
- (*cpuinfo.memerr)(type, sfsr, sfva, afsr, afva, tf);
+ (*cpuinfo.memerr)(type, sfsr, sfva, tf);
/*
* If we get here, exit the trap handler and wait for the
* trap to re-occur.
@@ -916,7 +914,8 @@ mem_access_fault4m(type, sfsr, sfva, afsr, afva, tf)
if ((lda((sfva & 0xFFFFF000) | ASI_SRMMUFP_LN, ASI_SRMMUFP) &
SRMMU_TETYPE) != SRMMU_TEPTE)
goto fault; /* Translation bad */
- else goto out; /* Translation OK, retry operation */
+ lda(SRMMU_SFSR, ASI_SRMMU);
+ goto out; /* Translation OK, retry operation */
}
va = trunc_page(sfva);
@@ -1018,7 +1017,7 @@ kfault:
(int)p->p_addr->u_pcb.pcb_onfault : 0;
if (!onfault) {
(void) splhigh();
- printf("data fault: pc=0x%x addr=0x%x sfsr=%b\n",
+ printf("data fault: pc=0x%x sfva=0x%x sfsr=%b\n",
pc, sfva, sfsr, SFSR_BITS);
panic("kernel fault");
/* NOTREACHED */