diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2000-02-21 17:08:38 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2000-02-21 17:08:38 +0000 |
commit | ec50561cbc3916c5a415a251577c7ba50ca1da6e (patch) | |
tree | 873766d1cf5d1762c16dc2b5dc4e269844a123d7 /sys | |
parent | 931e3980342219ff95207bb2c2f0e660dc945f63 (diff) |
The last pieces of hypersparc support.
- Split get_faultstatus into get_syncflt and get_asyncflt.
- Get the syncflt status before setting up the trap frame and put the
results in cpuinfo.syncfltdump (related to the next change).
- unlock the sfsr/sfva after reading from ASI_SRMMUFP (it gets locked if
the translation fails).
- + other interface changes and cleanups.
(most work from NetBSD).
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/sparc/cpu.c | 53 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/cpuvar.h | 20 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/genassym.cf | 7 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/intr.c | 65 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/intreg.h | 7 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/locore.s | 178 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/memreg.c | 93 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/memreg.h | 8 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/pmap.c | 4 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/trap.c | 17 |
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 */ |