Merge with master
[akaros.git] / kern / include / pmap.h
1 /* See COPYRIGHT for copyright information. */
2
3 #ifndef ROS_KERN_PMAP_H
4 #define ROS_KERN_PMAP_H
5
6 #include <ros/memlayout.h>
7 #include <ros/mman.h>
8 #include <sys/queue.h>
9 #include <multiboot.h>
10 #include <atomic.h>
11 #include <process.h>
12 #include <assert.h>
13 #include <page_alloc.h>
14 #include <multiboot.h>
15
16 /* This macro takes a kernel virtual address -- an address that points above
17  * KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
18  * and returns the corresponding physical address.  It panics if you pass it a
19  * non-kernel virtual address.
20  */
21 #define PADDR(kva)                                              \
22 ({                                                              \
23         physaddr_t __m_kva = (physaddr_t) (kva);                \
24         if (__m_kva < KERNBASE)                                 \
25                 panic("PADDR called with invalid kva %08lx", __m_kva);\
26         __m_kva - KERNBASE;                                     \
27 })
28
29 /* This macro takes a physical address and returns the corresponding kernel
30  * virtual address.  It warns if you pass an invalid physical address. */
31 #define KADDR(pa)                                               \
32 ({                                                              \
33         physaddr_t __m_pa = (pa);                               \
34         size_t __m_ppn = PPN(__m_pa);                           \
35         if (__m_ppn >= npages)                                  \
36                 warn("KADDR called with invalid pa %08lx", __m_pa);\
37         (void*TRUSTED) (__m_pa + KERNBASE);                             \
38 })
39
40 extern char (SNT RO bootstacktop)[], (SNT RO bootstack)[];
41
42 // List of physical pages
43 extern page_t * RO CT(npages) pages;
44
45 extern physaddr_t RO boot_cr3;
46 extern pde_t *CT(NPDENTRIES) RO boot_pgdir;
47
48 extern char *RO BND(end, maxaddrpa_ptr + IVY_KERNBASE) boot_freemem;
49
50 void    multiboot_detect_memory(multiboot_info_t *COUNT(1) mbi);
51 void    multiboot_print_memory_map(multiboot_info_t *COUNT(1) mbi);
52 bool    enable_pse(void);
53 void    vm_init(void);
54
55 void    page_init(void);
56 void    page_check(void);
57 int         page_insert(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, void *SNT va, int perm);
58 void*COUNT(PGSIZE) page_insert_in_range(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, 
59                              void *SNT vab, void *SNT vae, int perm);
60 void    page_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
61 page_t*COUNT(1) page_lookup(pde_t SSOMELOCK*COUNT(NPDENTRIES) pgdir, void *SNT va, pte_t **pte_store);
62 error_t pagetable_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
63 void    page_decref(page_t *COUNT(1) pp);
64
65 void setup_default_mtrrs(barrier_t* smp_barrier);
66 void    tlb_invalidate(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
67 void tlb_flush_global(void);
68
69 void * (DALLOC(len) user_mem_check) (env_t *env, const void *DANGEROUS va,
70                                      size_t len, int perm);
71
72 void * (DALLOC(len) user_mem_assert)(env_t *env, const void *DANGEROUS va,
73                                      size_t len, int perm);
74
75 size_t user_mem_strlcpy(env_t *env, char *NT COUNT(len - 1),
76                         const char *DANGEROUS va, size_t len, int perm);
77
78 error_t
79 memcpy_from_user(env_t* env, void* COUNT(len) dest,
80                  const void *DANGEROUS va, size_t len);
81                  
82 /* Arch specific implementations for these */
83 pte_t *pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va, int create);
84 int get_va_perms(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va);
85 void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len);
86
87 static inline page_t *SAFE ppn2page(size_t ppn)
88 {
89         if( ppn >= npages )
90                 warn("ppn2page called with ppn (%08u) larger than npages", ppn);
91         return &(pages[ppn]);
92 }
93
94 static inline ppn_t page2ppn(page_t *pp)
95 {
96         return pp - pages;
97 }
98
99 static inline physaddr_t page2pa(page_t *pp)
100 {
101         return page2ppn(pp) << PGSHIFT;
102 }
103
104 static inline page_t*COUNT(1) pa2page(physaddr_t pa)
105 {
106         if (PPN(pa) >= npages)
107                 warn("pa2page called with pa (0x%08x) larger than npages", pa);
108         return &pages[PPN(pa)];
109 }
110
111 static inline void*COUNT(PGSIZE) page2kva(page_t *pp)
112 {
113         return KADDR(page2pa(pp));
114 }
115
116 static inline void*COUNT(PGSIZE) ppn2kva(size_t pp)
117 {
118         return page2kva(ppn2page(pp));
119 }
120
121 static inline page_t* kva2page(void* addr) 
122 {
123         return pa2page(PADDR(addr));
124 }
125
126 /*
127  * Memory management for processes: syscall related functions, virtual memory
128  * regions, etc.
129  */
130 void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, int fd, size_t offset);
131
132 /* Memory region for a process, consisting of linear(virtual) addresses.  This
133  * is what the kernel allocates a process, and the physical mapping can be done
134  * lazily (or not).  This way, if a page is swapped out, and the PTE says it
135  * isn't present, we still have a way to account for how the whole region ought
136  * to be dealt with. */
137 struct memregion {
138         LIST_ENTRY(memregion) link; // actually, i'd like a sorted tree of these
139         uintptr_t base;
140         size_t len;
141         int perm;
142 };
143 TAILQ_HEAD(memregion_list, memregion); // Declares 'struct memregion_list'
144
145 #endif /* !ROS_KERN_PMAP_H */