550W Document
550W, a high-end OS
pgtable.h
浏览该文件的文档.
1 #pragma once
2 
3 #include <asm/sbi.h>
4 #include <common/types.h>
5 
6 #define SATP_MODE_SV39 8
7 #define SATP_MODE_SV48 9
8 
9 #define SATP_ASID_SHIFT 44lu
10 #define SATP_MODE_SHIFT 60lu
11 
12 #define NORMAL_PAGE_SHIFT 12lu
13 #define NORMAL_PAGE_SIZE (1lu << NORMAL_PAGE_SHIFT)
14 #define LARGE_PAGE_SHIFT 21lu
15 #define LARGE_PAGE_SIZE (1lu << LARGE_PAGE_SHIFT)
16 
17 typedef uint64_t pte_t;
18 typedef uint64_t *pagetable_t; // 512 PTEs
19 
20 static inline void local_flush_tlb_all(void) {
21  __asm__ __volatile__("sfence.vma" : : : "memory");
22 }
23 
24 /* Flush one page from local TLB */
25 static inline void local_flush_tlb_page(unsigned long addr) {
26  __asm__ __volatile__("sfence.vma %0" : : "r"(addr) : "memory");
27 }
28 
29 static inline void local_flush_icache_all(void) {
30  asm volatile("fence.i" ::: "memory");
31 }
32 
33 static inline void flush_icache_all(void) {
34  local_flush_icache_all();
35  sbi_remote_fence_i(NULL);
36 }
37 
38 static inline void flush_tlb_all(void) {
39  local_flush_tlb_all();
40  sbi_remote_sfence_vma(NULL, 0, -1);
41 }
42 
43 static inline void flush_tlb_page_all(unsigned long addr) {
44  local_flush_tlb_page(addr);
45  sbi_remote_sfence_vma(NULL, 0, -1);
46 }
47 
48 static inline void set_satp(unsigned mode, unsigned asid, unsigned long ppn) {
49  unsigned long __v = (unsigned long)(((unsigned long)mode << SATP_MODE_SHIFT) | ((unsigned long)asid << SATP_ASID_SHIFT) | ppn);
50  __asm__ __volatile__("sfence.vma\ncsrw satp, %0" : : "rK"(__v) : "memory");
51 }
52 
53 #define KERNEL_START_PA 0x80200000lu
54 #define KERNEL_END_PA 0x80600000lu
55 #define PGDIR_PA 0x82000000lu // use bootblock's page as PGDIR
56 
57 /*
58  * PTE format:
59  * | XLEN-1 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
60  * PFN reserved for SW D A G U X W R V
61  */
62 
63 #define _PAGE_ACCESSED_OFFSET 6
64 
65 #define _PAGE_PRESENT ((uint64_t)1 << 0)
66 #define _PAGE_READ ((uint64_t)1 << 1) /* Readable */
67 #define _PAGE_WRITE ((uint64_t)1 << 2) /* Writable */
68 #define _PAGE_EXEC ((uint64_t)1 << 3) /* Executable */
69 #define _PAGE_USER ((uint64_t)1 << 4) /* User */
70 #define _PAGE_GLOBAL ((uint64_t)1 << 5) /* Global */
71 #define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */
72 #define _PAGE_DIRTY ((uint64_t)1 << 7) /* Set by hardware on any write */
73 #define _PAGE_SOFT ((uint64_t)1 << 8) /* Reserved for software */
74 
75 #define _PAGE_PFN_SHIFT 10lu
76 
77 #define VA_MASK ((1lu << 39) - 1)
78 
79 #define PPN_BITS 9lu
80 #define NUM_PTE_ENTRY ((uint64_t)1 << PPN_BITS)
81 
82 typedef uint64_t PTE;
83 
84 static inline uintptr_t iskva(uintptr_t kva) {
85  // kva = kpa + 0xffff_ffc0_0000_0000
86  return kva > 0xffffffc000000000;
87 }
88 
89 static inline uintptr_t kva2pa(uintptr_t kva) {
90  // kva = kpa + 0xffff_ffc0_0000_0000
91  return kva - 0xffffffc000000000;
92 }
93 
94 static inline PTE *pa2kva(uintptr_t pa) {
95  return (PTE *)(pa + 0xffffffc000000000);
96 }
97 
98 static inline uint64_t get_pa(PTE entry) {
99  uint64_t pa_temp = (entry >> _PAGE_PFN_SHIFT) % ((uint64_t)1 << SATP_ASID_SHIFT);
100  return pa_temp << 12;
101 }
102 
103 static inline uintptr_t get_kva_of(uintptr_t va, uintptr_t pgdir_va) {
104  PTE entry = *(uint64_t *)pgdir_va;
105  uint64_t ppn = get_pa(entry);
106  uint64_t mask = (((uint64_t)1) << 13) - 1;
107  return ppn + (va & mask);
108 }
109 
110 /* Get/Set page frame number of the `entry` */
111 static inline uint64_t get_pfn(PTE entry) {
112  uint64_t pa_temp = (entry >> _PAGE_PFN_SHIFT) % ((uint64_t)1 << SATP_ASID_SHIFT);
113  return pa_temp;
114 }
115 
116 static inline void set_pfn(PTE *entry, uint64_t pfn) {
117  uint64_t temp10 = (*entry) % ((uint64_t)1 << 10);
118  *entry = (pfn << 10) | temp10;
119 }
120 
121 /* Get/Set attribute(s) of the `entry` */
122 static inline long get_attribute(PTE entry, uint64_t mask) {
123  return entry & mask;
124 }
125 
126 static inline void set_attribute(PTE *entry, uint64_t bits) {
127  uint64_t pfn_temp = (*entry) >> 10;
128  *entry = (pfn_temp << 10) | bits;
129 }
130 
131 void clear_pgdir(uintptr_t pgdir_addr);
void clear_pgdir(uintptr_t pgdir_addr)
Definition: pgtable.c:3
#define SATP_MODE_SHIFT
Definition: pgtable.h:10
uint64_t PTE
Definition: pgtable.h:82
uint64_t pte_t
Definition: pgtable.h:17
#define SATP_ASID_SHIFT
Definition: pgtable.h:9
#define _PAGE_PFN_SHIFT
Definition: pgtable.h:75
uint64_t * pagetable_t
Definition: pgtable.h:18
#define NULL
Definition: types.h:6
uint64 uintptr_t
Definition: types.h:47