Pmap ops: perm->settings
[akaros.git] / kern / arch / riscv / pmap_ops.h
1 /* Copyright (c) 2015 Google Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Arch-specific operations for page tables and PTEs */
6
7 #ifndef ROS_ARCH_PMAPS_OPS_H
8 #define ROS_ARCH_PMAPS_OPS_H
9
10 static inline bool pte_walk_okay(pte_t pte)
11 {
12         return pte ? TRUE : FALSE;
13 }
14
15 /* PTE states:
16  *  - present: the PTE is involved in a valid page table walk, with the physaddr
17  *  part pointing to a physical page.
18  *
19  *      - mapped: the PTE is involved in some sort of mapping, e.g. a VMR.  We're
20  *      storing something in the PTE, but it is isn't necessarily present and
21  *      pointing to an actual physical page.  All present are mapped, but not vice
22  *      versa.  Mapped could also include paged-out, if we support that later.
23  *
24  *      - unmapped: completely unused. (0 value) */
25 static inline bool pte_is_present(pte_t pte)
26 {
27         return *(kpte_t*)pte & PTE_P ? TRUE : FALSE;
28 }
29
30 static inline bool pte_is_unmapped(pte_t pte)
31 {
32         return PAGE_UNMAPPED(*(kpte_t*)pte);
33 }
34
35 static inline bool pte_is_mapped(pte_t pte)
36 {
37         return !PAGE_UNMAPPED(*(kpte_t*)pte);
38 }
39
40 static inline bool pte_is_paged_out(pte_t pte)
41 {
42         return PAGE_PAGED_OUT(*(kpte_t*)pte);
43 }
44
45 static inline bool pte_is_dirty(pte_t pte)
46 {
47         return *(kpte_t*)pte & PTE_D ? TRUE : FALSE;
48 }
49
50 static inline bool pte_is_accessed(pte_t pte)
51 {
52         return *(kpte_t*)pte & PTE_A ? TRUE : FALSE;
53 }
54
55 /* Used in debugging code - want something better involving the walk */
56 static inline bool pte_is_jumbo(pte_t pte)
57 {
58         return *(kpte_t*)pte & PTE_PS ? TRUE : FALSE;
59 }
60
61 static inline physaddr_t pte_get_paddr(pte_t pte)
62 {
63         return PTE_ADDR(*(kpte_t*)pte);
64 }
65
66 /* Returns the PTE in an unsigned long, for debugging mostly. */
67 static inline unsigned long pte_print(pte_t pte)
68 {
69         return *(kpte_t*)pte;
70 }
71
72 static inline void pte_write(pte_t pte, physaddr_t pa, int settings)
73 {
74         *(kpte_t*)pte = PTE(pa2ppn(pa), settings);
75 }
76
77 static inline void pte_clear_present(pte_t pte)
78 {
79         *(kpte_t*)pte &= ~PTE_P;
80 }
81
82 static inline void pte_clear(pte_t pte)
83 {
84         *(kpte_t*)pte = 0;
85 }
86
87 /* These are used by memcpy_*_user, but are very dangerous (and possibly used
88  * incorrectly there).  These aren't the overall perms for a VA.  For U and W,
89  * we need the intersection of the PTEs along the walk and not just the last
90  * one.  It just so happens that the W is only cleared on the last PTE, so the
91  * check works for that.  But if there was a page under ULIM that wasn't U due
92  * to an intermediate PTE, we'd miss that. */
93 static inline bool pte_has_perm_ur(pte_t pte)
94 {
95         return *(kpte_t*)pte & PTE_USER_RO ? TRUE : FALSE;
96 }
97
98 static inline bool pte_has_perm_urw(pte_t pte)
99 {
100         return *(kpte_t*)pte & PTE_USER_RW ? TRUE : FALSE;
101 }
102
103 /* Settings includes protection (maskable via PTE_PROT) and other bits, such as
104  * jumbo, dirty, accessed, etc.  Whatever this returns can get fed back to
105  * replace_settings or pte_write.
106  *
107  * Arch-indep settings include: PTE_PERM (U, W, P, etc), PTE_D, PTE_A, PTE_PS.
108  * Other OSs (x86) may include others. */
109 static inline int pte_get_settings(pte_t pte)
110 {
111         return *(kpte_t*)pte & PTE_PERM;
112 }
113
114 static inline void pte_replace_perm(pte_t pte, int perm)
115 {
116         *(kpte_t*)pte = (*(kpte_t*)pte & ~PTE_PERM) | perm;
117 }
118
119 #endif /* ROS_ARCH_PMAPS_OPS_H */