/* Copyright (c) 2015 Google Inc.
 * Barret Rhoden <brho@cs.berkeley.edu>
 * See LICENSE for details.
 *
 * 64 bit EPT helpers */

#pragma once

#include <arch/vmm/intel/vmx.h>	/* for sync/flush helpers */
#include <smp.h>				/* for current */

/* Some EPTE PTE flags are only valid for the last PTEs in a walk */
#define EPTE_R					(1ULL << 0)		/* Readable */
#define EPTE_W					(1ULL << 1)		/* Writeable */
#define EPTE_X					(1ULL << 2)		/* Executable */
#define EPTE_MEM_BITS			(7ULL << 3)		/* Memory type specifier */
#define EPTE_IGN_PAT			(1ULL << 6)		/* Ignore PAT */
#define EPTE_PS					(1ULL << 7)		/* Jumbo Page Size */
#define EPTE_A					(1ULL << 8)		/* Accessed */
#define EPTE_D					(1ULL << 9)		/* Dirty */
#define EPTE_SUP_VE				(1ULL << 63)	/* Suppress virt exceptions */
#define EPTE_P (EPTE_R | EPTE_W | EPTE_X)

/* Types available for the EPTE_MEM_TYPE */
#define EPT_MEM_TYPE_UC			0
#define EPT_MEM_TYPE_WC			1
#define EPT_MEM_TYPE_WT			4
#define EPT_MEM_TYPE_WP			5
#define EPT_MEM_TYPE_WB			6
/* Helper to align the type to its location in the PTE */
#define EPT_MEM_TYPE(type) ((type) << 3)

/* Some machines don't support A and D EPTE bits.  We'll |= 1 in those cases. */
extern int x86_ept_pte_fix_ups;

static inline epte_t *kpte_to_epte(kpte_t *kpte)
{
	return (epte_t*)(((uintptr_t)kpte) + PGSIZE);
}

static inline bool epte_is_present(epte_t *epte)
{
	/* Actually, certain combos, like W but not R could be misconfigurations */
	return *epte & EPTE_P ? TRUE : FALSE;
}

static inline bool epte_is_unmapped(epte_t *epte)
{
	return *epte == 0;
}

static inline bool epte_is_mapped(epte_t *epte)
{
	return *epte != 0;
}

static inline bool epte_is_paged_out(epte_t *epte)
{
	return *epte != 0;
}

/* Some Intel machines don't support A or D.  In these cases, we must assume
 * the pages have been accessed or dirtied... */
static inline bool epte_is_dirty(epte_t *epte)
{
	return (*epte | x86_ept_pte_fix_ups) & EPTE_D ? TRUE : FALSE;
}

static inline bool epte_is_accessed(epte_t *epte)
{
	return (*epte | x86_ept_pte_fix_ups) & EPTE_A ? TRUE : FALSE;
}

static inline bool epte_is_jumbo(epte_t *epte)
{
	return *epte & EPTE_PS ? TRUE : FALSE;
}

static inline physaddr_t epte_get_paddr(epte_t *epte)
{
	/* 63:52 are ignored/flags.  51:12 are the addr.  Technically 51:N must be
	 * 0, where N is the physical addr width */
	return *epte & 0x000ffffffffff000;
}

static inline int __pte_to_epte_perm(int perm)
{
	switch (perm) {
		/* Since we keep the EPT in lockstep with the KPT, we might get some
		 * mapping requests for the kernel (e.g. vmap_pmem).  */
		case PTE_KERN_RW:
		case PTE_KERN_RO:
		case PTE_NONE:
			return 0;
		case PTE_USER_RW:
			return EPTE_W | EPTE_R | EPTE_X;
		case PTE_USER_RO:
			return EPTE_R | EPTE_X;
		default:
			panic("Bad PTE type 0x%x\n", perm);
	}
}

static inline void epte_write(epte_t *epte, physaddr_t pa, int settings)
{
	/* Could put in a check against the max physaddr len */
	epte_t temp = pa;
	temp |= __pte_to_epte_perm(settings & PTE_PERM);
	temp |= settings & PTE_PS ? EPTE_PS : 0;
	/* All memory is WB by default, but the guest can override that with their
	 * PAT on the first page walk (guest KPT/cr3) */
	temp |= EPT_MEM_TYPE(EPT_MEM_TYPE_WB);
	*epte = temp;
}

static inline void epte_clear_present(epte_t *epte)
{
	*epte &= ~EPTE_P;
}

static inline void epte_clear(epte_t *epte)
{
	*epte = 0;
}

static inline bool epte_has_perm_ur(epte_t *epte)
{
	return (*epte & (EPTE_R | EPTE_X)) == (EPTE_R | EPTE_X);
}

static inline bool epte_has_perm_urw(epte_t *epte)
{
	return (*epte & (EPTE_R | EPTE_W | EPTE_X)) == (EPTE_R | EPTE_W | EPTE_X);
}

static inline int epte_get_settings(epte_t *epte)
{
	int settings = 0;
	if (*epte & EPTE_P) {
		/* We want to know User and Writable, in the 'PTE' sense.  All present
		 * epte entries are User PTEs. */
		settings |= PTE_P | PTE_U;
		settings |= *epte & EPTE_W ? PTE_W : 0;
	}
	settings |= *epte & EPTE_PS ? PTE_PS : 0;
	settings |= *epte & EPTE_A ? PTE_A : 0;
	settings |= *epte & EPTE_D ? PTE_D : 0;
	return settings;
}

/* Again, we're replacing the old perms with U and/or W.  Any non-U are ignored,
 * as with epte_write.  */
static inline void epte_replace_perm(epte_t *epte, int perm)
{
	*epte = (*epte & ~EPTE_P) | __pte_to_epte_perm(perm & PTE_PERM);
}

/* These ops might be the same for AMD as Intel; in which case we can move the
 * body of these ept_sync_* funcs into here */
static inline void ept_inval_addr(unsigned long addr)
{
	if (current && current->vmm.vmmcp)
		ept_sync_individual_addr(current->env_pgdir.eptp, addr);
}

static inline void ept_inval_context(void)
{
	if (current && current->vmm.vmmcp)
		ept_sync_context(current->env_pgdir.eptp);
}

static inline void ept_inval_global(void)
{
	ept_sync_global();
}
