* riscv64/riscv64/pmap.h (RISCV_L1_SPAN): Define 2MB superpage size.
  (RISCV_PTE_LEAF_RWX): Define common leaf PTE flags.
* riscv64/riscv64/pmap.c (pmap_bootstrap): Implement Sv39 bootstrap.
  Allocate root table and two L1 tables from the bootstrap heap.
  Map the kernel image at KERNEL_MAP_BASE using 2MB superpages.
  Direct-map physical memory at DIRECT_MAP_VA_BASE for phystokv.
  Activate Sv39 via satp and flush the TLB.
---
 riscv64/riscv64/pmap.c | 65 +++++++++++++++++++++++++++++++++++++++++-
 riscv64/riscv64/pmap.h |  6 ++++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/riscv64/riscv64/pmap.c b/riscv64/riscv64/pmap.c
index dca90a94..d5835554 100644
--- a/riscv64/riscv64/pmap.c
+++ b/riscv64/riscv64/pmap.c
@@ -16,9 +16,11 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <string.h>
 #include <device/dtb.h>
 #include <kern/debug.h>
 #include <mach/vm_prot.h>
+#include <riscv64/proc_reg.h>
 #include <vm/pmap.h>
 #include <vm/vm_page.h>
 
@@ -124,8 +126,69 @@ pmap_discover_physical_memory(struct dtb_node *node)
 void
 pmap_bootstrap(void)
 {
+       pt_entry_t *root, *l1_kernel, *l1_direct;
+       vm_offset_t kernel_phys_end, va;
+       unsigned int idx, num_kernel_pages, num_direct_pages;
+
        kernel_pmap = &kernel_pmap_store;
-       panic("riscv64: pmap_bootstrap not implemented");
+
+       /* Allocate Sv39 root table and two L1 tables from the bootstrap heap.  
*/
+       root = (pt_entry_t *) pmap_grab_page();
+       memset(root, 0, PAGE_SIZE);
+       l1_kernel = (pt_entry_t *) pmap_grab_page();
+       memset(l1_kernel, 0, PAGE_SIZE);
+       l1_direct = (pt_entry_t *) pmap_grab_page();
+       memset(l1_direct, 0, PAGE_SIZE);
+
+       /*
+        * Map the kernel image using 2MB superpages.
+        * Physical range: [__text_start, round_page(_end))
+        * Virtual range:  KERNEL_MAP_BASE + offset
+        */
+       kernel_phys_end = round_page((vm_offset_t) &_end);
+       num_kernel_pages = (kernel_phys_end - (vm_offset_t) &__text_start)
+                          >> (RISCV_VPN1_SHIFT);
+
+       for (idx = 0; idx < num_kernel_pages; idx++) {
+               phys_addr_t pa = (vm_offset_t) &__text_start
+                                + (vm_offset_t) idx * (RISCV_L1_SPAN);
+       l1_kernel[idx] = pa_to_pte(pa) | RISCV_PTE_LEAF_RWX;
+       }
+
+       /*
+        * Direct-map physical memory so phystokv/_kvtophys work.
+        * Map the bootstrap heap range [phys_mem_start, heap_end)
+        * at DIRECT_MAP_VA_BASE.
+        */
+       num_direct_pages = (heap_end - round_page(phys_mem_start))
+                          >> (RISCV_VPN1_SHIFT);
+       if (num_direct_pages == 0)
+               num_direct_pages = 1;
+
+       for (idx = 0; idx < num_direct_pages; idx++) {
+               phys_addr_t pa = round_page(phys_mem_start)
+                                + (vm_offset_t) idx * (RISCV_L1_SPAN);
+       l1_direct[idx] = pa_to_pte(pa) | RISCV_PTE_LEAF_RWX;
+       }
+
+       /*
+        * Install L1 tables in the root:
+        *   root[510] -> l1_kernel  (VA 0xffffffff80000000)
+        *   root[508] -> l1_direct  (VA 0xffffffc000000000)
+        */
+       root[lin2vpn2(KERNEL_MAP_BASE)] =
+               pa_to_pte((phys_addr_t) l1_kernel) | RISCV_PTE_V;
+       root[lin2vpn2(DIRECT_MAP_VA_BASE)] =
+               pa_to_pte((phys_addr_t) l1_direct) | RISCV_PTE_V;
+
+       kernel_pmap->root_table = root;
+
+       /* Activate Sv39.  */
+       satp_write(satp_sv39((phys_addr_t) root));
+       sfence_vma();
+
+       kernel_virtual_start = KERNEL_MAP_BASE;
+       kernel_virtual_end = VM_MAX_KERNEL_ADDRESS;
 }
 
 void
diff --git a/riscv64/riscv64/pmap.h b/riscv64/riscv64/pmap.h
index fbb163ba..2df267f8 100644
--- a/riscv64/riscv64/pmap.h
+++ b/riscv64/riscv64/pmap.h
@@ -35,6 +35,7 @@ typedef phys_addr_t pt_entry_t;
 #define RISCV_VPN_BITS         9
 #define RISCV_PTE_SIZE         8
 #define RISCV_PT_ENTRIES       512
+#define RISCV_L1_SPAN          (2 * 1024 * 1024)       /* 2MB superpage */
 
 #define RISCV_VPN2_SHIFT       30
 #define RISCV_VPN1_SHIFT       21
@@ -65,6 +66,11 @@ typedef phys_addr_t pt_entry_t;
 #define RISCV_PTE_IS_LEAF(pte) \
        ((pte) & (RISCV_PTE_R | RISCV_PTE_W | RISCV_PTE_X))
 
+/* Common leaf flags for a read/write/execute mapping.  */
+#define RISCV_PTE_LEAF_RWX \
+       (RISCV_PTE_V | RISCV_PTE_R | RISCV_PTE_W | RISCV_PTE_X \
+        | RISCV_PTE_A | RISCV_PTE_D)
+
 struct pmap {
        pt_entry_t              *root_table;
        int                     ref_count;
-- 
2.43.0


Reply via email to