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