fixes towards risc-v user programs running
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Wed, 1 Jun 2011 11:20:50 +0000 (04:20 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:03 +0000 (17:36 -0700)
kern/arch/riscv/arch.h
kern/arch/riscv/cboot.c
kern/arch/riscv/mmu.h
kern/arch/riscv/pmap.c
kern/arch/riscv/ros/mmu.h

index e8a3cb3..48578aa 100644 (file)
 #define HW_CACHE_ALIGN 64
 #define IOAPIC_BASE    KERN_LOAD_ADDR // upper 2GB reserved (see mmu_init)
 
+#ifdef __riscv64
+# define KERN64
+#endif
+
 void print_cpuinfo(void);
 void show_mapping(uintptr_t start, size_t size);
 void backtrace(void);
index 31e6451..4bcd18a 100644 (file)
@@ -7,7 +7,11 @@
 #include <stdio.h>
 #include <pmap.h>
 
-#define KERNSIZE L1PGSIZE
+#ifdef __riscv64
+# define MAX_KERNBASE_SIZE L1PGSIZE
+#else
+# define MAX_KERNBASE_SIZE ((uintptr_t)(-KERNBASE))
+#endif
 
 static void
 build_multiboot_info(multiboot_info_t* mbi)
@@ -46,25 +50,29 @@ void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys,
 void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys)
 #endif
 {
-       // The boot L1 PT retains the identity mapping [0,KERNSIZE-1],
-       // whereas the post-boot L1 PT does not.
-       for(uintptr_t va = 0; va < KERNSIZE+L1PGSIZE-1; va += L1PGSIZE)
-               l1pt_boot_phys[L1X(va)] = PTE(LA2PPN(va), PTE_KERN_RW | PTE_E);
+       pte_t perm = PTE_KERN_RW | PTE_E;
+
+       // The boot L1 PT retains the identity mapping [0,MAX_KERNBASE_SIZE-1],
+       // whereas the post-boot L1 PT does not.  This is not a "safe" mapping,
+       // since there may be fewer than MAX_KERNBASE_SIZE bytes of physical memory,
+       // so we'll only use this mapping briefly.
+       for(uintptr_t va = 0; va < MAX_KERNBASE_SIZE+L1PGSIZE-1; va += L1PGSIZE)
+               l1pt_boot_phys[L1X(va)] = PTE(LA2PPN(va), perm);
 
        #ifdef __riscv64
-       // for rv64, we need to create an L1 and an L2 PT.
-       
        // kernel can be mapped by a single L2 PT.
-       static_assert(L1X(KERNBASE) == L1X(KERNBASE+KERNSIZE-1));
-       static_assert(KERNSIZE % L2PGSIZE == 0);
+       static_assert(L1X(KERNBASE) == L1X(KERNBASE+MAX_KERNBASE_SIZE-1));
+       static_assert(MAX_KERNBASE_SIZE % L2PGSIZE == 0);
        static_assert(KERNBASE % L2PGSIZE == 0);
 
        // KERNBASE mapping uses one L1 PTD -> L2 PT
        l1pt_phys[L1X(KERNBASE)]      = PTD(l2pt_kernbase_phys);
        l1pt_boot_phys[L1X(KERNBASE)] = PTD(l2pt_kernbase_phys);
 
-       for(uintptr_t va = KERNBASE; va < KERNBASE+KERNSIZE; va += L2PGSIZE)
-               l2pt_kernbase_phys[L2X(va)] = PTE(LA2PPN(va-KERNBASE), PTE_KERN_RW | PTE_E);
+       // don't actually map all the way up to MAX_KERNBASE_SIZE, just to phys. mem size
+       uintptr_t memsize = ROUNDDOWN(mfpcr(PCR_MEMSIZE)*PGSIZE, L2PGSIZE);
+       for(uintptr_t va = KERNBASE; va < KERNBASE+memsize; va += L2PGSIZE)
+               l2pt_kernbase_phys[L2X(va)] = PTE(LA2PPN(va-KERNBASE), perm);
 
        // The kernel code and static data actually are usually not accessed
        // via the KERNBASE mapping, but rather by an aliased "load" mapping in
@@ -81,15 +89,15 @@ void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys)
        l1pt_boot_phys[L1X(KERN_LOAD_ADDR)] = PTD(l2pt_load_phys);
 
        for(uintptr_t va = KERN_LOAD_ADDR; va != 0; va += L2PGSIZE)
