1 /*
2  * Copyright (c) 2020 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #if RISCV_MMU
11 
12 #ifndef ASSEMBLY
13 #include <stdint.h>
14 #include <arch/defines.h>
15 
16 // RISC-V specific mmu #defines and structures here
17 typedef uintptr_t riscv_pte_t;
18 #endif
19 
20 #define KB                (1024UL)
21 #define MB                (1024UL*1024UL)
22 #define GB                (1024UL*1024UL*1024UL)
23 
24 // some constants based on our particular implementation
25 #if RISCV_MMU == 48
26 #define RISCV_MMU_PT_LEVELS 4
27 #define RISCV_MMU_PT_SHIFT  9
28 #define RISCV_MMU_PT_ENTRIES 512 // 1 << PT_SHIFT
29 #define RISCV_MMU_CANONICAL_MASK ((1UL << 48) - 1)
30 #define RISCV_MMU_PPN_BITS 56
31 #define RISCV_MMU_PHYSMAP_BASE_VIRT (KERNEL_ASPACE_BASE)
32 #define RISCV_MMU_PHYSMAP_PAGE_SIZE (1UL << 39)
33 #define RISCV_MMU_PHYSMAP_PAGE_COUNT 1
34 #elif RISCV_MMU == 39
35 #define RISCV_MMU_PT_LEVELS 3
36 #define RISCV_MMU_PT_SHIFT  9
37 #define RISCV_MMU_PT_ENTRIES 512 // 1 << PT_SHIFT
38 #define RISCV_MMU_CANONICAL_MASK ((1UL << 39) - 1)
39 #define RISCV_MMU_PPN_BITS 56
40 #define RISCV_MMU_PHYSMAP_BASE_VIRT (KERNEL_ASPACE_BASE)
41 #define RISCV_MMU_PHYSMAP_PAGE_SIZE (1UL << 30)
42 #define RISCV_MMU_PHYSMAP_PAGE_COUNT 64
43 #elif RISCV_MMU == 32
44 #define RISCV_MMU_PT_LEVELS 2
45 #define RISCV_MMU_PT_SHIFT  10
46 #define RISCV_MMU_PT_ENTRIES 1024 // 1 << PT_SHIFT
47 #define RISCV_MMU_CANONICAL_MASK UINT32_MASK
48 #define RISCV_MMU_PPN_BITS 32
49 #define RISCV_MMU_PHYSMAP_BASE_VIRT (KERNEL_ASPACE_BASE)
50 #define RISCV_MMU_PHYSMAP_PAGE_SIZE (1UL << 30)
51 #define RISCV_MMU_PHYSMAP_PAGE_COUNT 1
52 #else
53 #error implement
54 #endif
55 
56 #define RISCV_MMU_PHYSMAP_SIZE      (RISCV_MMU_PHYSMAP_PAGE_SIZE * RISCV_MMU_PHYSMAP_PAGE_COUNT)
57 
58 // number of page table entries for the kernel and user half
59 // TODO: compute directly from KERNEL/USER_ASPACE_SIZE
60 #define RISCV_MMU_USER_PT_ENTRIES 256
61 #define RISCV_MMU_KERNEL_PT_ENTRIES 256
62 
63 // page table bits
64 #define RISCV_PTE_V         (1 << 0) // valid
65 #define RISCV_PTE_R         (1 << 1) // read
66 #define RISCV_PTE_W         (1 << 2) // write
67 #define RISCV_PTE_X         (1 << 3) // execute
68 #define RISCV_PTE_PERM_MASK (0x7 << 1)
69 #define RISCV_PTE_U         (1 << 4) // user
70 #define RISCV_PTE_G         (1 << 5) // global
71 #define RISCV_PTE_A         (1 << 6) // accessed
72 #define RISCV_PTE_D         (1 << 7) // dirty
73 #define RISCV_PTE_RSW_MASK  (3 << 8) // reserved for software
74 #define RISCV_PTE_PPN_SHIFT (10)
75 #define RISCV_PTE_PPN_MASK  (((1UL << (RISCV_MMU_PPN_BITS - PAGE_SIZE_SHIFT)) - 1) << RISCV_PTE_PPN_SHIFT)
76 
77 // riscv PPN is stored shifed over 2 from the natural alignment
78 #define RISCV_PTE_PPN(pte) (((pte) & RISCV_PTE_PPN_MASK) << (PAGE_SIZE_SHIFT - RISCV_PTE_PPN_SHIFT))
79 #define RISCV_PTE_PPN_TO_PTE(paddr) (((paddr) >> PAGE_SIZE_SHIFT) << RISCV_PTE_PPN_SHIFT)
80 
81 // SATP register, contains the current mmu mode, address space id, and
82 // pointer to root page table
83 #define RISCV_SATP_MODE_NONE (0UL)
84 #define RISCV_SATP_MODE_SV32 (1UL)
85 #define RISCV_SATP_MODE_SV39 (8UL)
86 #define RISCV_SATP_MODE_SV48 (9UL)
87 #define RISCV_SATP_MODE_SV57 (10UL)
88 #define RISCV_SATP_MODE_SV64 (11UL)
89 
90 #if __riscv_xlen == 32
91 #define RISCV_SATP_MODE_SHIFT (31)
92 #define RISCV_SATP_ASID_SHIFT (22)
93 #define RISCV_SATP_ASID_SIZE  (9)
94 #define RISCV_SATP_ASID_MASK  ((1 << RISCV_SATP_ASID_SIZE) - 1)
95 
96 #elif __riscv_xlen == 64
97 #define RISCV_SATP_MODE_SHIFT (60)
98 #define RISCV_SATP_ASID_SHIFT (44)
99 #define RISCV_SATP_ASID_SIZE  (16)
100 #define RISCV_SATP_ASID_MASK  ((1UL << RISCV_SATP_ASID_SIZE) - 1)
101 #endif
102 
103 #endif // RISCV_MMU
104 
105