Author: arty
Date: Fri Sep 1 13:46:44 2006
New Revision: 23861
URL:
http://svn.reactos.org/svn/reactos?rev=23861&view=rev
Log:
Most of an implementation of page lookup for PPC. Written for
understanding and also to provide a way to inspect virtual to phyiscal
translations. We should and will do this with ofw most of the time, but
we'll have to do it ourselves in the delicate time before jumping to
ntoskrnl.
Modified:
branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c
Modified: branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/boot/freeldr/fr…
==============================================================================
--- branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c (original)
+++ branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c Fri Sep 1 13:46:44
2006
@@ -384,6 +384,20 @@
return res;
}
+int GetPhys( int addr ) {
+ register int res asm ("r3");
+ __asm__("mfmsr 5\n\t"
+ "mr 4,5\n\t"
+ "xor 1,1,1\n\t"
+ "addi 1,1,-1\n\t"
+ "xori 1,1,0x10\n\t"
+ "and 5,1,5\n\t"
+ "mtmsr 5\n\t"
+ "lwz 3,0(3)\n\t"
+ "mtmsr 4");
+ return res;
+}
+
int GetSR(int n) {
register int res asm ("r3");
switch( n ) {
@@ -484,6 +498,75 @@
*batLo = bl;
}
+int GetSDR1() {
+ register int res asm("r3");
+ __asm__("mfsdr1 3");
+ return res;
+}
+
+int BatHit( int bath, int batl, int virt ) {
+ return (virt & 0xfffc0000) == (bath & 0xfffc0000);
+}
+
+int BatTranslate( int bath, int batl, int virt ) {
+ return (virt & 0x3ffff) | (batl & 0xfffc0000);
+}
+
+/* translate address */
+int virt2phys( int virt, int inst ) {
+ int msr = GetMSR();
+ int txmask = inst ? 0x20 : 0x10;
+ if( msr & txmask ) {
+ int i, bath, batl, sr, sdr1, physbase, vahi, valo;
+ int npteg, hash, ptegaddr, hashmask, ptehi, ptelo;
+ int vsid, pteh;
+ for( i = 0; i < 4; i++ ) {
+ GetBat( i, inst, &bath, &batl );
+ if( BatHit( bath, batl, virt ) ) {
+ return BatTranslate( bath, batl, virt );
+ }
+ }
+
+ sr = GetSR( virt >> 28 );
+ vsid = sr & 0xfffffff;
+ valo = (vsid << 28) | (virt & 0xfffffff);
+ if( sr & 0x80000000 )
+ return valo;
+
+ sdr1 = GetSDR1();
+
+ physbase = sdr1 & ~0xffff;
+ vahi = vsid >> 4;
+ npteg = ((sdr1 & 0x1ff) << 10);
+ hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff);
+
+ hashmask = ((sdr1 & 0xffff) << 12) | 0x3ff;
+
+ for( pteh = 0; pteh < 0xff; pteh += 64, hash ^= ~0 ) {
+ ptegaddr = ((hashmask & hash) * 64) + physbase;
+
+ for( i = 0; i < 8; i++ ) {
+ int ptevsid, pteapi;
+
+ ptehi = GetPhys( ptegaddr + (i * 8) );
+ ptelo = GetPhys( ptegaddr + (i * 8) + 4 );
+ ptevsid = (ptehi >> 8) & 0x7fffff;
+ pteapi = ptehi & 0x3f;
+
+ //printf("pte[%d] @ %x = %x:%x\n",
+ //i, ptegaddr + (i * 8), ptehi, ptelo);
+
+ if( (ptehi & 64) != pteh ) continue;
+ if( ptevsid != (vsid & 0x7fffff) ) continue;
+ if( pteapi != ((virt >> 22) & 0x3f) ) continue;
+
+ return (ptelo & 0xfffff000) | (virt & 0xfff);
+ }
+ }
+ return -1;
+ } else return virt;
+}
+
void PpcInit( of_proxy the_ofproxy ) {
int i, len, stdin_handle_chosen, bathi, batlo;
ofproxy = the_ofproxy;
@@ -528,6 +611,9 @@
GetBat( i, 1, &bathi, &batlo );
printf("IBAT%d %x:%x\n", i, bathi, batlo);
}
+
+ printf("virt2phys (0x8000,I) -> %x\n", virt2phys(0x8000,1));
+ printf("virt2phys (0xe00000,D) -> %x\n", virt2phys(0x60000000,0));
MachVtbl.VideoClearScreen = PpcVideoClearScreen;
MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;