#ifndef _MACHINE_PMAP_H_
#define _MACHINE_PMAP_H_
#include <cpu/pmap.h>
#define KVADDR(l4, l3, l2, l1) ( \
((unsigned long)-1 << 47) | \
((unsigned long)(l4) << PML4SHIFT) | \
((unsigned long)(l3) << PDPSHIFT) | \
((unsigned long)(l2) << PDRSHIFT) | \
((unsigned long)(l1) << PAGE_SHIFT))
#define UVADDR(l4, l3, l2, l1) ( \
((unsigned long)(l4) << PML4SHIFT) | \
((unsigned long)(l3) << PDPSHIFT) | \
((unsigned long)(l2) << PDRSHIFT) | \
((unsigned long)(l1) << PAGE_SHIFT))
#define NKPML4E 16
#define NUPDP_USER (NPML4EPG/2)
#define NUPDP_TOTAL (NPML4EPG)
#define NUPD_TOTAL (NPDPEPG * NUPDP_TOTAL)
#define NUPT_TOTAL (NPDEPG * NUPD_TOTAL)
#define NUPTE_TOTAL ((vm_pindex_t)NPTEPG * NUPT_TOTAL)
#define NUPTE_USER ((vm_pindex_t)NPTEPG * NPDEPG * NPDPEPG * NUPDP_USER)
#define NDMPML4E 128
#define PML4PML4I (NPML4EPG/2)
#define KPML4I (NPML4EPG-NKPML4E)
#define DMPML4I (KPML4I-NDMPML4E)
#if NKPML4E + NDMPML4E >= 255
#error "NKPML4E or NDMPML4E is too large"
#endif
#define KPDPI (NPDPEPG-2)
#define MPPML4I (KPML4I + NKPML4E - 1)
#define MPPDPI KPDPI
#define MPPTDI (NPDEPG-8)
#define ISA_HOLE_START 0xa0000
#define ISA_HOLE_LENGTH (0x100000-ISA_HOLE_START)
#ifndef LOCORE
#ifndef _SYS_TYPES_H_
#include <sys/types.h>
#endif
#ifndef _SYS_CPUMASK_H_
#include <sys/cpumask.h>
#endif
#ifndef _SYS_QUEUE_H_
#include <sys/queue.h>
#endif
#ifndef _SYS_TREE_H_
#include <sys/tree.h>
#endif
#ifndef _SYS_SPINLOCK_H_
#include <sys/spinlock.h>
#endif
#ifndef _SYS_THREAD_H_
#include <sys/thread.h>
#endif
#ifndef _MACHINE_TYPES_H_
#include <machine/types.h>
#endif
#ifndef _MACHINE_PARAM_H_
#include <machine/param.h>
#endif
#ifdef _KERNEL
#define addr_PTmap (KVADDR(PML4PML4I, 0, 0, 0))
#define addr_PDmap (KVADDR(PML4PML4I, PML4PML4I, 0, 0))
#define addr_PDPmap (KVADDR(PML4PML4I, PML4PML4I, PML4PML4I, 0))
#define addr_PML4map (KVADDR(PML4PML4I, PML4PML4I, PML4PML4I, PML4PML4I))
#define addr_PML4pml4e (addr_PML4map + (PML4PML4I * sizeof(pml4_entry_t)))
#define PTmap ((pt_entry_t *)(addr_PTmap))
#define PDmap ((pd_entry_t *)(addr_PDmap))
#define PDPmap ((pd_entry_t *)(addr_PDPmap))
#define PML4map ((pd_entry_t *)(addr_PML4map))
#define PML4pml4e ((pd_entry_t *)(addr_PML4pml4e))
extern uint64_t KPDPphys;
extern uint64_t KPML4phys;
#endif
struct pmap;
struct pv_entry;
struct vm_page;
struct vm_object;
struct vmspace;
struct md_page {
long interlock_count;
long writeable_count_unused;
};
#define MD_PAGE_FREEABLE(m) \
(((m)->flags & (PG_MAPPED | PG_WRITEABLE)) == 0)
struct md_object {
void *dummy_unused;
};
struct pmap_statistics {
long resident_count;
long wired_count;
};
typedef struct pmap_statistics *pmap_statistics_t;
struct pv_entry_rb_tree;
RB_PROTOTYPE2(pv_entry_rb_tree, pv_entry, pv_entry,
pv_entry_compare, vm_pindex_t);
#define REGULAR_PMAP 0
#define EPT_PMAP 1
#define NPT_PMAP 2
enum {
TYPE_IDX = 0,
PG_V_IDX,
PG_RW_IDX,
PG_U_IDX,
PG_A_IDX,
PG_M_IDX,
PG_PS_IDX,
PG_G_IDX,
PG_W_IDX,
PG_MANAGED_IDX,
PG_N_IDX,
PG_NX_IDX,
PG_BITS_SIZE,
};
#define PROTECTION_CODES_SIZE 8
#define PAT_INDEX_SIZE 8
#define PM_PLACEMARKS 64
#define PM_NOPLACEMARK ((vm_pindex_t)-1)
#define PM_PLACEMARK_WAKEUP ((vm_pindex_t)0x8000000000000000LLU)
struct pmap {
pml4_entry_t *pm_pml4;
pml4_entry_t *pm_pml4_iso;
struct pv_entry *pm_pmlpv;
struct pv_entry *pm_pmlpv_iso;
TAILQ_ENTRY(pmap) pm_pmnode;
RB_HEAD(pv_entry_rb_tree, pv_entry) pm_pvroot;
int pm_count;
cpulock_t pm_active_lock;
cpumask_t pm_active;
int pm_flags;
uint32_t pm_softhold;
struct pmap_statistics pm_stats;
struct spinlock pm_spin;
struct pv_entry *pm_pvhint_pt;
struct pv_entry *pm_pvhint_unused;
vm_pindex_t pm_placemarks[PM_PLACEMARKS];
uint64_t pm_invgen;
uint64_t pmap_bits[PG_BITS_SIZE];
uint64_t protection_codes[PROTECTION_CODES_SIZE];
pt_entry_t pmap_cache_bits_pte[PAT_INDEX_SIZE];
pt_entry_t pmap_cache_bits_pde[PAT_INDEX_SIZE];
pt_entry_t pmap_cache_mask_pte;
pt_entry_t pmap_cache_mask_pde;
int (*copyinstr)(const void *, void *, size_t, size_t *);
int (*copyin)(const void *, void *, size_t);
int (*copyout)(const void *, void *, size_t);
int (*fubyte)(const uint8_t *);
int (*subyte)(uint8_t *, uint8_t);
int32_t (*fuword32)(const uint32_t *);
int64_t (*fuword64)(const uint64_t *);
int (*suword64)(uint64_t *, uint64_t);
int (*suword32)(uint32_t *, int);
uint32_t (*swapu32)(volatile uint32_t *, uint32_t v);
uint64_t (*swapu64)(volatile uint64_t *, uint64_t v);
uint32_t (*fuwordadd32)(volatile uint32_t *, uint32_t v);
uint64_t (*fuwordadd64)(volatile uint64_t *, uint64_t v);
};
#define PMAP_FLAG_SIMPLE 0x00000001
#define PMAP_EMULATE_AD_BITS 0x00000002
#define PMAP_HVM 0x00000004
#define PMAP_SEGSHARED 0x00000008
#define PMAP_MULTI 0x00000010
#define pmap_resident_count(pmap) \
((pmap)->pm_stats.resident_count)
#define pmap_resident_tlnw_count(pmap) \
((pmap)->pm_stats.resident_count - (pmap)->pm_stats.wired_count)
typedef struct pmap *pmap_t;
#ifdef _KERNEL
extern struct pmap *kernel_pmap;
#endif
typedef struct pv_entry {
pmap_t pv_pmap;
vm_pindex_t pv_pindex;
RB_ENTRY(pv_entry) pv_entry;
struct vm_page *pv_m;
u_int pv_hold;
u_int pv_flags;
#ifdef PMAP_DEBUG
const char *pv_func;
int pv_line;
const char *pv_func_lastfree;
int pv_line_lastfree;
#endif
} *pv_entry_t;
#define PV_HOLD_LOCKED 0x80000000U
#define PV_HOLD_WAITING 0x40000000U
#define PV_HOLD_UNUSED2000 0x20000000U
#define PV_HOLD_MASK 0x1FFFFFFFU
#define PV_FLAG_UNUSED01 0x00000001U
#define PV_FLAG_UNUSED02 0x00000002U
#ifdef _KERNEL
extern caddr_t CADDR1;
extern pt_entry_t *CMAP1;
extern vm_paddr_t avail_end;
extern vm_paddr_t avail_start;
extern vm_offset_t clean_eva;
extern vm_offset_t clean_sva;
extern char *ptvmmap;
#ifndef __VM_PAGE_T_DEFINED__
#define __VM_PAGE_T_DEFINED__
typedef struct vm_page *vm_page_t;
#endif
#ifndef __VM_MEMATTR_T_DEFINED__
#define __VM_MEMATTR_T_DEFINED__
typedef char vm_memattr_t;
#endif
void pmap_release(struct pmap *pmap);
void pmap_interlock_wait (struct vmspace *);
void pmap_bootstrap (vm_paddr_t *);
void *pmap_mapbios(vm_paddr_t, vm_size_t);
void *pmap_mapdev (vm_paddr_t, vm_size_t);
void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int);
void *pmap_mapdev_uncacheable(vm_paddr_t, vm_size_t);
void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);
void pmap_unmapdev (vm_offset_t, vm_size_t);
struct vm_page *pmap_use_pt (pmap_t, vm_offset_t);
void pmap_set_opt (void);
void pmap_init_pat(void);
void pmap_invalidate_cache_pages(vm_page_t *pages, int count);
void pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
static __inline int
pmap_emulate_ad_bits(pmap_t pmap) {
return pmap->pm_flags & PMAP_EMULATE_AD_BITS;
}
#endif
#endif
#endif