/* Copyright (c) 2015 Google Inc.
 * Barret Rhoden <brho@cs.berkeley.edu>
 * See LICENSE for details.
 *
 * Arch-specific operations for page tables and PTEs */

#ifndef ROS_ARCH_PMAPS_OPS_H
#define ROS_ARCH_PMAPS_OPS_H

static inline bool pte_walk_okay(pte_t pte)
{
	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.
 *
 * 	- 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.
 *
 * 	- unmapped: completely unused. (0 value) */
static inline bool pte_is_present(pte_t pte)
{
	return *(kpte_t*)pte & PTE_P ? TRUE : FALSE;
}

static inline bool pte_is_unmapped(pte_t pte)
{
	return PAGE_UNMAPPED(*(kpte_t*)pte);
}

static inline bool pte_is_mapped(pte_t pte)
{
	return !PAGE_UNMAPPED(*(kpte_t*)pte);
}

static inline bool pte_is_paged_out(pte_t pte)
{
	return PAGE_PAGED_OUT(*(kpte_t*)pte);
}

static inline bool pte_is_dirty(pte_t pte)
{
	return *(kpte_t*)pte & PTE_D ? TRUE : FALSE;
}

static inline bool pte_is_accessed(pte_t pte)
{
	return *(kpte_t*)pte & PTE_A ? TRUE : FALSE;
}

/* Used in debugging code - want something better involving the walk */
static inline bool pte_is_jumbo(pte_t pte)
{
	return *(kpte_t*)pte & PTE_PS ? TRUE : FALSE;
}

static inline physaddr_t pte_get_paddr(pte_t pte)
{
	return PTE_ADDR(*(kpte_t*)pte);
}

/* Returns the PTE in an unsigned long, for debugging mostly. */
static inline unsigned long pte_print(pte_t pte)
{
	return *(kpte_t*)pte;
}

static inline void pte_write(pte_t pte, physaddr_t pa, int settings)
{
	*(kpte_t*)pte = PTE(pa2ppn(pa), settings);
}

static inline void pte_clear_present(pte_t pte)
{
	*(kpte_t*)pte &= ~PTE_P;
}

static inline void pte_clear(pte_t pte)
{
	*(kpte_t*)pte = 0;
}

/* These are used by memcpy_*_user, but are very dangerous (and possibly used
 * incorrectly there).  These aren't the overall perms for a VA.  For U and W,
 * we need the intersection of the PTEs along the walk and not just the last
 * one.  It just so happens that the W is only cleared on the last PTE, so the
 * check works for that.  But if there was a page under ULIM that wasn't U due
 * to an intermediate PTE, we'd miss that. */
static inline bool pte_has_perm_ur(pte_t pte)
{
	return *(kpte_t*)pte & PTE_USER_RO ? TRUE : FALSE;
}

static inline bool pte_has_perm_urw(pte_t pte)
{
	return *(kpte_t*)pte & PTE_USER_RW ? TRUE : FALSE;
}

/* Settings includes protection (maskable via PTE_PROT) and other bits, such as
 * jumbo, dirty, accessed, etc.  Whatever this returns can get fed back to
 * replace_settings or 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 *(kpte_t*)pte & PTE_PERM;
}

static inline void pte_replace_perm(pte_t pte, int perm)
{
	*(kpte_t*)pte = (*(kpte_t*)pte & ~PTE_PERM) | perm;
}

#endif /* ROS_ARCH_PMAPS_OPS_H */
