Subject: PowerPC G5 port update and Open Firmware woes
To: None <port-macppc@NetBSD.org>
From: Yevgeny Binder <yevbee@comcast.net>
List: port-macppc
Date: 07/08/2006 23:46:44
The past couple of weeks I've been using Sanjay Lal's preliminary  
PowerPC 970 patches to run -current on my dual 2.0 G5 PowerMac. I can  
directly boot his modified INSTALL kernel without a bootloader both  
over the network and from an internal hard disk. Console I/O must be  
done over a serial line, and there is no native support for the  
onboard SATA controller yet.

I've been trying to add display/keyboard console support, with little  
success. The problem lies in the fact that 64-bit PowerPC chips do  
not include the Block Address Translation (BAT) facility. Open  
Firmware requires that the memory region mapped to the display  
framebuffer be marked as cache-inhibited, so that updates are written  
directly to video RAM. The BAT mechanism was used on earlier PowerPC  
chips to accomplish this, by mapping the VRAM's physical addresses to  
virtual memory and setting the I (cache inhibited) and G (guarded)  
flags on the corresponding block table entries.

The only way to do this on the G5 is to use Segment Address  
Translation. This entails bringing up the entire pmap interface. This  
is fine later in the boot process, but since we want to _debug_ pmap  
and other machine-dependent initializations very early in the kernel  
boot sequence, before address translation is enabled, we're out of luck.

To try to tackle this issue, I first switched from the ofb console  
device to ofcons, which is a more low-level interface with less  
overhead. I find the address and size of the framebuffer with Open  
Firmware's 'frame-buffer-adr' method and 'screen' package properties,  
respectively. As a temporary measure, Allen Briggs suggested that I  
manually flush the data cache of the entire framebuffer with a loop  
of dcbf instructions. While this is grossly inefficient and should  
eventually be replaced by a better solution, it does the job, and  
I've gotten console output between the start of initppc() and the  
uvm_page_physload() call within pmap_bootstrap().

After this point, however, pmap_bootstrap() starts to load the 16  
segment registers with a loop of mtsrin instructions. Console output  
stops upon the first load. I don't understand what effect this should  
have: Address translation has not yet been enabled in the kernel when  
this happens, and the Open Firmware client interface routines load up  
their own segment registers anyway. My only guess was that the  
addresses that I pass to dcbf, which I got from Open Firmware (and  
are hence virtual addresses in OFW's context, supposedly), somehow  
become invalid after the mtsrin. But if address translation is off in  
the kernel the whole time through, how can that be?

I took a copy of the openfirmware() assembly routine [1] and modified  
it to call dcbf instead, so that the cache flush occurs in the  
context of Open Firmware. This produces a very strange result: After  
the first character appears on screen, the string "Sttttttttttttttt"  
is displayed, and nothing else happens. (I've posted the routine at  
[2] if anyone would like to check it over for correctness; I would  
certainly appreciate it.)

It may seem overly optimistic to expect stuff to work while pmap is  
still half-hatched, but I see no reason why this particular operation  
in Open Firmware, which supposedly preserves and restores the MMU  
state, shouldn't operate properly.

This adds to my existing suspicion that the OFW client interface is  
not implemented correctly, or at least not on the G5. Although it  
works well enough while the kernel's address translation is off, it  
will still not work even after pmap is fully brought up. The key, I  
believe, lies in the lack of an OFW callback routine. The PowerPC OFW  
binding specs [3] state that when the client operating system brings  
up its address translation mechanism and starts modifying the MMU  
state, it must provide a callback routine in order to continue using  
OFW services. It seems strange to me that the kernel has been working  
correctly on older PPC machines without a callback installed, but I  
believe that one is necessary in order to work on the G5. Then again,  
I'm no expert, so I welcome your thoughts.

I would really appreciate any insights or advice that you can give me  
on these issues.

Thank you,
Yevgeny Binder

References
[1] - see powerpc/oea/ofw_subr.S
[2] - http://netbsd-soc.sourceforge.net/projects/ppcg5/docs/ 
ofw_subr.S.20060708
        line 230 (ofw_flush_cache_range)
[3] - http://playground.sun.com/1275/bindings/ppc/release/ppc-2_1.html