Port-pmax archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Is pmax alive?
On Sun, 8 May 2016, Felix Deichmann wrote:
> > NB I'm not a NetBSD expert -- this is a generic analysis based solely on
> > the MIPS architecture and information provided here. Hope this helps
> > anyway.
>
> I used a daily built HEAD INSTALL kernel from nyftp as a start and booted it
> over tftp... (So I don't have the possibility to debug this one with gdb etc.
> probably.)
I think you'd have to use a hardware probe to be able to debug at a level
this low (i.e. TLB Refill), and then obviously you'd have to have a way to
wire it to the CPU in the DECstation (I doubt those old CPUs supported
JTAG or had a debug port).
> Your analysis sounds competent, but I fear I'm not capable of hunting this
> down alone. I'd gladly help and setup a -current environment, test patches
> etc. if I'm provided with code.
OK, I've given it a stab, try the patch below. As I say my experience
with NetBSD is nil, so this code may cause cows to stop giving milk and
all kinds of other weird effects. It may not build even. I can't help
with the cows and milk I'm afraid, but if it doesn't compile, then send me
the error messages and I'll see what I can do.
NB there are numerous bugs with CP0 accesses in locore.S -- all the
changes to this file in the patch below are solely to fix these bugs. To
make a long story short the CP0 read instructions (MFC0/DMFC0) all have a
single-instruction delay slot with MIPS ISAs I through to III, similar to
the MIPS I load delay slot. That is the result of the instruction is
delivered late.
I think the proper way to fix these bugs, without the need to schedule
all the slots manually, is to remove `.set noreorder' from this assembly
source and let the assembler sort it out. I fail to see a good reason to
have this directive here -- there are a few branch delay slots manually
scheduled, but none of them has a data dependency, so these delay-slot
instructions can all be moved ahead of the respective branch or jump and
the assembler will schedule them into the delay slot where possible too,
depending on the MIPS ISA selected for assembly. This will optimise some
other code too, e.g. in `mips_cp0_status_read' the MFC0 instruction can
(and will) be moved into the `JR $ra' instruction's delay slot with the
MIPS IV ISA and up.
I'll leave it up to NetBSD developers to sort this out the way they
consider the best though.
It's impoertant to note however that as a side effect of the bug fix at
line 190 the CU1 bit (bit #29 or MIPS_SR_COP_1_BIT) will I believe remain
set in the Status register -- which is required for the debug part to
work. According to your report `status=0x80010' so this bit was clear and
staring at the sources I couldn't figure out where this happened until I
realised there are these CP0 delay slot fillers missing. Currently the
value of this bit depends on the value returned from `splhigh_noprof', as
the piece of code in question can be reduced to:
jal _C_LABEL(splhigh_noprof) # call `splhigh_noprof'
nop # delay-slot NOP
mfc0 v0, MIPS_COP_0_STATUS # read Status into $v0
or v0, MIPS_SR_INT_IE # old $v0 value used
mtc0 v0, MIPS_COP_0_STATUS # write Status back
With this patch applied you should now see `old_pc' and `old_vaddr'
reported, which will provide values at the entry to the original TLB
Refill exception. These will allow you (or other people reading this
list) to track down the original cause. Don't let the kernel reach
userland or it'll clobber the FPU for user processes.
I suggest reviewing other assembly sources though, to check for missing
delay slot fillers. One of them may well be the cause of the breakage
you've observed. My usual advice however is to avoid `.set noreorder'
where possible and only use it where there's a data dependency between a
jump or branch instruction and the instruction intended for the delay
slot.
NB the instruction counts in `utlb_miss' are wrong too -- there's a gap
between #04 and #07.
HTH,
Maciej
netbsd-pmax-r3k-refill-debug.diff
Index: netbsd/src/sys/arch/mips/mips/locore.S
===================================================================
--- netbsd.orig/src/sys/arch/mips/mips/locore.S
+++ netbsd/src/sys/arch/mips/mips/locore.S
@@ -79,6 +79,7 @@
#if (defined(MIPS3_PLUS) && !defined(MIPS1)) || defined(emips)
/* keep firmware exception handler until we hook. */
mfc0 v0, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
#if defined(emips)
and v0, MIPS_SR_TS | MIPS3_SR_RE
#else
@@ -150,6 +151,7 @@
#endif /* HPCMIPS_L1CACHE_DISABLE */
#else
mfc0 t0, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
#ifdef _LP64
or t0, MIPS_SR_KX # turn on XKSEG and XKPHYS
#endif
@@ -187,6 +189,7 @@
ei
#else
mfc0 v0, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
or v0, MIPS_SR_INT_IE
mtc0 v0, MIPS_COP_0_STATUS
#endif
@@ -226,6 +229,7 @@ NESTED(cpu_switchto, CALLFRAME_SIZ, ra)
#endif
mfc0 t0, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
and t0, MIPS_SR_INT_IE
#if __mips >= 32
teqi t0, 0
@@ -350,6 +354,7 @@ END(cpu_switchto)
softint_cleanup:
#ifdef PARANOIA
mfc0 t1, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
and v0, t1, MIPS_SR_INT_IE
#if __mips >= 32
teqi v0, 0
@@ -393,9 +398,11 @@ NESTED(softint_fast_dispatch, CALLFRAME_
*/
mfc0 t1, MIPS_COP_0_STATUS
#if defined(PARANOIA) && __mips >= 32
+ nop # MFC0 MIPS1-3 delay slot
and v0, t1, MIPS_SR_INT_IE # assert interrupts are on
teqi v0, 0
#elif defined(PARANOID_LOOP)
+ nop # MFC0 MIPS1-3 delay slot
and v0, t1, MIPS_SR_INT_IE # assert interrupts are on
1: beqz v0, 1b
nop
@@ -488,6 +495,7 @@ END(lwp_oncpu)
LEAF(savectx)
#ifdef PARANOIA
mfc0 v0, MIPS_COP_0_STATUS
+ nop # MFC0 MIPS1-3 delay slot
and t0, v0, MIPS_SR_INT_IE
#if __mips >= 32
teqi t0, 0
Index: netbsd/src/sys/arch/mips/mips/locore_mips1.S
===================================================================
--- netbsd.orig/src/sys/arch/mips/mips/locore_mips1.S
+++ netbsd/src/sys/arch/mips/mips/locore_mips1.S
@@ -89,7 +89,10 @@ EXPORT(MIPSX(exceptionentry_start))
*/
VECTOR(MIPSX(utlb_miss), unknown)
.set noat
+ _MFC0 k1, MIPS_COP_0_EXC_PC
_MFC0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
+ mtc1 k1, $f31
+ mtc1 k0, $f30
lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #01: k1=hi of seg0tab
bltz k0, 1f # R3000 chip bug
PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2)#03: k0=seg offset (almost)
Index: netbsd/src/sys/arch/mips/mips/trap.c
===================================================================
--- netbsd.orig/src/sys/arch/mips/mips/trap.c
+++ netbsd/src/sys/arch/mips/mips/trap.c
@@ -202,6 +202,17 @@ trap(uint32_t status, uint32_t cause, va
status, cause, pc, vaddr);
sz -= n;
str += n;
+ {
+ vaddr_t orig_vaddr, orig_pc;
+
+ asm("mfc1 %0, $f30; mfc1 %1, $f31"
+ : "=&r" (orig_vaddr), "=r" (orig_pc));
+ n = snprintf(str, sz, "orig_epc=%#" PRIxVADDR
+ ", orig_vaddr=%#" PRIxVADDR "\n",
+ orig_pc, orig_vaddr);
+ sz -= n;
+ str += n;
+ }
if (USERMODE(status)) {
KASSERT(tf == utf);
n = snprintf(str, sz, "frame=%p usp=%#" PRIxREGISTER
Home |
Main Index |
Thread Index |
Old Index