- DBGKD_WAIT_STATE_CHANGE64 is used in KD protocol 5, not number 6 that we use. Proto...
[reactos.git] / reactos / lib / ppcmmu / mmuobject.c
index e09c403..45190bb 100644 (file)
@@ -2,7 +2,6 @@
 #include "ppcmmu/mmu.h"
 #include "ppcmmu/mmuutil.h"
 #include "mmuobject.h"
-#include "helper.h"
 
 typedef unsigned long ULONG;
 
@@ -40,6 +39,8 @@ Actions:
 11 revoke vsid
 */
 
+#define MMU_ADDR_RESERVED ((vaddr_t)-2)
+
 MmuTrapHandler callback[0x30];
 typedef struct _MmuFreePage {
     int page;
@@ -56,7 +57,7 @@ typedef struct _MmuVsidInfo {
     struct _MmuVsidInfo *next;
     MmuVsidTree *tree[256];
 } MmuVsidInfo;
-MmuFreePage *FreeList;
+MmuFreePage *FreeList = 0;
 // 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, GdbAttach = 0, Booted = 0, Vsid[16];
@@ -66,15 +67,21 @@ MmuFreeTree *FreeTree;
 MmuVsidInfo *Segs[16], *VsidHead = 0;
 
 extern void fmtout(const char *fmt, ...);
+extern char *serport;
 int ptegreload(ppc_trap_frame_t *frame, vaddr_t addr);
 void SerialSetUp(int deviceType, void *deviceAddr, int baud);
 int SerialInterrupt(int n, ppc_trap_frame_t *tf);
 void TakeException(int n, ppc_trap_frame_t *tf);
+int mmuisfreepage(paddr_t pageno);
+void copy(void *t, void *s, int b);
+paddr_t mmunewpage();
+void dumpmap();
+void trapcallback(int action, ppc_trap_frame_t *trap_frame);
 
 int _mmumain(int action, void *arg1, void *arg2, void *arg3, void *tf)
 {
     ppc_trap_frame_t *trap_frame = (action >= 0x100) ? tf : arg1;
-    int ret = 0;
+    int ret = 0, tmp, i;
 
     switch(action)
     {
@@ -82,26 +89,24 @@ int _mmumain(int action, void *arg1, void *arg2, void *arg3, void *tf)
     case 3:
        if(!ptegreload(trap_frame, trap_frame->dar))
        {
-           __asm__("mfmsr 3\n\tori 3,3,0x30\n\tmtmsr 3\n\t");
-           if (!callback[action](action,trap_frame)) TakeException(action, trap_frame);
-       }
+            trapcallback(action, trap_frame);
+        }
        break;
     case 4:
        if(!ptegreload(trap_frame, trap_frame->srr0))
-       {
-           __asm__("mfmsr 3\n\tori 3,3,0x30\n\tmtmsr 3\n\t");
-           if (!callback[action](action,trap_frame)) TakeException(action, trap_frame);
-       }
+        {
+            trapcallback(action, trap_frame);
+        }
        break;
 
     case 5:
         /* EE -- Try to get a serial interrupt if debugging enabled, then fall
          * back to primary handler 
          */
-        if (!SerialInterrupt(action, trap_frame)) 
-            callback[action](action, trap_frame);
-        else
-            trap_frame->srr1 |= 0x8000;
+        if (!SerialInterrupt(action, trap_frame) && callback[action]
+        {
+            trapcallback(action, trap_frame);
+        }
         break;
     case 0:
     case 2:
@@ -112,7 +117,7 @@ int _mmumain(int action, void *arg1, void *arg2, void *arg3, void *tf)
     case 0xa:
     case 0xc:
     case 0x20:
-        if (!callback[action](action,trap_frame)) TakeException(action, trap_frame);
+        trapcallback(action, trap_frame);
         break;
 
         /* MMU Functions */
@@ -153,6 +158,17 @@ int _mmumain(int action, void *arg1, void *arg2, void *arg3, void *tf)
     case 0x10b:
        mmufreevsid((int)arg1, (int)arg2);
        break;
+    case 0x10c:
+        ret = mmunewpage();
+        break;
+    case 0x10d:
+        copy(trap_frame, (void *)0xf040, sizeof(*trap_frame));
+        __asm__("mr 1,%0\n\tb trap_finish_start" : : "r" 
+                (((int)trap_frame) - 16));
+        break;
+    case 0x10e:
+        dumpmap();
+        break;
 
     case 0x200:
         SerialSetUp((int)arg1, arg2, 9600);
@@ -165,14 +181,55 @@ int _mmumain(int action, void *arg1, void *arg2, void *arg3, void *tf)
        while(1);
     }
 
+    /* Restore bats when we were called voluntarily.  We may not get a chance
+     * to do this after returning.
+     *
+     * At this point, we're in address space that matches physical space.
+     * We turn off mapping, restore bats, then let rfi switch us back to where
+     * we came.
+     */
+
+    if (action >= 0x100)
+    {
+        __asm__("mfmsr %0" : "=r" (tmp));
+        tmp &= ~0x30;
+        __asm__("mtmsr %0" : : "r" (tmp));
+        
+        for(i = 0; i < 4; i++) {
+            SetBat(i, 0, GetPhys(0xf000 + i * 16), GetPhys(0xf004 + i * 16));
+            SetBat(i, 1, GetPhys(0xf008 + i * 16), GetPhys(0xf00c + i * 16));
+        }
+    }
+
     return ret;
 }
 
+void trapcallback(int action, ppc_trap_frame_t *trap_frame)
+{
+    if ((paddr_t)callback[action] < PAGETAB)
+        callback[action](action, trap_frame);
+    else
+    {
+        int framecopy = 0xf040;
+        copy((void *)framecopy, trap_frame, sizeof(*trap_frame));
+        trap_frame->srr0 = (int)callback[action];
+        trap_frame->srr1 &= 0x7fff;
+        trap_frame->gpr[3] = action;
+        trap_frame->gpr[4] = framecopy;
+        __asm__("mr 1,%0\n\tsubi 1,1,16\n\tb trap_finish_start" : : "r" (trap_frame));
+    }
+}
+
 void outchar(char c)
 {
     SetPhysByte(0x800003f8, c);
 }
 
+void copy(void *target, void *src, int bytes)
+{
+    while(bytes--) *((char *)target++) = *((char *)src++);
+}
+
 void outstr(const char *str)
 {
     while(*str) outchar(*str);
@@ -232,7 +289,7 @@ void mmusetramsize(paddr_t ramsize)
     {
        RamSize = ramsize;
        FirstUsablePage = (paddr_t)last_map;
-       NextPage = PPC_PAGE_NUMBER(FirstUsablePage);
+       NextPage = PPC_PAGE_NUMBER(FirstUsablePage) + 1;
     }
 }
 
@@ -275,16 +332,16 @@ void initme()
     /* Default to hang on unknown exception */
     for(i = 0; i < 30; i++)
     {
-        callback[i] = TakeException;
+        callback[i] = (MmuTrapHandler)TakeException;
         if (i != 1) /* Preserve reset handler */
             copy_trap_handler(i);
     }
 
     /* Serial Interrupt */
-    callback[5] = SerialInterrupt;
+    callback[5] = 0; /* Do nothing until the user asks */
 
     /* Program Exception */
-    callback[6] = TakeException;
+    callback[6] = (MmuTrapHandler)TakeException;
 
     /* Floating point exception */
     callback[8] = fpenable;
@@ -293,20 +350,48 @@ void initme()
     callback[9] = ignore;
 
     /* Single Step */
-    callback[0x20] = TakeException;
+    callback[0x20] = (MmuTrapHandler)TakeException;
 }
 
 ppc_map_t *allocpage()
 {
     MmuFreePage *FreePage = 0;
 
-    if(NextPage < PPC_PAGE_NUMBER(RamSize)) {
-       return &PpcPageTable[NextPage++];
-    } else {
+    if (FreeList)
+    {
+        if ((void *)FreeList == (void *)PpcPageTable)
+        {
+            fmtout("Problem! FreeList: page 0 is free\n");
+            while(1);
+        }
+
        FreePage = FreeList;
        FreeList = FreeList->next;
+        ((ppc_map_t*)FreePage)->addr = MMU_ADDR_RESERVED;
        return ((ppc_map_t*)FreePage);
     }
+    else
+    {
+        while(!mmuisfreepage(NextPage) && NextPage < PPC_PAGE_NUMBER(RamSize))
+        {
+            NextPage++;
+        }
+        if (NextPage < PPC_PAGE_NUMBER(RamSize))
+        {
+            if (NextPage < 0x30)
+            {
+                fmtout("Problem! NextPage is low (%x)\n", NextPage);
+                while(1);
+            }
+            
+            PpcPageTable[NextPage].addr = MMU_ADDR_RESERVED;
+            return &PpcPageTable[NextPage++];
+        }
+        else
+        {
+            return NULL;
+        }
+    }
 }
 
 void freepage(ppc_map_t *PagePtr)
@@ -417,6 +502,9 @@ int mmuaddpage(ppc_map_info_t *info, int count)
 
     for(i = 0; i < count; i++)
     {
+        info[i].phys &= ~PPC_PAGE_MASK;
+        info[i].addr &= ~PPC_PAGE_MASK;
+
        virt = info[i].addr;
        vsid = ((info[i].addr >> 28) & 15) | (info[i].proc << 4);
        VsidInfo = findvsid(vsid);
@@ -438,6 +526,15 @@ int mmuaddpage(ppc_map_info_t *info, int count)
        phys = PPC_PAGE_ADDR((PagePtr - PpcPageTable));
        ptelo = phys & ~PPC_PAGE_MASK;
        
+        if (phys < 0x30000)
+        {
+            /* Should not be allocating physical */
+            fmtout("Allocated physical: %x, logical %x\n", phys, virt);
+            fmtout("PagePtr %x (page %d)\n", PagePtr, i);
+            fmtout("info [ %x %x %x %x ]\n", info[i].proc, info[i].addr, info[i].flags, info[i].phys);
+            while(1);
+        }
+
        /* Update page data */
        PagePtr->pte.pteh = ptehi;
        PagePtr->pte.ptel = ptelo;
@@ -458,6 +555,13 @@ int mmuaddpage(ppc_map_info_t *info, int count)
     return 1;
 }
 
+paddr_t mmunewpage()
+{
+    ppc_map_t *PagePtr = allocpage();
+    if (!PagePtr) return 0;
+    return PPC_PAGE_ADDR(PagePtr - PpcPageTable);
+}
+
 ppc_pteg_t *PtegFromPage(ppc_map_t *map, int hfun)
 {
     if(!map->proc && !map->addr) return 0;
@@ -472,7 +576,7 @@ int PageMatch(vaddr_t addr, ppc_pte_t pte)
        (((addr >> 22) & 63) == api_pte);
 }
 
-ppc_map_t *mmuvirtmap(vaddr_t addr, int vsid)
+ppc_map_t *mmuvirtmap(vaddr_t addr)
 {
     int seg = (addr >> 28) & 15;
     MmuVsidInfo *seginfo = Segs[seg];
@@ -501,7 +605,7 @@ void mmudelpage(ppc_map_info_t *info, int count)
        }
        else
        {
-           PagePtr = mmuvirtmap(info[i].proc, info[i].addr);
+           PagePtr = mmuvirtmap(info[i].addr);
            ipa = PPC_PAGE_ADDR(PagePtr - PpcPageTable);
        }
 
@@ -533,13 +637,13 @@ void mmugetpage(ppc_map_info_t *info, int count)
        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;
+            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);
+           PagePtr = mmuvirtmap(info[i].addr);
            if(!PagePtr)
                info[i].phys = 0;
            else
