Added whitelisting to MSR read/write code
[akaros.git] / kern / arch / x86 / pmap_ops.h
index 7a2293e..a38bebd 100644 (file)
  * time is a pain, and for now we'll do the walks serially.  Because of that, a
  * given pte_t may have a KPTE and/or an EPTE.  Ideally, it'd be *and*. */
 
-#ifndef ROS_ARCH_PMAPS_OPS_H
-#define ROS_ARCH_PMAPS_OPS_H
+#pragma once
+
+#include <arch/vmm/ept.h>
+#include <arch/kpt.h>
 
 /* TODO: (EPT)  build a CONFIG mode where we assert the EPT agrees with the KPT
  * for all of the read ops */
 
 static inline bool pte_walk_okay(pte_t pte)
 {
-       /* walk_okay should only be called after a walk, when we have both a KPTE
-        * and an EPTE */
-       dassert(pte.kpte ? TRUE : !pte.epte);
-       return pte.kpte ? TRUE : FALSE;
+       return pte ? TRUE : FALSE;
 }
 
 /* PTE states:
- *  - present: the PTE is involved in a valid page table walk, with the physaddr
- *  part pointing to a physical page.
+ *  - present: the PTE is involved in a valid page table walk, can be used
+ *  for some form of hardware access (read, write, user, etc), and with the
+ *  physaddr part pointing to a physical page.
  *
  *     - mapped: the PTE is involved in some sort of mapping, e.g. a VMR.  We're
- *     storing something in the PTE, but it is isn't necessarily present and
- *     pointing to an actual physical page.  All present are mapped, but not vice
- *     versa.  Mapped could also include paged-out, if we support that later.
+ *     storing something in the PTE, but it is isn't necessarily present.
+ *     Currently, all mapped pages should point to an actual physical page.
+ *     All present are mapped, but not vice versa.  Mapped pages can point to a
+ *     real page, but with no access permissions, which is the main distinction
+ *     between present and mapped.
+ *
+ *     - paged_out: we don't actually use this yet.  Since mapped vs present is
+ *     based on the PTE present bits, we'd need to use reserved bits in the PTE to
+ *     differentiate between other states.  Right now, paged_out == mapped, as far
+ *     as the code is concerned.
  *
  *     - unmapped: completely unused. (0 value) */
 static inline bool pte_is_present(pte_t pte)
 {
-#if 0  /* could do some debuggin like this.  painful. */
-       bool ret_kpte, ret_epte;
-       assert(pte.kpte || pte.epte);
-       ret_kpte = pte.kpte ? (*pte.kpte & PTE_P ? TRUE : FALSE) : 0;
-       /* TODO: EPT check */
-       ret_epte = pte.epte ? (*pte.epte & PTE_P ? TRUE : FALSE) : 0;
-       if (pte.kpte && pte.epte)
-               assert(ret_kpte == ret_epte);
-       return pte.kpte ? ret_kpte : ret_epte;
-#endif
-       return pte.kpte ? (*pte.kpte & PTE_P ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_present(pte);
 }
 
 static inline bool pte_is_unmapped(pte_t pte)
 {
-       return pte.kpte ? PAGE_UNMAPPED(*pte.kpte)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_unmapped(pte);
 }
 
 static inline bool pte_is_mapped(pte_t pte)
 {
-       return pte.kpte ? !PAGE_UNMAPPED(*pte.kpte)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_mapped(pte);
 }
 
 static inline bool pte_is_paged_out(pte_t pte)
 {
-       return pte.kpte ? PAGE_PAGED_OUT(*pte.kpte)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_paged_out(pte);
 }
 
 static inline bool pte_is_dirty(pte_t pte)
 {
-       return pte.kpte ? (*pte.kpte & PTE_D ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_dirty(pte) ||
+              epte_is_dirty(kpte_to_epte(pte));
 }
 
 static inline bool pte_is_accessed(pte_t pte)
 {
-       return pte.kpte ? (*pte.kpte & PTE_A ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_accessed(pte) ||
+              epte_is_accessed(kpte_to_epte(pte));
 }
 
 /* Used in debugging code - want something better involving the walk */
 static inline bool pte_is_jumbo(pte_t pte)
 {
-       return pte.kpte ? (*pte.kpte & PTE_PS ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_is_jumbo(pte);
 }
 
 static inline physaddr_t pte_get_paddr(pte_t pte)
 {
-       return pte.kpte ? PTE_ADDR(*pte.kpte)
-                       : 0; /* TODO: EPT check */
+       return kpte_get_paddr(pte);
 }
 
 /* Returns the PTE in an unsigned long, for debugging mostly. */
 static inline unsigned long pte_print(pte_t pte)
 {
-       return pte.kpte ? *pte.kpte
-                       : 0; /* TODO: EPT check */
+       return kpte_print(pte);
 }
 
-static inline void pte_write(pte_t pte, physaddr_t pa, int perm)
+static inline void pte_write(pte_t pte, physaddr_t pa, int settings)
 {
-       if (pte.kpte)
-               *pte.kpte = PTE(pa2ppn(pa), perm);
-       if (pte.epte)
-               /* TODO: EPT write (if EPT) */;
+       kpte_write(pte, pa, settings);
+       epte_write(kpte_to_epte(pte), pa, settings);
 }
 
 static inline void pte_clear_present(pte_t pte)
 {
-       if (pte.kpte)
-               *pte.kpte &= ~PTE_P;
-       if (pte.epte)
-               /* TODO: EPT write (if EPT) */;
+       kpte_clear_present(pte);
+       epte_clear_present(kpte_to_epte(pte));
 }
 
 static inline void pte_clear(pte_t pte)
 {
-       if (pte.kpte)
-               *pte.kpte = 0;
-       if (pte.epte)
-               /* TODO: EPT write (if EPT) */;
+       kpte_clear(pte);
+       epte_clear(kpte_to_epte(pte));
 }
 
 /* These are used by memcpy_*_user, but are very dangerous (and possibly used
@@ -131,30 +115,27 @@ static inline void pte_clear(pte_t pte)
  * to an intermediate PTE, we'd miss that. */
 static inline bool pte_has_perm_ur(pte_t pte)
 {
-       return pte.kpte ? (*pte.kpte & PTE_USER_RO ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_has_perm_ur(pte);
 }
 
 static inline bool pte_has_perm_urw(pte_t pte)
 {
-       return pte.kpte ? (*pte.kpte & PTE_USER_RW ? TRUE : FALSE)
-                       : 0; /* TODO: EPT check */
+       return kpte_has_perm_urw(pte);
 }
 
-/* return the arch-independent format for prots - whatever you'd expect to
- * receive for pte_write.  Careful with the ret, since a valid type is 0. */
-static inline int pte_get_perm(pte_t pte)
+/* Settings includes protection (maskable via PTE_PROT) and other bits, such as
+ * jumbo, dirty, accessed, etc.  Whatever this returns can get fed back to
+ * pte_write.
+ *
+ * Arch-indep settings include: PTE_PERM (U, W, P, etc), PTE_D, PTE_A, PTE_PS.
+ * Other OSs (x86) may include others. */
+static inline int pte_get_settings(pte_t pte)
 {
-       return pte.kpte ? *pte.kpte & PTE_PERM
-                       : 0; /* TODO: EPT check */
+       return kpte_get_settings(pte);
 }
 
 static inline void pte_replace_perm(pte_t pte, int perm)
 {
-       if (pte.kpte)
-               *pte.kpte = (*pte.kpte & ~PTE_PERM) | perm;
-       if (pte.epte)
-               /* TODO: EPT write (if EPT) */;
+       kpte_replace_perm(pte, perm);
+       epte_replace_perm(kpte_to_epte(pte), perm);
 }
-
-#endif /* ROS_ARCH_PMAPS_OPS_H */