-               l2pt_load_phys[L2X(va)] = PTE(LA2PPN(va-KERN_LOAD_ADDR), PTE_KERN_RW|PTE_E);
+               l2pt_load_phys[L2X(va)] = PTE(LA2PPN(va-KERN_LOAD_ADDR), perm);
        #else
        // for rv32, just create the L1 page table.
        static_assert(KERNBASE % L1PGSIZE == 0);
 
        // KERNBASE mapping
-       for(uintptr_t pa = 0; pa < KERNSIZE; pa += L1PGSIZE)
+       for(uintptr_t pa = 0; pa < MAX_KERNBASE_SIZE; pa += L1PGSIZE)
        {
-               pte_t pte = PTE(LA2PPN(pa), PTE_KERN_RW|PTE_E);
+               pte_t pte = PTE(LA2PPN(pa), perm);
                l1pt_phys[L1X(KERNBASE+pa)] = pte;
                l1pt_boot_phys[L1X(KERNBASE+pa)] = pte;
        }
index 15d77ab..26fe834 100644 (file)
@@ -60,7 +60,7 @@
 #define PTD(pa) ((uintptr_t)(pa) | PTE_T)
 
 // Page directory and page table constants
-#define NPTENTRIES (PTSIZE/sizeof(pte_t))
+#define NPTENTRIES (PGSIZE/sizeof(pte_t))
 
 // Page table/directory entry flags.
 #define PTE_T    0x001 // Entry is a page Table descriptor
@@ -88,7 +88,7 @@
 #define PDX(la)    L1X(la)                     // for env stuff
 
 // address in page table entry
-#define PTE_ADDR(pte)  ((physaddr_t) (pte) & (PGSIZE-1))
+#define PTE_ADDR(pte)  ((physaddr_t) (pte) & ~(PGSIZE-1))
 
 // address in page table descriptor
 #define PTD_ADDR(ptd)  PTE_ADDR(ptd)
index 54c80af..8c85245 100644 (file)
@@ -49,22 +49,22 @@ vm_init(void)
 pte_t*
 pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
 {
-  pte_t* ppte[NPTLEVELS];
-       pte_t* pt[NPTLEVELS];
+       pte_t* ppte;
+       pte_t* pt;
 
-       pt[0] = pgdir;
+       pt = pgdir;
        for(int i = 0; i < NPTLEVELS-1; i++)
        {
-         // this code relies upon the fact that all page tables are the same size
-         uintptr_t idx = (uintptr_t)va >> (L1PGSHIFT - i*(L1PGSHIFT-L2PGSHIFT));
+               // this code relies upon the fact that all page tables are the same size
+               uintptr_t idx = (uintptr_t)va >> (L1PGSHIFT - i*(L1PGSHIFT-L2PGSHIFT));
                idx = idx & (NPTENTRIES-1);
 
-               ppte[i] = &pt[i][idx];
+               ppte = &pt[idx];
 
-               if(*ppte[i] & PTE_E)
-                       return ppte[i];
+               if(*ppte & PTE_E)
+                       return ppte;
 
-       if(!(*ppte[i] & PTE_T))
+               if(!(*ppte & PTE_T))
                {
                        if(!create)
                                return NULL;
@@ -74,15 +74,15 @@ pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
                                return NULL;
                        memset(page2kva(new_table), 0, PGSIZE);
 
-                       *ppte[i] = PTD(page2pa(new_table));
+                       *ppte = PTD(page2pa(new_table));
                }
 
-               pt[i+1] = (pte_t*)KADDR(PTD_ADDR(*ppte[i]));
+               pt = (pte_t*)KADDR(PTD_ADDR(*ppte));
        }
 
        uintptr_t idx = (uintptr_t)va >> (L1PGSHIFT - (NPTLEVELS-1)*(L1PGSHIFT-L2PGSHIFT));
        idx = idx & (NPTENTRIES-1);
-  return &pt[NPTLEVELS-1][idx];
+  return &pt[idx];
 }
 
 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
index 4d6b11d..1cd34c5 100644 (file)
@@ -15,6 +15,7 @@
 # define L4PGSHIFT                    (12)
 # define L4PGSIZE        (1L << L4PGSHIFT)
 # define PGSHIFT                 L4PGSHIFT
+# define PTSIZE                   L2PGSIZE
 #else
 # define KERNBASE               0x80000000
 # define KERN_LOAD_ADDR           KERNBASE
 # define L2PGSHIFT                      12
 # define L2PGSIZE         (1 << L2PGSHIFT)
 # define PGSHIFT                 L2PGSHIFT
+# define PTSIZE                   L1PGSIZE
 #endif
 
 #define PGSIZE (1 << PGSHIFT)
-#define PTSIZE PGSIZE
 
 #ifndef __ASSEMBLER__
 typedef unsigned long pte_t;