Split atomic library
[akaros.git] / include / pmap.h
1 /* See COPYRIGHT for copyright information. */
2
3 #ifndef ROS_KERN_PMAP_H
4 #define ROS_KERN_PMAP_H
5 #ifndef ROS_KERNEL
6 # error "This is a ROS kernel header; user programs should not #include it"
7 #endif
8
9 #include <arch/multiboot.h>
10
11 #include <ros/memlayout.h>
12
13 #include <atomic.h>
14 #include <env.h>
15 #include <assert.h>
16
17 /* This macro takes a kernel virtual address -- an address that points above
18  * KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
19  * and returns the corresponding physical address.  It panics if you pass it a
20  * non-kernel virtual address.
21  */
22 #define PADDR(kva)                                              \
23 ({                                                              \
24         physaddr_t __m_kva = (physaddr_t) (kva);                \
25         if (__m_kva < KERNBASE)                                 \
26                 panic("PADDR called with invalid kva %08lx", __m_kva);\
27         __m_kva - KERNBASE;                                     \
28 })
29
30 /* This macro takes a physical address and returns the corresponding kernel
31  * virtual address.  It warns if you pass an invalid physical address. */
32 #define KADDR(pa)                                               \
33 ({                                                              \
34         physaddr_t __m_pa = (pa);                               \
35         uint32_t __m_ppn = PPN(__m_pa);                         \
36         if (__m_ppn >= npage)                                   \
37                 warn("KADDR called with invalid pa %08lx", __m_pa);\
38         (void*) (__m_pa + KERNBASE);                            \
39 })
40
41 /*
42  * Page descriptor structures, mapped at UPAGES.
43  * Read/write to the kernel, read-only to user programs.
44  *
45  * Each Page describes one physical page.
46  * You can map a Page * to the corresponding physical address
47  * with page2pa() in kern/pmap.h.
48  */
49
50 struct Page;
51 typedef struct Page page_t;
52
53 LIST_HEAD(page_list_t, page_t);
54 typedef LIST_ENTRY(page_t) page_list_entry_t;
55
56 struct Page {
57         page_list_entry_t pp_link;      /* free list link */
58
59         // pp_ref is the count of pointers (usually in page table entries)
60         // to this page, for pages allocated using page_alloc.
61         // Pages allocated at boot time using pmap.c's
62         // boot_alloc do not have valid reference count fields.
63
64         uint16_t pp_ref;
65 };
66
67
68 extern char bootstacktop[], bootstack[];
69
70 extern page_t *pages;
71 extern size_t npage;
72
73 extern physaddr_t boot_cr3;
74 extern pde_t *boot_pgdir;
75
76 extern segdesc_t (COUNT(SEG_COUNT) gdt)[];
77 extern pseudodesc_t gdt_pd;
78
79 void    i386_detect_memory(multiboot_info_t *mbi);
80 void    i386_print_memory_map(multiboot_info_t *mbi);
81 bool    enable_pse(void);
82 void    i386_vm_init(void);
83
84 void    page_init(void);
85 void    page_check(void);
86 int     page_alloc(page_t **pp_store);
87 void    page_free(page_t *pp);
88 int     page_insert(pde_t *pgdir, page_t *pp, void *va, int perm);
89 void    page_remove(pde_t *pgdir, void *va);
90 page_t *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store);
91 error_t pagetable_remove(pde_t *pgdir, void *va);
92 void    page_decref(page_t *pp);
93
94 void setup_default_mtrrs(barrier_t* smp_barrier);
95 void    tlb_invalidate(pde_t *pgdir, void *va);
96 void tlb_flush_global(void);
97
98 void *COUNT(len)
99 user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm);
100
101 void *COUNT(len)
102 user_mem_assert(env_t *env, const void *DANGEROUS va, size_t len, int perm);
103
104 static inline void cache_flush(void)
105 {
106         wbinvd();
107 }
108
109 static inline void cacheline_flush(void* addr)
110 {
111         clflush((uintptr_t*)addr);
112 }
113
114 static inline ppn_t page2ppn(page_t *pp)
115 {
116         return pp - pages;
117 }
118
119 static inline physaddr_t page2pa(page_t *pp)
120 {
121         return page2ppn(pp) << PGSHIFT;
122 }
123
124 static inline page_t* pa2page(physaddr_t pa)
125 {
126         if (PPN(pa) >= npage)
127                 warn("pa2page called with pa (0x%08x) larger than npage", pa);
128         return &pages[PPN(pa)];
129 }
130
131 static inline void* page2kva(page_t *pp)
132 {
133         return KADDR(page2pa(pp));
134 }
135
136 pte_t *pgdir_walk(pde_t *pgdir, const void *va, int create);
137
138 #endif /* !ROS_KERN_PMAP_H */