Author: arty Date: Sat Oct 6 12:34:33 2007 New Revision: 29410
URL: http://svn.reactos.org/svn/reactos?rev=29410&view=rev Log: Added to trunk.
Added: trunk/reactos/lib/ppcmmu/ trunk/reactos/lib/ppcmmu/dummy.c trunk/reactos/lib/ppcmmu/ldscript trunk/reactos/lib/ppcmmu/mmuobject.c trunk/reactos/lib/ppcmmu/mmuobject.h trunk/reactos/lib/ppcmmu/mmutest.c trunk/reactos/lib/ppcmmu/mmuutil.c trunk/reactos/lib/ppcmmu/ppcmmu.mak trunk/reactos/lib/ppcmmu/ppcmmu.rbuild
Added: trunk/reactos/lib/ppcmmu/dummy.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/dummy.c?rev=2941... ============================================================================== (empty)
Added: trunk/reactos/lib/ppcmmu/ldscript URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/ldscript?rev=294... ============================================================================== --- trunk/reactos/lib/ppcmmu/ldscript (added) +++ trunk/reactos/lib/ppcmmu/ldscript Sat Oct 6 12:34:33 2007 @@ -1,0 +1,8 @@ +OUTPUT_FORMAT(elf32-powerpc); + +SECTIONS +{ + .text : { *(.text) } + .data : { *(.data) *(.rodata) } + .bss : { *(.sbss) *(.bss) *(COMMON) } +}
Added: trunk/reactos/lib/ppcmmu/mmuobject.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/mmuobject.c?rev=... ============================================================================== --- trunk/reactos/lib/ppcmmu/mmuobject.c (added) +++ trunk/reactos/lib/ppcmmu/mmuobject.c Sat Oct 6 12:34:33 2007 @@ -1,0 +1,661 @@ +#include <stdarg.h> +#include "ppcmmu/mmu.h" +#include "ppcmmu/mmuutil.h" +#include "mmuobject.h" +#include "helper.h" + +typedef unsigned long ULONG; + +/* + +The MMU Object: +0x00300 -- Data miss +0x00400 -- Instruction miss +0x10000 -- Entry point +... Code +0x20000 -- Physical map (PTE + Process Ptr + Address : 16 bytes) + +4096 / 16 bytes = 256 entries per page +256 pages = 1Megabyte = 1 page table page + +Setup by freeldr and used to build the kernel map, then used by the kernel + +Calling: + +r3 -- Action +r4 .. r6 -- Args + +Actions: +00 Init +01 Map pages +02 erase pages +03 set segment vsid +04 page miss callback +05 inquire page +06 unit test +07 alloc page +08 set memory size +09 get first usable page +10 alloc vsid +11 revoke vsid +*/ + +MmuPageCallback callback; +typedef struct _MmuFreePage { + int page; + struct _MmuFreePage *next; +} MmuFreePage; +typedef struct _MmuFreeTree { + struct _MmuFreeTree *next; +} MmuFreeTree; +typedef struct _MmuVsidTree { + ppc_map_t *leaves[256]; +} MmuVsidTree; +typedef struct _MmuVsidInfo { + int vsid; + struct _MmuVsidInfo *next; + MmuVsidTree *tree[256]; +} MmuVsidInfo; +MmuFreePage *FreeList; +// Pages are allocated one by one until NextPage == RamSize >> PPC_PAGE_SHIFT +// Then we take only from the free list +int Clock = 0, TreeAlloc = 0; +paddr_t RamSize, FirstUsablePage, NextPage; +MmuVsidTree *NextTreePage = 0; +MmuFreeTree *FreeTree; +MmuVsidInfo *Segs[16], *VsidHead = 0; + +extern void fmtout(const char *fmt, ...); +int ptegreload(ppc_trap_frame_t *frame, vaddr_t addr); + +__asm__(".text\n\t" + ".globl mmumain\n\t" + ".globl _mmumain\n\t" + ".globl oldstack\n\t" + "mmumain:\n\t" + "lis 7,oldstack@ha\n\t" + "addi 7,7,oldstack@l\n\t" + "mflr 0\n\t" + "stw 1,0(7)\n\t" + "lis 1,2\n\t" + "subi 1,1,16\n\t" + "stw 0,0(1)\n\t" + "bl _mmumain\n\t" + "lis 7,oldstack@ha\n\t" + "addi 7,7,oldstack@l\n\t" + "lwz 0,0(1)\n\t" + "lwz 1,0(7)\n\t" + "mtlr 0\n\t" + "blr\n" + "oldstack:\n\t" + ".long 0\n\t"); + +__asm__(".text\n\t" + ".globl data_miss_finish_start\n" + "data_miss_finish_start:\n\t" + "lwz 2,8(1)\n\t" + "lwz 3,12(1)\n\t" + "lwz 4,16(1)\n\t" + "lwz 5,20(1)\n\t" + "lwz 6,24(1)\n\t" + "lwz 7,28(1)\n\t" + "lwz 8,32(1)\n\t" + "lwz 9,36(1)\n\t" + "lwz 10,40(1)\n\t" + "lwz 11,44(1)\n\t" + "lwz 12,48(1)\n\t" + "lwz 13,52(1)\n\t" + "lwz 14,56(1)\n\t" + "lwz 15,60(1)\n\t" + "lwz 16,64(1)\n\t" + "lwz 17,68(1)\n\t" + "lwz 18,72(1)\n\t" + "lwz 19,76(1)\n\t" + "lwz 20,80(1)\n\t" + "lwz 21,84(1)\n\t" + "lwz 22,88(1)\n\t" + "lwz 23,92(1)\n\t" + "lwz 24,96(1)\n\t" + "lwz 25,100(1)\n\t" + "lwz 26,104(1)\n\t" + "lwz 27,108(1)\n\t" + "lwz 28,112(1)\n\t" + "lwz 29,116(1)\n\t" + "lwz 30,120(1)\n\t" + "lwz 31,124(1)\n\t" + "lwz 0,128(1)\n\t" + "mtlr 0\n\t" + "lwz 0,132(1)\n\t" + "mtcr 0\n\t" + "lwz 0,136(1)\n\t" + "mtctr 0\n\t" + "lwz 0,0(1)\n\t" + "mfsprg1 1\n\t" + "rfi\n\t"); + +/* + * Trap frame: + * r0 .. r32 + * lr, ctr, srr0, srr1, dsisr + */ +__asm__(".text\n\t" + ".globl data_miss_start\n\t" + ".globl data_miss_end\n\t" + "data_miss_start:\n\t" + "mtsprg1 1\n\t" + "lis 1,2\n\t" + "subi 1,1,256\n\t" + "stw 0,0(1)\n\t" + "mfsprg1 0\n\t" + "stw 0,4(1)\n\t" + "stw 2,8(1)\n\t" + "stw 3,12(1)\n\t" + "stw 4,16(1)\n\t" + "stw 5,20(1)\n\t" + "stw 6,24(1)\n\t" + "stw 7,28(1)\n\t" + "stw 8,32(1)\n\t" + "stw 9,36(1)\n\t" + "stw 10,40(1)\n\t" + "stw 11,44(1)\n\t" + "stw 12,48(1)\n\t" + "stw 13,52(1)\n\t" + "stw 14,56(1)\n\t" + "stw 15,60(1)\n\t" + "stw 16,64(1)\n\t" + "stw 17,68(1)\n\t" + "stw 18,72(1)\n\t" + "stw 19,76(1)\n\t" + "stw 20,80(1)\n\t" + "stw 21,84(1)\n\t" + "stw 22,88(1)\n\t" + "stw 23,92(1)\n\t" + "stw 24,96(1)\n\t" + "stw 25,100(1)\n\t" + "stw 26,104(1)\n\t" + "stw 27,108(1)\n\t" + "stw 28,112(1)\n\t" + "stw 29,116(1)\n\t" + "stw 30,120(1)\n\t" + "stw 31,124(1)\n\t" + "mflr 0\n\t" + "stw 0,128(1)\n\t" + "mfcr 0\n\t" + "stw 0,132(1)\n\t" + "mfctr 0\n\t" + "stw 0,136(1)\n\t" + "mfsrr0 0\n\t" + "stw 0,140(1)\n\t" + "mfsrr1 0\n\t" + "stw 0,144(1)\n\t" + "mfdsisr 0\n\t" + "stw 0,148(1)\n\t" + "mfdar 0\n\t" + "stw 0,152(1)\n\t" + "mfxer 0\n\t" + "stw 0,156(1)\n\t" + "li 3,100\n\t" + "mr 4,1\n\t" + "lis 5,data_miss_finish_start@ha\n\t" + "addi 5,5,data_miss_finish_start@l\n\t" + "mtlr 5\n\t" + "lis 5,_mmumain@ha\n\t" + "addi 5,5,_mmumain@l\n\t" + "mtctr 5\n\t" + "bctr\n" + "data_miss_end:\n\t" + ".space 4"); + +extern int data_miss_end, data_miss_start; + +int _mmumain(int action, void *arg1, void *arg2, void *arg3) +{ + void (*fun)(void *) = arg1; + ppc_trap_frame_t *trap_frame = arg1; + int ret = 0; + + switch(action) + { + case 0: + initme(); + break; + case 1: + ret = mmuaddpage(arg1, (int)arg2); + break; + case 2: + mmudelpage(arg1, (int)arg2); + break; + case 3: + mmusetvsid((int)arg1, (int)arg2, (int)arg3); + break; + case 4: + /* Miss callback = arg1 */ + ret = (int)callback; + callback = arg1; + break; + case 5: + mmugetpage(arg1, (int)arg2); + break; + case 6: + ret = mmunitest(); + break; + case 7: + __asm__("mfmsr 3\n\t" + "ori 3,3,0x30\n\t" + "mtmsr 3\n\t" + "mtsdr1 %0\n\t" + "mr 0,%2\n\t" + "mtctr 0\n\t" + "mr 3,%1\n\t" + "bctrl\n\t" + : : "r" (HTABORG), "r" (arg2), "r" (fun)); + /* BYE ! */ + break; + case 8: + mmusetramsize((paddr_t)arg1); + break; + case 9: + return FirstUsablePage; + case 10: + mmuallocvsid((int)arg1, (int)arg2); + break; + case 11: + mmufreevsid((int)arg1, (int)arg2); + break; + case 100: + if(!ptegreload(trap_frame, trap_frame->dar)) + { + __asm__("mfmsr 3\n\tori 3,3,0x30\n\tmtmsr 3\n\t"); + callback(0,arg1); + } + break; + case 101: + if(!ptegreload(trap_frame, trap_frame->srr0)) + { + __asm__("mfmsr 3\n\tori 3,3,0x30\n\tmtmsr 3\n\t"); + callback(1,arg1); + } + break; + default: + while(1); + } + + return ret; +} + +void outchar(char c) +{ + SetPhysByte(0x800003f8, c); +} + +void outstr(const char *str) +{ + while(*str) outchar(*str); +} + +void outdig(int dig) +{ + if(dig < 10) outchar(dig + '0'); + else outchar(dig - 10 + 'A'); +} + +void outnum(unsigned long num) +{ + int i; + for( i = 0; i < 8; i++ ) + { + outdig(num >> 28); + num <<= 4; + } +} + +void fmtout(const char *str, ...) +{ + va_list ap; + va_start(ap, str); + while(*str) + { + if(*str == '%') + { + if(str[1] == '%') + { + outchar('%'); + } + else if(str[1] == 's') + { + outstr(va_arg(ap, const char *)); + } + else + { + outnum(va_arg(ap, int)); + } + str++; + } + else + { + outchar(*str); + } + str++; + } + va_end(ap); +} + +void mmusetramsize(paddr_t ramsize) +{ + ppc_map_t *last_map = &PpcPageTable[PPC_PAGE_NUMBER(ramsize)]; + if(!RamSize) + { + RamSize = ramsize; + FirstUsablePage = (paddr_t)last_map; + NextPage = PPC_PAGE_NUMBER(FirstUsablePage); + } +} + +void initme() +{ + int i; + int *target, *start; + + for(i = 0; i < HTABSIZ / sizeof(int); i++) + { + ((int *)HTABORG)[i] = 0; + } + + for(target = (int *)0x300, start = &data_miss_start; start < &data_miss_end; start++, target++) + { + SetPhys((paddr_t)target, *start); + } + + (&data_miss_start)[50]++; + + for(target = (int *)0x400, start = &data_miss_start; start < &data_miss_end; start++, target++) + { + SetPhys((paddr_t)target, *start); + } +} + +ppc_map_t *allocpage() +{ + MmuFreePage *FreePage = 0; + + if(NextPage < PPC_PAGE_NUMBER(RamSize)) { + return &PpcPageTable[NextPage++]; + } else { + FreePage = FreeList; + FreeList = FreeList->next; + return ((ppc_map_t*)FreePage); + } +} + +void freepage(ppc_map_t *PagePtr) +{ + MmuFreePage *FreePage = (MmuFreePage*)PagePtr; + PagePtr->proc = PagePtr->addr = 0; + FreePage->next = FreeList; + FreeList = FreePage; +} + +MmuVsidTree *allocvsidtree() +{ + if(FreeTree) + { + MmuVsidTree *result = (MmuVsidTree*)FreeTree; + FreeTree = FreeTree->next; + return result; + } + else if(TreeAlloc >= 3 || !NextTreePage) + { + ppc_map_t *map = allocpage(); + NextTreePage = (MmuVsidTree*)PPC_PAGE_ADDR((map - PpcPageTable)); + TreeAlloc = 1; + return NextTreePage; + } + else + { + return &NextTreePage[TreeAlloc++]; + } +} + +void freevsidtree(MmuVsidTree *tree) +{ + int i; + for(i = 0; i < 256; i++) + if(tree->leaves[i]) + freepage(tree->leaves[i]); + MmuFreeTree *NextFreeTree = (MmuFreeTree *)tree; + NextFreeTree->next = FreeTree; + FreeTree = NextFreeTree; +} + +void *allocvsid(int vsid) +{ + ppc_map_t *map = allocpage(); + MmuVsidInfo *info; + if(!map) return 0; + map->pte.pteh = map->pte.ptel = 0; + info = (MmuVsidInfo*)PPC_PAGE_ADDR((map - PpcPageTable)); + info->vsid = vsid; + info->next = VsidHead; + VsidHead = info; + return info; +} + +void mmuallocvsid(int vsid, int mask) +{ + int i; + for(i = 0; i < 16; i++) + { + if(mask & (1 << i)) + allocvsid((vsid << 4) + i); + } +} + +MmuVsidInfo *findvsid(int vsid) +{ + MmuVsidInfo *info; + for(info = VsidHead; info; info = info->next) + { + if(info->vsid == vsid) return info; + } + return 0; +} + +void freevsid(int vsid) +{ + int i; + MmuVsidInfo *info = findvsid(vsid); + if(!info) return; + ppc_map_t *map = &PpcPageTable[PPC_PAGE_NUMBER((paddr_t)info)]; + for(i = 0; i < 256; i++) + { + if(info->tree[i]) + freevsidtree(info->tree[i]); + } + freepage(map); +} + +void mmufreevsid(int vsid, int mask) +{ + int i; + for(i = 0; i < 16; i++) + { + if(mask & (1 << i)) + allocvsid((vsid << 4) + i); + } +} + +int mmuaddpage(ppc_map_info_t *info, int count) +{ + int i, iva = 0, vsid, phys, virt; + int ptehi; + int ptelo, vsid_table_hi, vsid_table_lo; + ppc_map_t *PagePtr; + MmuVsidInfo *VsidInfo; + MmuVsidTree *VsidTree; + + for(i = 0; i < count; i++) + { + virt = info[i].addr; + vsid = ((info[i].addr >> 28) & 15) | (info[i].proc << 4); + VsidInfo = findvsid(vsid); + + if(!VsidInfo) return -1; + + ptehi = (1 << 31) | (vsid << 7) | ((virt >> 22) & 0x3f); + + if(info[i].phys) { + PagePtr = &PpcPageTable[PPC_PAGE_NUMBER(info[i].phys)]; + } else { + PagePtr = allocpage(); + if(!PagePtr) + { + return 0; + } + } + + phys = PPC_PAGE_ADDR((PagePtr - PpcPageTable)); + ptelo = phys & ~PPC_PAGE_MASK; + + /* Update page data */ + PagePtr->pte.pteh = ptehi; + PagePtr->pte.ptel = ptelo; + PagePtr->proc = info[i].proc; + PagePtr->addr = virt; + + vsid_table_hi = virt >> 20 & 255; + vsid_table_lo = virt >> 12 & 255; + + if(!VsidInfo->tree[vsid_table_hi]) + VsidInfo->tree[vsid_table_hi] = allocvsidtree(); + VsidTree = VsidInfo->tree[vsid_table_hi]; + if(!VsidTree) return 0; + VsidTree->leaves[vsid_table_lo] = PagePtr; + + __asm__("tlbie %0\n\tsync\n\tisync" : : "r" (iva)); + } + return 1; +} + +ppc_pteg_t *PtegFromPage(ppc_map_t *map, int hfun) +{ + if(!map->proc && !map->addr) return 0; + return &PpcHashedPTE[PtegNumber(map->addr, hfun)]; +} + +int PageMatch(vaddr_t addr, ppc_pte_t pte) +{ + int vsid_pte = (pte.pteh >> 7) & 15, api_pte = pte.pteh & 63; + return + (((addr >> 28) & 15) == vsid_pte) && + (((addr >> 22) & 63) == api_pte); +} + +ppc_map_t *mmuvirtmap(vaddr_t addr, int vsid) +{ + int seg = (addr >> 28) & 15; + MmuVsidInfo *seginfo = Segs[seg]; + MmuVsidTree *segtree = 0; + if(!seginfo) return 0; + segtree = seginfo->tree[(addr >> 20) & 255]; + if(!segtree) return 0; + return segtree->leaves[(addr >> 12) & 255]; +} + +void mmudelpage(ppc_map_info_t *info, int count) +{ + int i, j, k, ipa; + ppc_map_t *PagePtr; + ppc_pteg_t *PageEntry; + ppc_pte_t ZeroPte = { 0 }; + + for(i = 0; i < count; i++) + { + if (info[i].phys) + { + ipa = info[i].phys; + PagePtr = &PpcPageTable[ipa]; + info[i].proc = PagePtr->proc; + info[i].addr = PagePtr->addr; + } + else + { + PagePtr = mmuvirtmap(info[i].proc, info[i].addr); + ipa = PPC_PAGE_ADDR(PagePtr - PpcPageTable); + } + + for(j = 0; j < 2; j++) + { + PageEntry = PtegFromPage(PagePtr, j); + for(k = 0; k < 8; k++) + { + if(PageMatch(ipa, PageEntry->block[k])) + { + if(PageEntry->block[k].ptel & 0x100) + info[i].flags |= MMU_PAGE_DIRTY; + PageEntry->block[k] = ZeroPte; + } + } + } + freepage(PagePtr); + __asm__("tlbie %0\n\tsync\n\tisync" : : "r" (info[i].addr)); + } +} + +void mmugetpage(ppc_map_info_t *info, int count) +{ + int i; + ppc_map_t *PagePtr; + + for( i = 0; i < count; i++ ) + { + if(!info[i].addr && !info[i].proc) + { + PagePtr = &((ppc_map_t*)PAGETAB)[info[i].phys]; + info[i].proc = PagePtr->proc; + info[i].addr = PagePtr->addr; + info[i].flags = MMU_ALL_RW; + } else { + vaddr_t addr = info[i].addr; + int vsid = ((addr >> 28) & 15) | (info[i].proc << 4); + PagePtr = mmuvirtmap(info[i].addr, vsid); + if(!PagePtr) + info[i].phys = 0; + else + { + info[i].phys = PPC_PAGE_ADDR(PagePtr - PpcPageTable); + info[i].flags = MMU_ALL_RW; // HACK + } + } + } +} + +void mmusetvsid(int start, int end, int vsid) +{ + int i, sr, s_vsid; + for(i = start; i < end; i++) + { + s_vsid = (vsid << 4) | (i & 15); + sr = (GetSR(i) & ~PPC_VSID_MASK) | s_vsid; + SetSR(i, sr); + Segs[i] = findvsid(s_vsid); + } +} + +int ptegreload(ppc_trap_frame_t *frame, vaddr_t addr) +{ + int hfun = (Clock >> 3) & 1, ptegnum = PtegNumber(addr, hfun); + int vsid = GetSR((addr >> 28) & 15) & PPC_VSID_MASK; + ppc_map_t *map = mmuvirtmap(addr, vsid); + if(!map) return 0; + map->pte.pteh = (map->pte.pteh & ~64) | (hfun << 6); + PpcHashedPTE[ptegnum].block[Clock & 7] = map->pte; +#if 0 + fmtout("Reloading addr %x (phys %x) at %x[%x] (%x:%x)\r\n", + addr, PPC_PAGE_ADDR(map - PpcPageTable), ptegnum, Clock & 15, + PpcHashedPTE[ptegnum].block[Clock&7].pteh, + PpcHashedPTE[ptegnum].block[Clock&7].ptel); +#endif + Clock++; + __asm__("tlbie %0\n\tsync\n\tisync" : : "r" (addr)); + return 1; +}
Added: trunk/reactos/lib/ppcmmu/mmuobject.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/mmuobject.h?rev=... ============================================================================== --- trunk/reactos/lib/ppcmmu/mmuobject.h (added) +++ trunk/reactos/lib/ppcmmu/mmuobject.h Sat Oct 6 12:34:33 2007 @@ -1,0 +1,17 @@ +#ifndef _LIBMMU_MMUOBJECT_H +#define _LIBMMU_MMUOBJECT_H + +MmuPageCallback callback; +void initme(); +void mmusetramsize(paddr_t size); +int mmuaddpage(ppc_map_info_t *info, int count); +void mmudelpage(ppc_map_info_t *info, int count); +void mmugetpage(ppc_map_info_t *info, int count); +void mmusetvsid(int start, int end, int vsid); +void *allocvsid(int); +void mmuallocvsid(int vsid, int mask); +void freevsid(int); +void mmufreevsid(int vsid, int mask); +int mmunitest(); + +#endif/*_LIBMMU_MMUOBJECT_H*/
Added: trunk/reactos/lib/ppcmmu/mmutest.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/mmutest.c?rev=29... ============================================================================== --- trunk/reactos/lib/ppcmmu/mmutest.c (added) +++ trunk/reactos/lib/ppcmmu/mmutest.c Sat Oct 6 12:34:33 2007 @@ -1,0 +1,23 @@ +#include "ppcmmu/mmu.h" +#include "ppcmmu/mmuutil.h" +#include "mmuobject.h" + +int mmunitest() +{ + int ret; + int (*fun)(int ret) = (void *)0x80000000; + ppc_map_info_t info = { 0 }; + volatile int oldmsr, msr = 0x2030; + __asm__("mfmsr 0\n\tstw 0,0(%0)" : : "r" (&oldmsr)); + mmusetvsid(8, 9, 0); + info.flags = MMU_ALL_RW; + info.proc = 0; + info.addr = (vaddr_t)fun; + mmuaddpage(&info, 1); + __asm__("mtmsr %0" : : "r" (msr)); + __asm__("mtsdr1 %0" : : "r" (HTABORG)); + *((int *)fun) = 0x4e800020; + ret = fun(3); + __asm__("mtmsr %0" : : "r" (oldmsr)); + return ret != 3; +}
Added: trunk/reactos/lib/ppcmmu/mmuutil.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/mmuutil.c?rev=29... ============================================================================== --- trunk/reactos/lib/ppcmmu/mmuutil.c (added) +++ trunk/reactos/lib/ppcmmu/mmuutil.c Sat Oct 6 12:34:33 2007 @@ -1,0 +1,411 @@ +#include "ppcmmu/mmu.h" +#include "ppcmmu/mmuutil.h" + +inline int GetMSR() { + register int res asm ("r3"); + __asm__("mfmsr 3"); + return res; +} + +inline int GetDEC() { + register int res asm ("r3"); + __asm__("mfdec 3"); + return res; +} + +__asm__("\t.globl GetPhys\n" + "GetPhys:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "isync\n\t" + "sync\n\t" + "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" + "isync\n\t" + "sync\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl GetPhysHalf\n" + "GetPhysHalf:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "isync\n\t" + "sync\n\t" + "lhz 3,0(3)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" + "isync\n\t" + "sync\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl GetPhysByte\n" + "GetPhysByte:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "isync\n\t" + "sync\n\t" + "lbz 3,0(3)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" + "isync\n\t" + "sync\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl SetPhys\n" + "SetPhys:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "sync\n\t" + "eieio\n\t" + "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,3\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" + "mr 3,4\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl SetPhysHalf\n" + "SetPhysHalf:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "sync\n\t" + "eieio\n\t" + "sth 4,0(3)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,3\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" + "mr 3,4\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl SetPhysByte\n" + "SetPhysByte:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "sync\n\t" + "eieio\n\t" + "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,3\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" + "mr 3,4\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +inline int GetSR(int n) { + register int res = 0; + switch( n ) { + case 0: + __asm__("mfsr %0,0" : "=r" (res)); + break; + case 1: + __asm__("mfsr %0,1" : "=r" (res)); + break; + case 2: + __asm__("mfsr %0,2" : "=r" (res)); + break; + case 3: + __asm__("mfsr %0,3" : "=r" (res)); + break; + case 4: + __asm__("mfsr %0,4" : "=r" (res)); + break; + case 5: + __asm__("mfsr %0,5" : "=r" (res)); + break; + case 6: + __asm__("mfsr %0,6" : "=r" (res)); + break; + case 7: + __asm__("mfsr %0,7" : "=r" (res)); + break; + case 8: + __asm__("mfsr %0,8" : "=r" (res)); + break; + case 9: + __asm__("mfsr %0,9" : "=r" (res)); + break; + case 10: + __asm__("mfsr %0,10" : "=r" (res)); + break; + case 11: + __asm__("mfsr %0,11" : "=r" (res)); + break; + case 12: + __asm__("mfsr %0,12" : "=r" (res)); + break; + case 13: + __asm__("mfsr %0,13" : "=r" (res)); + break; + case 14: + __asm__("mfsr %0,14" : "=r" (res)); + break; + case 15: + __asm__("mfsr %0,15" : "=r" (res)); + break; + } + return res; +} + +inline void SetSR(int n, int val) { + switch( n ) { + case 0: + __asm__("mtsr 0,%0" : : "r" (val)); + break; + case 1: + __asm__("mtsr 1,%0" : : "r" (val)); + break; + case 2: + __asm__("mtsr 2,%0" : : "r" (val)); + break; + case 3: + __asm__("mtsr 3,%0" : : "r" (val)); + break; + case 4: + __asm__("mtsr 4,%0" : : "r" (val)); + break; + case 5: + __asm__("mtsr 5,%0" : : "r" (val)); + break; + case 6: + __asm__("mtsr 6,%0" : : "r" (val)); + break; + case 7: + __asm__("mtsr 7,%0" : : "r" (val)); + break; + case 8: + __asm__("mtsr 8,%0" : : "r" (val)); + break; + case 9: + __asm__("mtsr 9,%0" : : "r" (val)); + break; + case 10: + __asm__("mtsr 10,%0" : : "r" (val)); + break; + case 11: + __asm__("mtsr 11,%0" : : "r" (val)); + break; + case 12: + __asm__("mtsr 12,%0" : : "r" (val)); + break; + case 13: + __asm__("mtsr 13,%0" : : "r" (val)); + break; + case 14: + __asm__("mtsr 14,%0" : : "r" (val)); + break; + case 15: + __asm__("mtsr 15,%0" : : "r" (val)); + break; + } +} + +void GetBat( int bat, int inst, int *batHi, int *batLo ) { + register int bh asm("r3"), bl asm("r4"); + if( inst ) { + switch( bat ) { + case 0: + __asm__("mfibatu 3,0"); + __asm__("mfibatl 4,0"); + break; + case 1: + __asm__("mfibatu 3,1"); + __asm__("mfibatl 4,1"); + break; + case 2: + __asm__("mfibatu 3,2"); + __asm__("mfibatl 4,2"); + break; + case 3: + __asm__("mfibatu 3,3"); + __asm__("mfibatl 4,3"); + break; + } + } else { + switch( bat ) { + case 0: + __asm__("mfdbatu 3,0"); + __asm__("mfdbatl 4,0"); + break; + case 1: + __asm__("mfdbatu 3,1"); + __asm__("mfdbatl 4,1"); + break; + case 2: + __asm__("mfdbatu 3,2"); + __asm__("mfdbatl 4,2"); + break; + case 3: + __asm__("mfdbatu 3,3"); + __asm__("mfdbatl 4,3"); + break; + } + } + *batHi = bh; + *batLo = bl; +} + +#define BATSET(n,t) \ + case n: __asm__("mt" #t "batu " #n ",%0\n\tmt" #t "batl " #n ",%1" \ + : : "r" (batHi), "r" (batLo)); break; + +void SetBat( int bat, int inst, int batHi, int batLo ) { + if( inst ) { + switch( bat ) { + BATSET(0,i); + BATSET(1,i); + BATSET(2,i); + BATSET(3,i); + } + } else { + switch( bat ) { + BATSET(0,d); + BATSET(1,d); + BATSET(2,d); + BATSET(3,d); + } + } + __asm__("isync\n\tsync"); +} + +inline int GetSDR1() { + register int res asm("r3"); + __asm__("mfsdr1 3"); + return res; +} + +inline void SetSDR1( int sdr ) { + int i,j; + __asm__("mtsdr1 3"); + __asm__("sync"); + __asm__("isync"); + + for( i = 0; i < 256; i++ ) { + j = i << 12; + __asm__("tlbie %0,0" : : "r" (j)); + } + __asm__("eieio"); + __asm__("tlbsync"); + __asm__("ptesync"); +} + +inline int BatTranslate( int batu, int batl, int virt ) { + int mask; + if(batu & 0x3fc) + { + mask = ~(0x1ffff | ((batu & 0x3fc)>>2)<<17); + if((batu & 2) && ((batu & mask) == (virt & mask))) + return (batl & mask) | (virt & ~mask); + } else { + mask = ~(0x1ffff | (batl << 17)); + if(!(batl & 0x40) || ((batu & mask) != (virt & mask))) + return (batl & mask) | (virt & ~mask); + } + return -1; +} + +inline int BatHit( int batu, int batl, int virt ) { + return BatTranslate( batu, batl, virt ) != -1; +} + +/* translate address */ +int PpcVirt2phys( vaddr_t virt, int inst ) { + int msr = GetMSR(); + int txmask = inst ? 0x20 : 0x10; + int i, bath, batl, sr, sdr1, physbase, vahi, valo; + int npteg, hash, hashmask, ptehi, ptelo, ptegaddr; + int vsid, pteh, ptevsid, pteapi; + + if( msr & txmask ) { + sr = GetSR( virt >> 28 ); + vsid = sr & 0xfffffff; + vahi = vsid >> 4; + valo = (vsid << 28) | (virt & 0xfffffff); + if( sr & 0x80000000 ) { + return valo; + } + + for( i = 0; i < 4; i++ ) { + GetBat( i, inst, &bath, &batl ); + if( BatHit( bath, batl, virt ) ) { + return BatTranslate( bath, batl, virt ); + } + } + + sdr1 = GetSDR1(); + + physbase = sdr1 & ~0xffff; + hashmask = ((sdr1 & 0x1ff) << 10) | 0x3ff; + hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff); + npteg = hashmask + 1; + + for( pteh = 0; pteh < 0x80; pteh += 64, hash ^= 0x7ffff ) { + ptegaddr = ((hashmask & hash) * 64) + physbase; + + for( i = 0; i < 8; i++ ) { + ptehi = GetPhys( ptegaddr + (i * 8) ); + ptelo = GetPhys( ptegaddr + (i * 8) + 4 ); + + ptevsid = (ptehi >> 7) & 0xffffff; + pteapi = ptehi & 0x3f; + + if( (ptehi & 64) != pteh ) continue; + if( ptevsid != (vsid & 0xffffff) ) continue; + if( pteapi != ((virt >> 22) & 0x3f) ) continue; + + return (ptelo & 0xfffff000) | (virt & 0xfff); + } + } + return -1; + } else { + return virt; + } +} + +int PtegNumber(vaddr_t virt, int hfun) +{ + int sr = GetSR( (virt >> 28) & 0xf ); + int vsid = sr & PPC_VSID_MASK; + return ((((vsid & 0x7ffff) ^ ((virt >> 12) & 0xffff)) ^ (hfun ? -1 : 0)) & ((HTABSIZ - 1) >> 3) & 0x3ff); +}
Added: trunk/reactos/lib/ppcmmu/ppcmmu.mak URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/ppcmmu.mak?rev=2... ============================================================================== --- trunk/reactos/lib/ppcmmu/ppcmmu.mak (added) +++ trunk/reactos/lib/ppcmmu/ppcmmu.mak Sat Oct 6 12:34:33 2007 @@ -1,0 +1,26 @@ +O=$(INTERMEDIATE)/lib/ppcmmu +S=lib/ppcmmu +CC=powerpc-unknown-elf-gcc -I$T/include/reactos/ppcmmu +AR=powerpc-unknown-elf-ar +OBJCOPY=powerpc-unknown-elf-objcopy +LDSCRIPT=-Wl,-T,$S/ldscript +PPCMMU_TARGETS=$O/libppcmmu_code.a + +$O/mmuutil_object.o: $S/mmuutil.c | $O + $(CC) -Iinclude/reactos/libs -g -c -o $@ $S/mmuutil.c + +$O/libppcmmu_code.a: $O/mmuobject.o $O/mmuutil_object.o $O/mmutest.o | $O + $(CC) -Wl,-N -nostartfiles -nostdlib -o $O/mmuobject -Ttext=0x10000 $(LDSCRIPT) -Wl,-u,mmumain -Wl,-u,data_miss_start -Wl,-u,data_miss_end $O/mmuobject.o $O/mmuutil_object.o $O/mmutest.o + $(OBJCOPY) -O binary $O/mmuobject mmucode + $(OBJCOPY) -I binary -O elf32-powerpc -B powerpc:common mmucode $O/mmucode.o + mkdir -p `dirname $@` + $(AR) cr $@ $O/mmucode.o + +$O/mmuobject.o: $S/mmuobject.c $S/mmuobject.h | $O + $(CC) -Iinclude/reactos -Iinclude/reactos/libs -g -c -o $@ $S/mmuobject.c + +$O/mmutest.o: $S/mmutest.c $S/mmuobject.h | $O + $(CC) -Iinclude/reactos/libs -g -c -o $@ $S/mmutest.c + +ppcmmuobject_clean: + rm -f $O/*.o $O/*.a mmucode $O/mmuobject
Added: trunk/reactos/lib/ppcmmu/ppcmmu.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcmmu/ppcmmu.rbuild?re... ============================================================================== --- trunk/reactos/lib/ppcmmu/ppcmmu.rbuild (added) +++ trunk/reactos/lib/ppcmmu/ppcmmu.rbuild Sat Oct 6 12:34:33 2007 @@ -1,0 +1,10 @@ +<?xml version="1.0"?> +<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd"> +<module name="ppcmmu" type="staticlibrary"> + <include base="ppcmmu">.</include> + <define name="__NO_CTYPE_INLINES" /> + <if property="ARCH" value="powerpc"> + <file>mmuutil.c</file> + </if> + <file>dummy.c</file> +</module>