e1000 uses the new kernel dynamic VA mapping
[akaros.git] / kern / include / pmap.h
1 /* See COPYRIGHT for copyright information.
2  * Inlines, macros, and most function prototypes (c) the JOS project.
3  *
4  * Actual implementation:
5  * Copyright (c) 2009 The Regents of the University of California
6  * Barret Rhoden <brho@cs.berkeley.edu>
7  * Kevin Klues <klueska@cs.berkeley.edu> (multiboot functions)
8  * See LICENSE for details.
9  *
10  * Physical memory mangement, low-level virtual address space initialization and
11  * management, and other things related to virtual->physical mappings.
12  */
13
14 #ifndef ROS_KERN_PMAP_H
15 #define ROS_KERN_PMAP_H
16
17 #include <ros/memlayout.h>
18 #include <ros/mman.h>
19 #include <sys/queue.h>
20 #include <multiboot.h>
21 #include <atomic.h>
22 #include <process.h>
23 #include <assert.h>
24 #include <page_alloc.h>
25 #include <multiboot.h>
26
27 /* This macro takes a kernel virtual address -- an address that points above
28  * KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
29  * and returns the corresponding physical address.  It panics if you pass it a
30  * non-kernel virtual address.
31  */
32 #define PADDR(kva)                                              \
33 ({                                                              \
34         physaddr_t __m_pa, __m_kva = (physaddr_t) (kva);                \
35         if (__m_kva < KERNBASE)                                 \
36                 panic("PADDR called with invalid kva %p", __m_kva);\
37         if(__m_kva >= KERN_LOAD_ADDR)                                   \
38                 __m_pa = __m_kva - KERN_LOAD_ADDR;                                      \
39         else                                    \
40                 __m_pa = __m_kva - KERNBASE;                                    \
41         __m_pa; \
42 })
43
44 /* This macro takes a physical address and returns the corresponding kernel
45  * virtual address.  It warns if you pass an invalid physical address. */
46 #define KADDR(pa)                                               \
47 ({                                                              \
48         physaddr_t __m_pa = (pa);                               \
49         size_t __m_ppn = LA2PPN(__m_pa);                        \
50         if (__m_ppn >= npages)                                  \
51                 warn("KADDR called with invalid pa %p", __m_pa);\
52         (void*TRUSTED) (__m_pa + KERNBASE);                             \
53 })
54
55 extern char (SNT RO bootstacktop)[], (SNT RO bootstack)[];
56
57 // List of physical pages
58 extern page_t * RO CT(npages) pages;
59
60 extern physaddr_t RO boot_cr3;
61 extern pde_t *CT(NPDENTRIES) RO boot_pgdir;
62
63 extern char *RO BND(end, maxaddrpa_ptr + IVY_KERNBASE) boot_freemem;
64
65 void    multiboot_detect_memory(multiboot_info_t *COUNT(1) mbi);
66 void    multiboot_print_memory_map(multiboot_info_t *COUNT(1) mbi);
67 bool    enable_pse(void);
68 void    vm_init(void);
69
70 void    page_init(void);
71 void    page_check(void);
72 int         page_insert(pde_t *pgdir, struct page *page, void *SNT va, int perm);
73 void    page_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
74 page_t*COUNT(1) page_lookup(pde_t SSOMELOCK*COUNT(NPDENTRIES) pgdir, void *SNT va, pte_t **pte_store);
75 error_t pagetable_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
76 void    page_decref(page_t *COUNT(1) pp);
77
78 void setup_default_mtrrs(barrier_t* smp_barrier);
79 void    tlb_invalidate(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
80 void tlb_flush_global(void);
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
86 static inline page_t *SAFE ppn2page(size_t ppn)
87 {
88         if( ppn >= npages )
89                 warn("ppn2page called with ppn (%08lu) larger than npages", ppn);
90         return &(pages[ppn]);
91 }
92
93 static inline ppn_t page2ppn(page_t *pp)
94 {
95         return pp - pages;
96 }
97
98 static inline physaddr_t page2pa(page_t *pp)
99 {
100         return page2ppn(pp) << PGSHIFT;
101 }
102
103 static inline page_t*COUNT(1) pa2page(physaddr_t pa)
104 {
105         if (LA2PPN(pa) >= npages)
106                 warn("pa2page called with pa (%p) larger than npages", pa);
107         return &pages[LA2PPN(pa)];
108 }
109
110 static inline ppn_t pa2ppn(physaddr_t pa)
111 {
112         return pa >> PGSHIFT;
113 }
114
115 static inline void*COUNT(PGSIZE) page2kva(page_t *pp)
116 {
117         return KADDR(page2pa(pp));
118 }
119
120 static inline void*COUNT(PGSIZE) ppn2kva(size_t pp)
121 {
122         return page2kva(ppn2page(pp));
123 }
124
125 static inline page_t* kva2page(void* addr) 
126 {
127         return pa2page(PADDR(addr));
128 }
129
130 static inline ppn_t kva2ppn(void* addr) 
131 {
132         return page2ppn(kva2page(addr));
133 }
134
135 #endif /* !ROS_KERN_PMAP_H */