#ifndef _MACHINE_PMAP_H_
#define _MACHINE_PMAP_H_
#ifdef _KERNEL
#include <machine/cpufunc.h>
#include <machine/segments.h>
#endif
#include <sys/mutex.h>
#include <uvm/uvm_object.h>
#include <machine/pte.h>
#define PDSLOT_PTE ((KERNBASE/NBPD)-2)
#define PDSLOT_KERN (KERNBASE/NBPD)
#define PDSLOT_APTE ((unsigned)1022)
#ifndef NKPTP
#define NKPTP 8
#endif
#define NKPTP_MIN 4
#define PG_W PG_AVAIL1
#define PG_PVLIST PG_AVAIL2
#define PG_X PG_AVAIL3
#define PTP0_PA (PAGE_SIZE * 3)
#ifdef _KERNEL
struct pmap;
typedef struct pmap *pmap_t;
LIST_HEAD(pmap_head, pmap);
struct pmap {
uint64_t pm_pdidx[4];
uint64_t pm_pdidx_intel[4];
struct mutex pm_mtx;
struct mutex pm_apte_mtx;
paddr_t pm_pdirpa, pm_pdirpa_intel;
vaddr_t pm_pdir, pm_pdir_intel;
int pm_pdirsize;
struct uvm_object pm_obj;
LIST_ENTRY(pmap) pm_list;
struct vm_page *pm_ptphint;
struct pmap_statistics pm_stats;
vaddr_t pm_hiexec;
int pm_flags;
struct segment_descriptor pm_codeseg;
};
struct pv_entry {
struct pv_entry *pv_next;
struct pmap *pv_pmap;
vaddr_t pv_va;
struct vm_page *pv_ptp;
};
#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK)
#define PMAP_NOCACHE 0x1
#define PMAP_WC 0x2
#define PG_PMAP_MOD PG_PMAP0
#define PG_PMAP_REF PG_PMAP1
#define PG_PMAP_WC PG_PMAP2
struct pv_page_info {
TAILQ_ENTRY(pv_page) pvpi_list;
struct pv_entry *pvpi_pvfree;
int pvpi_nfree;
};
#define PVE_PER_PVPAGE ((PAGE_SIZE - sizeof(struct pv_page_info)) / \
sizeof(struct pv_entry))
struct pv_page {
struct pv_page_info pvinfo;
struct pv_entry pvents[PVE_PER_PVPAGE];
};
extern char PTD[];
extern struct pmap kernel_pmap_store;
extern int nkptp_max;
#define PMAP_REMOVE_ALL 0
#define PMAP_REMOVE_SKIPWIRED 1
extern struct pool pmap_pv_pool;
#define pmap_kernel() (&kernel_pmap_store)
#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
#define pmap_update(pm)
#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M)
#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U)
#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M)
#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U)
#define pmap_valid_entry(E) ((E) & PG_V)
#define pmap_proc_iflush(p,va,len)
#define pmap_init_percpu() do { } while (0)
#define pmap_unuse_final(p)
#define pmap_remove_holes(vm) do { } while (0)
vaddr_t pmap_tmpmap_pa_86(paddr_t);
vaddr_t pmap_tmpmap_pa(paddr_t);
void pmap_tmpunmap_pa_86(void);
void pmap_tmpunmap_pa(void);
void pmap_bootstrap(vaddr_t);
void pmap_bootstrap_pae(void);
void pmap_virtual_space(vaddr_t *, vaddr_t *);
void pmap_init(void);
struct pmap *pmap_create(void);
void pmap_destroy(struct pmap *);
void pmap_reference(struct pmap *);
void pmap_remove(struct pmap *, vaddr_t, vaddr_t);
void pmap_activate(struct proc *);
void pmap_deactivate(struct proc *);
void pmap_kenter_pa(vaddr_t, paddr_t, vm_prot_t);
void pmap_kremove(vaddr_t, vsize_t);
void pmap_zero_page(struct vm_page *);
void pmap_copy_page(struct vm_page *, struct vm_page *);
void pmap_enter_pv(struct vm_page *, struct pv_entry *,
struct pmap *, vaddr_t, struct vm_page *);
int pmap_clear_attrs(struct vm_page *, int);
static void pmap_page_protect(struct vm_page *, vm_prot_t);
void pmap_page_remove(struct vm_page *);
static void pmap_protect(struct pmap *, vaddr_t,
vaddr_t, vm_prot_t);
void pmap_remove(struct pmap *, vaddr_t, vaddr_t);
int pmap_test_attrs(struct vm_page *, int);
void pmap_write_protect(struct pmap *, vaddr_t,
vaddr_t, vm_prot_t);
int pmap_exec_fixup(struct vm_map *, struct trapframe *,
vaddr_t, struct pcb *);
void pmap_exec_account(struct pmap *, vaddr_t, u_int32_t,
u_int32_t);
struct pv_entry *pmap_remove_pv(struct vm_page *, struct pmap *, vaddr_t);
void pmap_apte_flush(void);
void pmap_switch(struct proc *, struct proc *);
vaddr_t reserve_dumppages(vaddr_t);
paddr_t vtophys(vaddr_t va);
paddr_t vtophys_pae(vaddr_t va);
extern u_int32_t (*pmap_pte_set_p)(vaddr_t, paddr_t, u_int32_t);
extern u_int32_t (*pmap_pte_setbits_p)(vaddr_t, u_int32_t, u_int32_t);
extern u_int32_t (*pmap_pte_bits_p)(vaddr_t);
extern paddr_t (*pmap_pte_paddr_p)(vaddr_t);
extern int (*pmap_clear_attrs_p)(struct vm_page *, int);
extern int (*pmap_enter_p)(pmap_t, vaddr_t, paddr_t, vm_prot_t, int);
extern void (*pmap_enter_special_p)(vaddr_t, paddr_t, vm_prot_t, u_int32_t);
extern int (*pmap_extract_p)(pmap_t, vaddr_t, paddr_t *);
extern vaddr_t (*pmap_growkernel_p)(vaddr_t);
extern void (*pmap_page_remove_p)(struct vm_page *);
extern void (*pmap_do_remove_p)(struct pmap *, vaddr_t, vaddr_t, int);
extern int (*pmap_test_attrs_p)(struct vm_page *, int);
extern void (*pmap_unwire_p)(struct pmap *, vaddr_t);
extern void (*pmap_write_protect_p)(struct pmap*, vaddr_t, vaddr_t, vm_prot_t);
extern void (*pmap_pinit_pd_p)(pmap_t);
extern void (*pmap_zero_phys_p)(paddr_t);
extern void (*pmap_copy_page_p)(struct vm_page *, struct vm_page *);
u_int32_t pmap_pte_set_pae(vaddr_t, paddr_t, u_int32_t);
u_int32_t pmap_pte_setbits_pae(vaddr_t, u_int32_t, u_int32_t);
u_int32_t pmap_pte_bits_pae(vaddr_t);
paddr_t pmap_pte_paddr_pae(vaddr_t);
int pmap_clear_attrs_pae(struct vm_page *, int);
int pmap_enter_pae(pmap_t, vaddr_t, paddr_t, vm_prot_t, int);
void pmap_enter_special_pae(vaddr_t, paddr_t, vm_prot_t, u_int32_t);
int pmap_extract_pae(pmap_t, vaddr_t, paddr_t *);
vaddr_t pmap_growkernel_pae(vaddr_t);
void pmap_page_remove_pae(struct vm_page *);
void pmap_do_remove_pae(struct pmap *, vaddr_t, vaddr_t, int);
int pmap_test_attrs_pae(struct vm_page *, int);
void pmap_unwire_pae(struct pmap *, vaddr_t);
void pmap_write_protect_pae(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
void pmap_pinit_pd_pae(pmap_t);
void pmap_zero_phys_pae(paddr_t);
void pmap_copy_page_pae(struct vm_page *, struct vm_page *);
#define pmap_pte_set (*pmap_pte_set_p)
#define pmap_pte_setbits (*pmap_pte_setbits_p)
#define pmap_pte_bits (*pmap_pte_bits_p)
#define pmap_pte_paddr (*pmap_pte_paddr_p)
#define pmap_clear_attrs (*pmap_clear_attrs_p)
#define pmap_page_remove (*pmap_page_remove_p)
#define pmap_do_remove (*pmap_do_remove_p)
#define pmap_test_attrs (*pmap_test_attrs_p)
#define pmap_unwire (*pmap_unwire_p)
#define pmap_write_protect (*pmap_write_protect_p)
#define pmap_pinit_pd (*pmap_pinit_pd_p)
#define pmap_zero_phys (*pmap_zero_phys_p)
#define pmap_copy_page (*pmap_copy_page_p)
u_int32_t pmap_pte_set_86(vaddr_t, paddr_t, u_int32_t);
u_int32_t pmap_pte_setbits_86(vaddr_t, u_int32_t, u_int32_t);
u_int32_t pmap_pte_bits_86(vaddr_t);
paddr_t pmap_pte_paddr_86(vaddr_t);
int pmap_clear_attrs_86(struct vm_page *, int);
int pmap_enter_86(pmap_t, vaddr_t, paddr_t, vm_prot_t, int);
void pmap_enter_special_86(vaddr_t, paddr_t, vm_prot_t, u_int32_t);
int pmap_extract_86(pmap_t, vaddr_t, paddr_t *);
vaddr_t pmap_growkernel_86(vaddr_t);
void pmap_page_remove_86(struct vm_page *);
void pmap_do_remove_86(struct pmap *, vaddr_t, vaddr_t, int);
int pmap_test_attrs_86(struct vm_page *, int);
void pmap_unwire_86(struct pmap *, vaddr_t);
void pmap_write_protect_86(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
void pmap_pinit_pd_86(pmap_t);
void pmap_zero_phys_86(paddr_t);
void pmap_copy_page_86(struct vm_page *, struct vm_page *);
void pmap_tlb_shootpage(struct pmap *, vaddr_t);
void pmap_tlb_shootrange(struct pmap *, vaddr_t, vaddr_t);
void pmap_tlb_shoottlb(void);
#ifdef MULTIPROCESSOR
void pmap_tlb_droppmap(struct pmap *);
void pmap_tlb_shootwait(void);
#else
#define pmap_tlb_shootwait()
#endif
void pmap_prealloc_lowmem_ptp(void);
void pmap_prealloc_lowmem_ptp_pae(void);
vaddr_t pmap_tmpmap_pa(paddr_t);
void pmap_tmpunmap_pa(void);
vaddr_t pmap_tmpmap_pa_pae(paddr_t);
void pmap_tmpunmap_pa_pae(void);
void pmap_flush_cache(vaddr_t, vsize_t);
void pmap_flush_page(paddr_t);
void pmap_flush_page_pae(paddr_t);
#define PMAP_CHECK_COPYIN 1
#define PMAP_GROWKERNEL
#define pmap_update_pg(va) invlpg((u_int)(va))
#define pmap_update_2pg(va, vb) { invlpg((u_int)(va)); invlpg((u_int)(vb)); }
static __inline void
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
{
if ((prot & PROT_WRITE) == 0) {
if (prot & (PROT_READ | PROT_EXEC)) {
(void) pmap_clear_attrs(pg, PG_RW);
} else {
pmap_page_remove(pg);
}
}
}
static __inline void
pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
if ((prot & PROT_WRITE) == 0) {
if (prot & (PROT_READ | PROT_EXEC)) {
pmap_write_protect(pmap, sva, eva, prot);
} else {
pmap_remove(pmap, sva, eva);
}
}
}
static __inline vaddr_t
pmap_growkernel(vaddr_t maxkvaddr)
{
return (*pmap_growkernel_p)(maxkvaddr);
}
static __inline int
pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
{
return (*pmap_enter_p)(pmap, va, pa, prot, flags);
}
static __inline void
pmap_enter_special(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int32_t flags)
{
(*pmap_enter_special_p)(va, pa, prot, flags);
}
static __inline int
pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pa)
{
return (*pmap_extract_p)(pmap, va, pa);
}
static __inline int
pmap_is_active(struct pmap *pmap, struct cpu_info *ci)
{
return (pmap == pmap_kernel() || ci->ci_curpmap == pmap);
}
static __inline int
pmap_is_curpmap(struct pmap *pmap)
{
return (pmap_is_active(pmap, curcpu()));
}
#endif
struct pv_entry;
struct vm_page_md {
struct mutex pv_mtx;
struct pv_entry *pv_list;
};
#define VM_MDPAGE_INIT(pg) do { \
mtx_init(&(pg)->mdpage.pv_mtx, IPL_VM); \
(pg)->mdpage.pv_list = NULL; \
} while (0)
#endif