new 64b kernel memory map (not userspace yet)
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Wed, 1 Jun 2011 02:12:02 +0000 (19:12 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:03 +0000 (17:36 -0700)
in short, KERNBASE = 0xFFF8 0000 0000 0000 (the most negative 48b addr),
and KERNSIZE = L1PGSIZE (512 GB).  kernel static symbols are referenced
through the KERN_LOAD_ADDR mapping, which is the upper 2GB, i.e.
KERN_LOAD_ADDR = 0xFFFF FFFF 8000 0000.  since all addresses in this range
are canonicalized signed 32-bit numbers, kernel symbols can be referenced
with 32b sign-extended addresses, reducing code size.

kern/arch/i686/ros/mmu.h
kern/arch/riscv/arch.h
kern/arch/riscv/boot.S
kern/arch/riscv/cboot.c
kern/arch/riscv/ros/mmu.h
kern/arch/riscv/trap.c
kern/arch/sparc/ros/mmu.h
kern/include/pmap.h

index 4d6cec1..6f9124b 100644 (file)
@@ -8,6 +8,7 @@ typedef unsigned long pde_t;
 
 // All physical memory mapped at this address
 #define KERNBASE        0xC0000000
+#define KERN_LOAD_ADDR  KERNBASE
 
 // Use this if needed in annotations
 #define IVY_KERNBASE (0xC000U << 16)
index 8941a47..e8a3cb3 100644 (file)
@@ -11,7 +11,7 @@
 
 /* Arch Constants */
 #define HW_CACHE_ALIGN 64
-#define IOAPIC_BASE    LOAD_ADDR // upper 2GB reserved (see mmu_init)
+#define IOAPIC_BASE    KERN_LOAD_ADDR // upper 2GB reserved (see mmu_init)
 
 void print_cpuinfo(void);
 void show_mapping(uintptr_t start, size_t size);
index 6947dbe..b67af71 100644 (file)
@@ -38,7 +38,7 @@ _start:
   // set up stack and terminate frame pointer for backtracing
   li     $fp, 0
   la     $sp, bootstacktop
-  li     $t1, LOAD_ADDR
+  li     $t1, KERN_LOAD_ADDR
   sub    $sp, $sp, $t1
 
   // set up initial page mappings
@@ -47,8 +47,10 @@ _start:
   la     $a1, l1pt_boot
   sub    $a1, $a1, $t1
 #ifdef __riscv64
-  la     $a2, l2pt
+  la     $a2, l2pt_kernbase
   sub    $a2, $a2, $t1
+  la     $a3, l2pt_load
+  sub    $a3, $a3, $t1
 #endif
   jal    pagetable_init
 
@@ -70,7 +72,7 @@ notcore0:
   add    $t0, $t0, 1
   sll    $t0, $t0, KSTKSHIFT
   add    $sp, $sp, $t0
-  li     $t1, LOAD_ADDR
+  li     $t1, KERN_LOAD_ADDR
   sub    $sp, $sp, $t1
   
   // turn on MMU
@@ -79,7 +81,7 @@ notcore0:
   jal    mmu_init
 
   // relocate stack and call into C code
-  li     $t1, LOAD_ADDR
+  li     $t1, KERN_LOAD_ADDR
   add    $sp, $sp, $t1
   lui    $t0, %hi(smp_init)
   jalr.j $t0, %lo(smp_init)
index fce5190..31e6451 100644 (file)
@@ -7,10 +7,18 @@
 #include <stdio.h>
 #include <pmap.h>
 
+#define KERNSIZE L1PGSIZE
+
 static void
 build_multiboot_info(multiboot_info_t* mbi)
 {
-       long memsize_kb = mfpcr(PCR_MEMSIZE)*(PGSIZE/1024);
+       long memsize = mfpcr(PCR_MEMSIZE)*PGSIZE;
+       // the current memory mapping requires the kernel be mapped by a single
+       // L2 page table.
+       memsize = MIN(memsize, L1PGSIZE);
+       memsize = ROUNDDOWN(memsize, L2PGSIZE);
+
+       long memsize_kb = memsize/1024;
        long basemem_kb = EXTPHYSMEM/1024;
 
        memset(mbi, 0, sizeof(mbi));
@@ -20,19 +28,20 @@ build_multiboot_info(multiboot_info_t* mbi)
        mbi->mem_upper = memsize_kb - basemem_kb;
 }
 
-#define KERNSIZE ((uintptr_t)(-KERNBASE))
-
 pte_t l1pt_boot[NPTENTRIES]
       __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
 pte_t l1pt[NPTENTRIES]
       __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
 #ifdef __riscv64
-pte_t l2pt[NPTENTRIES]
+pte_t l2pt_kernbase[NPTENTRIES]
+      __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
+pte_t l2pt_load[NPTENTRIES]
       __attribute__((section(".data"))) __attribute__((aligned(PGSIZE)));
 #endif
 
 #ifdef __riscv64
-void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys, pte_t* l2pt_phys)
+void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys,
+                    pte_t* l2pt_kernbase_phys, pte_t* l2pt_load_phys)
 #else
 void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys)
 #endif
