x86: Get the boot time from CMOS
[akaros.git] / kern / arch / riscv / pmap.c
1 /* See COPYRIGHT for copyright information. */
2 #include <arch/arch.h>
3 #include <arch/mmu.h>
4
5 #include <error.h>
6 #include <sys/queue.h>
7
8 #include <atomic.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <pmap.h>
12 #include <env.h>
13 #include <stdio.h>
14 #include <kmalloc.h>
15 #include <page_alloc.h>
16
17 #warning "convert pgdir* to pgdir_t"
18 pgdir_t* boot_pgdir;            // Virtual address of boot time page directory
19 physaddr_t boot_cr3;            // Physical address of boot time page directory
20
21 // --------------------------------------------------------------
22 // Set up initial memory mappings and turn on MMU.
23 // --------------------------------------------------------------
24
25 void
26 vm_init(void)
27 {
28         // we already set up our page tables before jumping
29         // into the kernel, so there's not much going on here
30
31         extern pte_t l1pt[NPTENTRIES];
32         boot_pgdir = l1pt;
33         boot_cr3 = PADDR(boot_pgdir);
34 }
35
36 // Given 'pgdir', a pointer to a page directory, pgdir_walk returns
37 // a pointer to the page table entry (PTE) for linear address 'va'.
38 // This requires walking the two-level page table structure.
39 //
40 // If the relevant page table doesn't exist in the page directory, then:
41 //    - If create == 0, pgdir_walk returns NULL.
42 //    - Otherwise, pgdir_walk tries to allocate a new page table
43 //      with page_alloc.  If this fails, pgdir_walk returns NULL.
44 //    - Otherwise, pgdir_walk returns a pointer into the new page table.
45 //
46 // This is boot_pgdir_walk, but using page_alloc() instead of boot_alloc().
47 // Unlike boot_pgdir_walk, pgdir_walk can fail.
48 pte_t*
49 pgdir_walk(pgdir_t *pgdir, const void *va, int create)
50 {
51         pte_t* ppte;
52         pte_t* pt;
53
54         pt = pgdir;
55         for(int i = 0; i < NPTLEVELS-1; i++)
56         {
57                 // this code relies upon the fact that all page tables are the same size
58                 uintptr_t idx = (uintptr_t)va >> (L1PGSHIFT - i*(L1PGSHIFT-L2PGSHIFT));
59                 idx = idx & (NPTENTRIES-1);
60
61                 ppte = &pt[idx];
62
63                 if(*ppte & PTE_E)
64                         return ppte;
65
66                 if(!(*ppte & PTE_T))
67                 {
68                         if(!create)
69                                 return NULL;
70
71                         page_t *new_table;
72                         if(kpage_alloc(&new_table))
73                                 return NULL;
74                         memset(page2kva(new_table), 0, PGSIZE);
75
76                         *ppte = PTD(page2pa(new_table));
77                 }
78
79                 pt = (pte_t*)KADDR(PTD_ADDR(*ppte));
80         }
81
82         uintptr_t idx = (uintptr_t)va >> (L1PGSHIFT - (NPTLEVELS-1)*(L1PGSHIFT-L2PGSHIFT));
83         idx = idx & (NPTENTRIES-1);
84   return &pt[idx];
85 }
86
87 /* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
88  * virtual address. */
89 int get_va_perms(pgdir_t *pgdir, const void *va)
90 {
91         pte_t* pte = pgdir_walk(pgdir, va, 0);
92         return pte == NULL ? 0 : (*pte & (PTE_PERM | PTE_E));
93 }
94
95 void
96 page_check(void)
97 {
98 }
99
100 uintptr_t gva2gpa(struct proc *p, uintptr_t cr3, uintptr_t gva)
101 {
102         panic("Unimplemented");
103         return 0;
104 }
105
106 int arch_pgdir_setup(pgdir_t boot_copy, pgdir_t *new_pd)
107 {
108         pte_t *kpt = kpage_alloc_addr();
109         if (!kpt)
110                 return -ENOMEM;
111         memcpy(kpt, (pte_t*)boot_copy, PGSIZE);
112
113         /* TODO: VPT/UVPT mappings */
114
115         *new_pd = (pgdir_t)kpt;
116         return 0;
117 }
118
119 physaddr_t arch_pgdir_get_cr3(pgdir_t pd)
120 {
121         return PADDR((pte_t*)pd);
122 }
123
124 void arch_pgdir_clear(pgdir_t *pd)
125 {
126         *pd = 0;
127 }
128
129 /* Returns the page shift of the largest jumbo supported */
130 int arch_max_jumbo_page_shift(void)
131 {
132         #warning "What jumbo page sizes does RISC support?"
133         return PGSHIFT;
134 }
135
136 #warning "Not sure where you do your PT destruction.  Be sure to not unmap any intermediate page tables for kernel mappings.  At least not the PML(n-1) maps"
137
138 void arch_add_intermediate_pts(pgdir_t pgdir, uintptr_t va, size_t len)
139 {
140         #error "Implement me"
141 }
142
143 void map_segment(pgdir_t pgdir, uintptr_t va, size_t size, physaddr_t pa,
144                  int perm, int pml_shift)
145 {
146         #error "Implement me"
147 }
148
149 int unmap_segment(pgdir_t pgdir, uintptr_t va, size_t size)
150 {
151         #error "Implement me"
152 }