VMM: Call EPT ops for every KPT op
[akaros.git] / kern / arch / x86 / 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  * Unfortunately, many of these ops are called from within a memwalk callback,
8  * which expects a full pte.  But doing walks for a KPT and an EPT at the same
9  * time is a pain, and for now we'll do the walks serially.  Because of that, a
10  * given pte_t may have a KPTE and/or an EPTE.  Ideally, it'd be *and*. */
11
12 #ifndef ROS_ARCH_PMAPS_OPS_H
13 #define ROS_ARCH_PMAPS_OPS_H
14
15 #include <arch/vmm/ept.h>
16 #include <arch/kpt.h>
17
18 /* TODO: (EPT)  build a CONFIG mode where we assert the EPT agrees with the KPT
19  * for all of the read ops */
20
21 static inline bool pte_walk_okay(pte_t pte)
22 {
23         return pte.kpte ? TRUE : FALSE;
24 }
25
26 /* PTE states:
27  *  - present: the PTE is involved in a valid page table walk, can be used
28  *  for some form of hardware access (read, write, user, etc), and with the
29  *  physaddr part pointing to a physical page.
30  *
31  *      - mapped: the PTE is involved in some sort of mapping, e.g. a VMR.  We're
32  *      storing something in the PTE, but it is isn't necessarily present.
33  *      Currently, all mapped pages should point to an actual physical page.
34  *      All present are mapped, but not vice versa.  Mapped pages can point to a
35  *      real page, but with no access permissions, which is the main distinction
36  *      between present and mapped.
37  *
38  *      - paged_out: we don't actually use this yet.  Since mapped vs present is
39  *      based on the PTE present bits, we'd need to use reserved bits in the PTE to
40  *      differentiate between other states.  Right now, paged_out == mapped, as far
41  *      as the code is concerned.
42  *
43  *      - unmapped: completely unused. (0 value) */
44 static inline bool pte_is_present(pte_t pte)
45 {
46         return kpte_is_present(pte.kpte);
47 }
48
49 static inline bool pte_is_unmapped(pte_t pte)
50 {
51         return kpte_is_unmapped(pte.kpte);
52 }
53
54 static inline bool pte_is_mapped(pte_t pte)
55 {
56         return kpte_is_mapped(pte.kpte);
57 }
58
59 static inline bool pte_is_paged_out(pte_t pte)
60 {
61         return kpte_is_paged_out(pte.kpte);
62 }
63
64 static inline bool pte_is_dirty(pte_t pte)
65 {
66         return kpte_is_dirty(pte.kpte) ||
67                epte_is_dirty(kpte_to_epte(pte.kpte));
68 }
69
70 static inline bool pte_is_accessed(pte_t pte)
71 {
72         return kpte_is_accessed(pte.kpte) ||
73                epte_is_accessed(kpte_to_epte(pte.kpte));
74 }
75
76 /* Used in debugging code - want something better involving the walk */
77 static inline bool pte_is_jumbo(pte_t pte)
78 {
79         return kpte_is_jumbo(pte.kpte);
80 }
81
82 static inline physaddr_t pte_get_paddr(pte_t pte)
83 {
84         return kpte_get_paddr(pte.kpte);
85 }
86
87 /* Returns the PTE in an unsigned long, for debugging mostly. */
88 static inline unsigned long pte_print(pte_t pte)
89 {
90         return kpte_print(pte.kpte);
91 }
92
93 static inline void pte_write(pte_t pte, physaddr_t pa, int perm)
94 {
95         kpte_write(pte.kpte, pa, perm);
96         epte_write(kpte_to_epte(pte.kpte), pa, perm);
97 }
98
99 static inline void pte_clear_present(pte_t pte)
100 {
101         kpte_clear_present(pte.kpte);
102         epte_clear_present(kpte_to_epte(pte.kpte));
103 }
104
105 static inline void pte_clear(pte_t pte)
106 {
107         kpte_clear(pte.kpte);
108         epte_clear(kpte_to_epte(pte.kpte));
109 }
110
111 /* These are used by memcpy_*_user, but are very dangerous (and possibly used
112  * incorrectly there).  These aren't the overall perms for a VA.  For U and W,
113  * we need the intersection of the PTEs along the walk and not just the last
114  * one.  It just so happens that the W is only cleared on the last PTE, so the
115  * check works for that.  But if there was a page under ULIM that wasn't U due
116  * to an intermediate PTE, we'd miss that. */
117 static inline bool pte_has_perm_ur(pte_t pte)
118 {
119         return kpte_has_perm_ur(pte.kpte);
120 }
121
122 static inline bool pte_has_perm_urw(pte_t pte)
123 {
124         return kpte_has_perm_urw(pte.kpte);
125 }
126
127 /* return the arch-independent format for prots - whatever you'd expect to
128  * receive for pte_write.  Careful with the ret, since a valid type is 0. */
129 static inline int pte_get_perm(pte_t pte)
130 {
131         return kpte_get_perm(pte.kpte);
132 }
133
134 static inline void pte_replace_perm(pte_t pte, int perm)
135 {
136         kpte_replace_perm(pte.kpte, perm);
137         epte_replace_perm(kpte_to_epte(pte.kpte), perm);
138 }
139
140 #endif /* ROS_ARCH_PMAPS_OPS_H */