@@ -45,27 +54,34 @@ void pagetable_init(pte_t* l1pt_phys, pte_t* l1pt_boot_phys)
        #ifdef __riscv64
        // for rv64, we need to create an L1 and an L2 PT.
        
-       // kernel can be mapped by a single L1 page and several L2 pages
-       static_assert(KERNSIZE <= L1PGSIZE);
+       // kernel can be mapped by a single L2 PT.
+       static_assert(L1X(KERNBASE) == L1X(KERNBASE+KERNSIZE-1));
+       static_assert(KERNSIZE % L2PGSIZE == 0);
        static_assert(KERNBASE % L2PGSIZE == 0);
 
-       // highest L1 page contains KERNBASE mapping
-       l1pt_phys[L1X(KERNBASE)] = l1pt_boot_phys[L1X(KERNBASE)] = PTD(l2pt_phys);
+       // 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);
 
-       // KERNBASE mapping with 1GB pages
-       for(uintptr_t va = KERNBASE; va < LOAD_ADDR; va += L2PGSIZE)
-               l2pt_phys[L2X(va)] = PTE(LA2PPN(va-KERNBASE), PTE_KERN_RW | PTE_E);
+       for(uintptr_t va = KERNBASE; va < KERNBASE+KERNSIZE; va += L2PGSIZE)
+               l2pt_kernbase_phys[L2X(va)] = PTE(LA2PPN(va-KERNBASE), PTE_KERN_RW | PTE_E);
 
        // The kernel code and static data actually are usually not accessed
-       // via the KERNBASE mapping, but rather by an aliased mapping in the
-       // upper 2GB (0xFFFFFFFF80000000 and up).
+       // via the KERNBASE mapping, but rather by an aliased "load" mapping in
+       // the upper 2GB (0xFFFFFFFF80000000 and up).
        // This simplifies the linking model by making all static addresses
        // representable in 32 bits.
        // In RISC-V, this allows static addresses to be loaded with a two
        // instruction sequence, rather than 8 instructions worst-case.
-       static_assert(LOAD_ADDR % L2PGSIZE == 0);
-       for(uintptr_t va = LOAD_ADDR; va != 0; va += L2PGSIZE)
-               l2pt_phys[L2X(va)] = PTE(LA2PPN(va-LOAD_ADDR), PTE_KERN_RW|PTE_E);
+       static_assert(L1X(KERN_LOAD_ADDR) > L1X(KERNBASE));
+       static_assert(KERN_LOAD_ADDR % L2PGSIZE == 0);
+       static_assert((uintptr_t)(-KERN_LOAD_ADDR) <= L1PGSIZE);
+
+       l1pt_phys[L1X(KERN_LOAD_ADDR)]      = PTD(l2pt_load_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);
        #else
        // for rv32, just create the L1 page table.
        static_assert(KERNBASE % L1PGSIZE == 0);
@@ -96,5 +112,5 @@ cmain()
 
        extern void kernel_init(multiboot_info_t *mboot_info);
        // kernel_init expects a pre-relocation mbi address
-       kernel_init((multiboot_info_t*)((uint8_t*)&mbi - LOAD_ADDR));
+       kernel_init((multiboot_info_t*)PADDR(&mbi));
 }
index 2737d1e..4d6b11d 100644 (file)
@@ -3,33 +3,30 @@
 
 // All physical memory mapped at this address
 #ifdef __riscv64
-# define KERNBASE  0xFFFFFF8000000000
-# define LOAD_ADDR 0xFFFFFFFF80000000
-# define NPTLEVELS                  4
-# define L1PGSHIFT         (12+9+9+9)
-# define L1PGSIZE   (1L << L1PGSHIFT)
-# define L2PGSHIFT           (12+9+9)
-# define L2PGSIZE   (1L << L2PGSHIFT)
-# define L3PGSHIFT             (12+9)
-# define L3PGSIZE   (1L << L3PGSHIFT)
-# define L4PGSHIFT               (12)
-# define L4PGSIZE   (1L << L4PGSHIFT)
-# define PGSHIFT            L4PGSHIFT
-# define KPGSHIFT           L3PGSHIFT
+# define KERNBASE       0xFFFF800000000000
+# define KERN_LOAD_ADDR 0xFFFFFFFF80000000
+# define NPTLEVELS                       4
+# define L1PGSHIFT              (12+9+9+9)
+# define L1PGSIZE        (1L << L1PGSHIFT)
+# define L2PGSHIFT                (12+9+9)
+# define L2PGSIZE        (1L << L2PGSHIFT)
+# define L3PGSHIFT                  (12+9)
+# define L3PGSIZE        (1L << L3PGSHIFT)
+# define L4PGSHIFT                    (12)
+# define L4PGSIZE        (1L << L4PGSHIFT)
+# define PGSHIFT                 L4PGSHIFT
 #else
