Subject: Support for ARM9E
To: None <port-arm@netbsd.org>
From: Scott <scott_allan@picovex.com>
List: port-arm
Date: 07/27/2006 15:08:02
Hi all,

The processor on my board is an ARM926EJ-S.  NetBSD didn't have support for 
it, so I've gone ahead and added code for it.  My understanding is that the 
ARM9E processors are ARMv5 like the ARM10 processors, and unlike the ARM9 
processors which are ARMv4.  Because of that, I've added CPU_ARM9E and am 
basically just treating it for the most part as CPU_ARM10.  This seems to be 
working just fine, but in doing this, I've ended up with a couple of curiosities.

1) I was having troubles if the cache buffering on my early MMU setup did not 
match the "real" MMU setup.  In summary, if my early translation table 
entries' Buffering bit was not the same as the "real" translation table 
entries', I would end up jumping into lala land shortly after setting the 
"real" TTB.

I finally figured out it was due to the way the setttb functions were written 
in cpufunc_asm_*.S.  Here is the ARM10 code (but other ones are written in the 
same way):

  ENTRY(arm10_setttb)
	stmfd	sp!, {r0, lr}
	bl	_C_LABEL(armv5_idcache_wbinv_all)
	ldmfd	sp!, {r0, lr}

	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */

	mcr	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLBs */
	RET

The call to armv5_idcache_wbinv_all is trying to get the caches into a 
quiescent state for flipping the TTB, but the ldmfd to restore the registers 
is basically undoing some of that work.  I was able to get it to work if I added:

	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I and D caches */

after the ldmfd.  It also worked if I reworked the idcache_wbinv_all function 
to use fewer registers and just stashed r0 and lr in r1 and r2.  Which leads 
us to...

2) The ARM926EJ-S provides some nifty test and clean operations.  From the TRM:

  ... use the following loop to clean the entire DCache:
  tc_loop:	MRC p15, 0, r15, c7, c10, 3	; test and clean
		BNE tc_loop

and:
  ... use the following loop to clean and invalidate the entire DCache:
  tci_loop:	MRC p15, 0, r15, c7, c14, 3	; test clean and invalidate
		BNE tci_loop

I checked the ARM1026EJ-S TRM and it supports these same operations.  The 
question is, does anyone know why NetBSD loops over all the sets/ways instead 
of using the nifty operations?

I'm hoping to push out an ARM9E patch soon, but I'd like to get your thoughts 
on these things first.

Thanks,
   Scott