Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' into ide
[palacios.git] / misc / test_vm / src / geekos / paging.c
index b2837dc..1a9778e 100644 (file)
@@ -2,7 +2,7 @@
  * Paging (virtual memory) support
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
  * Copyright (c) 2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -22,7 +22,7 @@
 //#include <geekos/vfs.h>
 #include <geekos/crc32.h>
 #include <geekos/paging.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 
 /* ----------------------------------------------------------------------
  * flag to indicate if debugging paging code
  */
 int debugFaults = 0;
-#define Debug(args...) if (debugFaults) Print(args)
+#define Debug(args...) if (debugFaults) PrintBoth(args)
 
 
 
-void SerialPrintPD(pde_t *pde)
+void PrintPD(pde_t *pde)
 {
-  int i;
+  uint_t i;
 
-  SerialPrint("Page Directory at %p:\n",pde);
-  for (i=0;i<NUM_PAGE_DIR_ENTRIES && pde[i].present;i++) { 
-    SerialPrintPDE((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),&(pde[i]));
+  PrintBoth("Page Directory at %p:\n",pde);
+  for (i = 0; i < NUM_PAGE_DIR_ENTRIES; i++) { 
+    if (pde[i].present) {
+      if ((i * PAGE_SIZE * 1024) > 0x40000000) {
+       PrintPDE((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),&(pde[i]));
+      }
+    }
   }
 }
 
-void SerialPrintPT(void *starting_address, pte_t *pte) 
+void PrintPT(void *starting_address, pte_t *pte) 
 {
   int i;
 
-  SerialPrint("Page Table at %p:\n",pte);
-  for (i=0;i<NUM_PAGE_TABLE_ENTRIES && pte[i].present;i++) { 
-    SerialPrintPTE(starting_address + PAGE_SIZE*i,&(pte[i]));
+  PrintBoth("Page Table at %p:\n",pte);
+  for (i=0;i<NUM_PAGE_TABLE_ENTRIES;i++) { 
+    if (pte[i].present) {
+      PrintPTE(starting_address + PAGE_SIZE*i,&(pte[i]));
+    }
   }
 }
 
 
-void SerialPrintPDE(void *virtual_address, pde_t *pde)
+void PrintPDE(void *virtual_address, pde_t *pde)
 {
-  SerialPrint("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
+  Print("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
              virtual_address,
              (void*) (pde->pageTableBaseAddr << PAGE_POWER),
              pde->present,
@@ -78,9 +84,9 @@ void SerialPrintPDE(void *virtual_address, pde_t *pde)
              pde->kernelInfo);
 }
   
-void SerialPrintPTE(void *virtual_address, pte_t *pte)
+void PrintPTE(void *virtual_address, pte_t *pte)
 {
-  SerialPrint("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, kernelInfo=%x\n",
+  PrintBoth("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, kernelInfo=%x\n",
              virtual_address,
              (void*)(pte->pageBaseAddr << PAGE_POWER),
              pte->present,
@@ -93,15 +99,19 @@ void SerialPrintPTE(void *virtual_address, pte_t *pte)
 }
 
 
-void SerialDumpPageTables(pde_t *pde)
+void DumpPageTables(pde_t *pde)
 {
-  int i;
+  uint_t i;
   
-  SerialPrint("Dumping the pages starting with the pde page at %p\n",pde);
+  PrintBoth("Dumping the pages starting with the pde page at %p\n",pde);
 
-  for (i=0;i<NUM_PAGE_DIR_ENTRIES && pde[i].present;i++) { 
-    SerialPrintPDE((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),&(pde[i]));
-    SerialPrintPT((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),(void*)(pde[i].pageTableBaseAddr<<PAGE_POWER));
+  for (i = 0; i < NUM_PAGE_DIR_ENTRIES; i++) { 
+    if (pde[i].present) {
+      if ((i * PAGE_SIZE * 1024) >= 0x40000000) {
+       PrintPDE((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), &(pde[i]));
+       PrintPT((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), (void *)(pde[i].pageTableBaseAddr << PAGE_POWER));
+      }
+    }
   }
 }
     
@@ -127,20 +137,20 @@ static void Print_Fault_Info(uint_t address, faultcode_t faultCode)
 
     g_freePageCount+=0;
 
-    SerialPrintLevel(100,"Pid %d, Page Fault received, at address %x (%d pages free)\n",
+    PrintBoth("Pid %d, Page Fault received, at address %x (%d pages free)\n",
         g_currentThread->pid, address, g_freePageCount);
     if (faultCode.protectionViolation)
-        SerialPrintLevel(100,"   Protection Violation, ");
+       PrintBoth("   Protection Violation, ");
     else
-        SerialPrintLevel(100,"   Non-present page, ");
+        PrintBoth("   Non-present page, ");
     if (faultCode.writeFault)
-        SerialPrintLevel(100,"Write Fault, ");
+       PrintBoth("Write Fault, ");
     else
-        SerialPrintLevel(100,"Read Fault, ");
+        PrintBoth("Read Fault, ");
     if (faultCode.userModeFault)
-        SerialPrintLevel(100,"in User Mode\n");
+        PrintBoth("in User Mode\n");
     else
-        SerialPrintLevel(100,"in Supervisor Mode\n");
+        PrintBoth("in Supervisor Mode\n");
 }
 
 /*
@@ -157,13 +167,13 @@ static void Print_Fault_Info(uint_t address, faultcode_t faultCode)
 
     /* Get the address that caused the page fault */
     address = Get_Page_Fault_Address();
-    Debug("Page fault @%lx\n", address);
+    PrintBoth("Page fault @%lx\n", address);
 
     /* Get the fault code */
     faultCode = *((faultcode_t *) &(state->errorCode));
 
     /* rest of your handling code here */
-    SerialPrintLevel(100,"Unexpected Page Fault received\n");
+    PrintBoth("Unexpected Page Fault received\n");
     Print_Fault_Info(address, faultCode);
     Dump_Interrupt_State(state);
     /* user faults just kill the process */
@@ -195,24 +205,24 @@ void Init_VM(struct Boot_Info *bootInfo)
   PrintBoth("Intitialing Virtual Memory\n");
 
   if (checkPaging()) { 
-    SerialPrintLevel(100,"Paging is currently ON\n");
+      PrintBoth("Paging is currently ON\n");
     return ;
   }
 
-  SerialPrintLevel(100,"Paging is currently OFF - initializing the pages for a 1-1 map\n");
+  PrintBoth("Paging is currently OFF - initializing the pages for a 1-1 map\n");
   
   numpages=bootInfo->memSizeKB / (PAGE_SIZE/1024);
   numpagetables = numpages / NUM_PAGE_TABLE_ENTRIES + ((numpages % NUM_PAGE_TABLE_ENTRIES) != 0 );
 
-  SerialPrintLevel(100,"We need %d pages, and thus %d page tables, and one page directory\n",numpages, numpagetables);
+  PrintBoth("We need %d pages, and thus %d page tables, and one page directory\n",numpages, numpagetables);
   
   pd = (pde_t*)Alloc_Page();
   
   if (!pd) { 
-    SerialPrintLevel(100,"We are giving up since we can't allocate a page directory!\n");
+      PrintBoth("We are giving up since we can't allocate a page directory!\n");
     return;
   } else {
-    SerialPrintLevel(100,"Our PDE is at physical address %p\n",pd);
+      PrintBoth("Our PDE is at physical address %p\n",pd);
   }
   
   for (i=0;i<NUM_PAGE_DIR_ENTRIES;i++) { 
@@ -228,9 +238,9 @@ void Init_VM(struct Boot_Info *bootInfo)
     } else {
       pt = (pte_t*)Alloc_Page();
       if (!pt) { 
-       SerialPrintLevel(100,"We are giving up since we can't allocate page table %d\n",i);
+         PrintBoth("We are giving up since we can't allocate page table %d\n",i);
       } else {
-       //SerialPrintLevel(100,"Page Table %d is at physical address %p\n",i,pt);
+       //PrintBoth("Page Table %d is at physical address %p\n",i,pt);
       }
       pd[i].present=1;
       pd[i].flags= VM_READ | VM_WRITE | VM_EXEC | VM_USER;
@@ -264,14 +274,156 @@ void Init_VM(struct Boot_Info *bootInfo)
       }
     }
   }
-  SerialPrintLevel(100,"Done creating 1<->1 initial page tables\n");
-  SerialPrintLevel(100,"Now installing page fault handler\n");
+
+
+  PrintBoth("Done creating 1<->1 initial page tables\n");
+  PrintBoth("Now installing page fault handler\n");
   //  SerialDumpPageTables(pd);
   Install_Interrupt_Handler(14,Page_Fault_Handler);
-  SerialPrintLevel(100,"Now turning on the paging bit!\n");
+  PrintBoth("Now turning on the paging bit!\n");
   Enable_Paging(pd);
-  SerialPrintLevel(100,"We are still alive after paging turned on!\n");
-  SerialPrintLevel(100,"checkPaging returns %d\n",checkPaging());
+  PrintBoth("We are still alive after paging turned on!\n");
+  PrintBoth("checkPaging returns %d\n",checkPaging());
+}
+
+
+
+/* How we test...
+ * 1 <-> 1 mapping of physical memory, 
+ * We assume that physical memory << 1G
+ * we setup the test so that 1G+ is mapped in a testable order
+ * then go through and ensure that all the paging operations work...
+ * The static mapping sits at 1G
+ * The tests are run at 2G
+
+ */
+
+void VM_Test(struct Boot_Info *bootInfo, uint_t num_test_pages) {
+  int i,j;
+
+  pde_t * pd;
+  //pde_t *pde;
+  //  pte_t *pte;
+
+  PrintBoth("Running Paging Test\n");
+
+  pd = Get_PDBR();
+
+
+  void * one_gig = (void *)0x40000000;
+  void * two_gig = (void *)0x80000000;
+
+  /* Set up the 1 GIG static map */
+  ulong_t pde_offset = (((ulong_t)one_gig / PAGE_SIZE) / 1024);    
+  for (i = 0; i < num_test_pages; i += 1024) {
+    pde_t * pde = &(pd[pde_offset + (i / 1024)]);
+    pte_t * pte = (pte_t *)Alloc_Page();
+    memset(pte, 0, PAGE_SIZE);
+
+    pde->present = 1;
+    pde->flags= VM_READ | VM_WRITE | VM_EXEC | VM_USER;
+    pde->pageTableBaseAddr = PAGE_ALLIGNED_ADDR(pte);
+
+    for (j = 0; (j + i) < num_test_pages ; j++) {
+      pte[j].present = 1;
+      pte[j].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER;
+      pte[j].pageBaseAddr = PAGE_ALLIGNED_ADDR(Alloc_Page());
+    }
+  }
+
+  PrintBoth("Setup VM Test static map\n");
+
+
+  /* Setup the Two Gig test area */
+  /* First is just a incrmental mirroring of the 1G area */
+
+  pde_offset = (((ulong_t)two_gig / PAGE_SIZE) / 1024);  
+  
+  for (i = 0; i < num_test_pages; i += 1024) {
+    pde_t * pde = &(pd[pde_offset + (i / 1024)]);
+    pte_t * pte = (pte_t *)Alloc_Page();
+    memset(pte, 0, PAGE_SIZE);
+
+    pde->present = 1;
+    pde->flags= VM_READ | VM_WRITE | VM_EXEC | VM_USER;
+    pde->pageTableBaseAddr = PAGE_ALLIGNED_ADDR(pte);
+
+    for (j = 0; (j + i) < num_test_pages; j++) {
+      pte_t * static_pte = LookupPage(one_gig + (PAGE_SIZE * (j+i)));
+      pte[j].present = 1;
+      pte[j].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER;
+      pte[j].pageBaseAddr = static_pte->pageBaseAddr;
+    }
+  }
+
+  PrintBoth("Setup initial test area\n");
+
+  PrintBoth("Loading CR3\n");
+  Set_PDBR(pd);
+
+  DumpPageTables(pd);
+
+  PrintBoth("Writing to Test Area\n");
+
+  /* Write data to each page in the 2G test area */
+  uint_t * test_ptr = (uint_t *)two_gig;
+  for (i = 0; i < num_test_pages; i++) {
+
+    PrintBoth("Writing %d to %p\n", i, test_ptr);
+    *test_ptr = (uint_t)i;
+    test_ptr += PAGE_SIZE / 4;
+  }
+
+
+  PrintBoth("Reversing Page Mapping\n");
+  
+  /* Reverse 2G test area mapping */
+  
+  pde_offset = (((ulong_t)two_gig / PAGE_SIZE) / 1024);
+
+  for (i = 0; i < num_test_pages; i += 1024) {
+    pde_t * pde = &(pd[pde_offset + (i / 1024)]);
+    pte_t * pte = (pte_t *)(pde->pageTableBaseAddr << 12);
+
+    for (j = 0; (j + i) < num_test_pages ; j++) {
+      pte_t * static_pte = LookupPage(one_gig + (PAGE_SIZE * (num_test_pages - (j+i) - 1)));
+      pte[j].pageBaseAddr = static_pte->pageBaseAddr;
+    } 
+  }
+
+
+  Set_PDBR(pd);
+  
+  PrintBoth("Page Mapping Reversed\n");
+  DumpPageTables(pd);
+
+
+  PrintBoth("Page Consistency Check\n");
+
+  test_ptr = (uint_t *)two_gig;
+  for (i = 0; i < num_test_pages; i++) {
+    if ((*test_ptr) != num_test_pages - (i+1)) {
+      PrintBoth("Consistency Error: (Test Value=%d; Actual Value=%d)\n", (num_test_pages - i), (*test_ptr));
+      while(1);
+    }
+    test_ptr += PAGE_SIZE / 4;
+  }
+
+  PrintBoth("Test Sucessful\n");
+
+
+  PrintBoth("Invalidation Test\n");
+
+
+  Invalidate_PG(two_gig);
+
+  uint_t foo = 0;
+
+  foo = *(uint_t *)two_gig;
+  *(uint_t *)((char *)two_gig + 4) = foo;
+
+
+  PrintBoth("Invalidation Test Successful\n");
 }