@@ -551,6 +655,12 @@ void mmugetpage(ppc_map_info_t *info, int count)
     }
 }
 
+int mmuisfreepage(paddr_t pageno)
+{
+    ppc_map_t *PagePtr = PpcPageTable + pageno;
+    return !PagePtr->addr;
+}
+
 void mmusetvsid(int start, int end, int vsid)
 {
     int i, sr, s_vsid;
@@ -561,15 +671,14 @@ void mmusetvsid(int start, int end, int vsid)
        if (Booted)
             SetSR(i, sr);
        Segs[i] = findvsid(s_vsid);
-        Vsid[i] = s_vsid;
+        Vsid[i] = 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);
+    ppc_map_t *map = mmuvirtmap(addr);
     if(!map) return 0;
     map->pte.pteh = (map->pte.pteh & ~64) | (hfun << 6);
     PpcHashedPTE[ptegnum].block[Clock & 7] = map->pte;
@@ -584,6 +693,52 @@ int ptegreload(ppc_trap_frame_t *frame, vaddr_t addr)
     return 1;
 }
 
+void printmap(vaddr_t vaddr, ppc_map_t *map)
+{
+    fmtout("%x: proc %x addr %x\n", 
+           PPC_PAGE_ADDR(map - PpcPageTable), 
+           map->proc, vaddr);
+}
+
+void dumptree(vaddr_t vaddr, MmuVsidTree *tree)
+{
+    int j;
+
+    for (j = 0; j < 256; j++)
+    {
+        if (tree->leaves[j])
+        {
+            printmap(vaddr | (j << 12), tree->leaves[j]);
+        }
+    }
+}
+
+void dumpvsid(MmuVsidInfo *vsid)
+{
+    int i;
+
+    fmtout("vsid %d (%x):\n", vsid->vsid>>4, vsid->vsid<<28);
+    for (i = 0; i < 256; i++)
+    {
+        if (vsid->tree[i])
+        {
+            dumptree((vsid->vsid<<28) | i << 20, vsid->tree[i]);
+        }
+    }
+}
+
+void dumpmap()
+{
+    int i,j;
+    ppc_map_t *map;
+    MmuVsidInfo *vsid;
+    fmtout("Address spaces:\n");
+    for (vsid = VsidHead; vsid; vsid = vsid->next)
+    {
+        dumpvsid(vsid);
+    }
+}
+
 void callkernel(void *fun_ptr, void *arg)
 {
     int i;