-# define KERNBASE          0x80000000
-# define LOAD_ADDR         0x80000000
-# define NPTLEVELS                  2
-# define L1PGSHIFT            (12+10)
-# define L1PGSIZE    (1 << L1PGSHIFT)
-# define L2PGSHIFT                 12
-# define L2PGSIZE    (1 << L2PGSHIFT)
-# define PGSHIFT            L2PGSHIFT
-# define KPGSHIFT           L1PGSHIFT
+# define KERNBASE               0x80000000
+# define KERN_LOAD_ADDR           KERNBASE
+# define NPTLEVELS                       2
+# define L1PGSHIFT                 (12+10)
+# define L1PGSIZE         (1 << L1PGSHIFT)
+# define L2PGSHIFT                      12
+# define L2PGSIZE         (1 << L2PGSHIFT)
+# define PGSHIFT                 L2PGSHIFT
 #endif
 
 #define PGSIZE (1 << PGSHIFT)
-#define KPGSIZE (1 << KPGSHIFT)
 #define PTSIZE PGSIZE
 
 #ifndef __ASSEMBLER__
index 84584ea..2cf08ae 100644 (file)
@@ -335,7 +335,7 @@ handle_fault_fetch(trapframe_t* state)
        if(in_kernel(state))
        {
                print_trapframe(state);
-               panic("Load Page Fault in the Kernel at 0x%08x!", state->badvaddr);
+               panic("Load Page Fault in the Kernel at %p!", state->badvaddr);
        }
        
        if(handle_page_fault(current, state->badvaddr, PROT_READ))
@@ -348,7 +348,7 @@ handle_fault_load(trapframe_t* state)
        if(in_kernel(state))
        {
                print_trapframe(state);
-               panic("Load Page Fault in the Kernel at 0x%08x!", state->badvaddr);
+               panic("Load Page Fault in the Kernel at %p!", state->badvaddr);
        }
        
        if(handle_page_fault(current, state->badvaddr, PROT_READ))
@@ -361,7 +361,7 @@ handle_fault_store(trapframe_t* state)
        if(in_kernel(state))
        {
                print_trapframe(state);
-               panic("Store Page Fault in the Kernel at 0x%08x!", state->badvaddr);
+               panic("Store Page Fault in the Kernel at %p!", state->badvaddr);
        }
        
        if(handle_page_fault(current, state->badvaddr, PROT_WRITE))
index 2435323..6866fda 100644 (file)
@@ -3,6 +3,7 @@
 
 // All physical memory mapped at this address
 #define KERNBASE        0x80000000
+#define KERN_LOAD_ADDR  KERNBASE
 
 // Use this if needed in annotations
 #define IVY_KERNBASE (0x8000U << 16)
index 379624f..bddd3be 100644 (file)
  */
 #define PADDR(kva)                                             \
 ({                                                             \
-       physaddr_t __m_kva = (physaddr_t) (kva);                \
+       physaddr_t __m_pa, __m_kva = (physaddr_t) (kva);                \
        if (__m_kva < KERNBASE)                                 \
-               panic("PADDR called with invalid kva %08lx", __m_kva);\
-       __m_kva - KERNBASE;                                     \
+               panic("PADDR called with invalid kva %p", __m_kva);\
+       if(__m_kva >= KERN_LOAD_ADDR)                                   \
+               __m_pa = __m_kva - KERN_LOAD_ADDR;                                      \
+       else                                    \
+               __m_pa = __m_kva - KERNBASE;                                    \
+       __m_pa; \
 })
 
 /* This macro takes a physical address and returns the corresponding kernel
@@ -44,7 +48,7 @@
        physaddr_t __m_pa = (pa);                               \
        size_t __m_ppn = LA2PPN(__m_pa);                        \
        if (__m_ppn >= npages)                                  \
-               warn("KADDR called with invalid pa %08lx", __m_pa);\
+               warn("KADDR called with invalid pa %p", __m_pa);\
        (void*TRUSTED) (__m_pa + KERNBASE);                             \
 })
 
@@ -83,7 +87,7 @@ void* mmio_alloc(physaddr_t pa, size_t size);
 static inline page_t *SAFE ppn2page(size_t ppn)
 {
        if( ppn >= npages )
-               warn("ppn2page called with ppn (%08u) larger than npages", ppn);
+               warn("ppn2page called with ppn (%08lu) larger than npages", ppn);
        return &(pages[ppn]);
 }
 
@@ -100,7 +104,7 @@ static inline physaddr_t page2pa(page_t *pp)
 static inline page_t*COUNT(1) pa2page(physaddr_t pa)
 {
        if (LA2PPN(pa) >= npages)
-               warn("pa2page called with pa (0x%08x) larger than npages", pa);
+               warn("pa2page called with pa (%p) larger than npages", pa);
        return &pages[LA2PPN(pa)];
 }