* 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