#ifndef _NVMM_X86_INTERNAL_H_
#define _NVMM_X86_INTERNAL_H_
#ifndef _KERNEL
#error "This file should not be included by userland programs."
#endif
#include "nvmm_x86.h"
#define NVMM_X86_MACH_NCONF 0
#define NVMM_X86_VCPU_NCONF 2
struct nvmm_x86_cpuid_mask {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
};
struct nvmm_x86_xsave {
struct nvmm_x64_state_fpu fpu;
uint64_t xstate_bv;
uint64_t xcomp_bv;
uint8_t rsvd0[8];
uint8_t rsvd[40];
};
CTASSERT(sizeof(struct nvmm_x86_xsave) == 512 + 64);
extern const struct nvmm_x64_state nvmm_x86_reset_state;
extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001;
extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007;
extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001;
extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007;
extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008;
bool nvmm_x86_pat_validate(uint64_t);
uint32_t nvmm_x86_xsave_size(uint64_t);
#if defined(__NetBSD__)
#include <x86/cpufunc.h>
#include <x86/fpu.h>
#elif defined(__DragonFly__)
#include <machine/cpufunc.h>
#include <machine/npx.h>
#endif
typedef struct {
uint32_t eax, ebx, ecx, edx;
} cpuid_desc_t;
#if defined(__NetBSD__)
#define x86_get_cpuid(l, d) x86_cpuid(l, (uint32_t *)d)
#define x86_get_cpuid2(l, c, d) x86_cpuid2(l, c, (uint32_t *)d)
#elif defined(__DragonFly__)
#define x86_get_cpuid(l, d) do_cpuid(l, (uint32_t *)d)
#define x86_get_cpuid2(l, c, d) cpuid_count(l, c, (uint32_t *)d)
#endif
#if defined(__NetBSD__)
#define x86_get_cr0() rcr0()
#define x86_get_cr2() rcr2()
#define x86_get_cr3() rcr3()
#define x86_get_cr4() rcr4()
#define x86_set_cr0(v) lcr0(v)
#define x86_set_cr2(v) lcr2(v)
#define x86_set_cr4(v) lcr4(v)
#elif defined(__DragonFly__)
#define x86_get_cr0() rcr0()
#define x86_get_cr2() rcr2()
#define x86_get_cr3() rcr3()
#define x86_get_cr4() rcr4()
#define x86_set_cr0(v) load_cr0(v)
#define x86_set_cr2(v) load_cr2(v)
#define x86_set_cr4(v) load_cr4(v)
#endif
#if defined(__NetBSD__)
#include <x86/dbregs.h>
static inline void
x86_curthread_save_dbregs(uint64_t *drs __unused)
{
x86_dbregs_save(curlwp);
}
static inline void
x86_curthread_restore_dbregs(uint64_t *drs __unused)
{
x86_dbregs_restore(curlwp);
}
#define x86_get_dr0() rdr0()
#define x86_get_dr1() rdr1()
#define x86_get_dr2() rdr2()
#define x86_get_dr3() rdr3()
#define x86_get_dr6() rdr6()
#define x86_get_dr7() rdr7()
#define x86_set_dr0(v) ldr0(v)
#define x86_set_dr1(v) ldr1(v)
#define x86_set_dr2(v) ldr2(v)
#define x86_set_dr3(v) ldr3(v)
#define x86_set_dr6(v) ldr6(v)
#define x86_set_dr7(v) ldr7(v)
#elif defined(__DragonFly__)
#include <sys/proc.h>
static inline void
x86_curthread_save_dbregs(uint64_t *drs)
{
struct pcb *pcb = curthread->td_lwp->lwp_thread->td_pcb;
if (__predict_true(!(pcb->pcb_flags & PCB_DBREGS)))
return;
drs[NVMM_X64_DR_DR0] = rdr0();
drs[NVMM_X64_DR_DR1] = rdr1();
drs[NVMM_X64_DR_DR2] = rdr2();
drs[NVMM_X64_DR_DR3] = rdr3();
drs[NVMM_X64_DR_DR6] = rdr6();
drs[NVMM_X64_DR_DR7] = rdr7();
}
static inline void
x86_curthread_restore_dbregs(uint64_t *drs)
{
struct pcb *pcb = curthread->td_lwp->lwp_thread->td_pcb;
if (__predict_true(!(pcb->pcb_flags & PCB_DBREGS)))
return;
load_dr0(drs[NVMM_X64_DR_DR0]);
load_dr1(drs[NVMM_X64_DR_DR1]);
load_dr2(drs[NVMM_X64_DR_DR2]);
load_dr3(drs[NVMM_X64_DR_DR3]);
load_dr6(drs[NVMM_X64_DR_DR6]);
load_dr7(drs[NVMM_X64_DR_DR7]);
}
#define x86_get_dr0() rdr0()
#define x86_get_dr1() rdr1()
#define x86_get_dr2() rdr2()
#define x86_get_dr3() rdr3()
#define x86_get_dr6() rdr6()
#define x86_get_dr7() rdr7()
#define x86_set_dr0(v) load_dr0(v)
#define x86_set_dr1(v) load_dr1(v)
#define x86_set_dr2(v) load_dr2(v)
#define x86_set_dr3(v) load_dr3(v)
#define x86_set_dr6(v) load_dr6(v)
#define x86_set_dr7(v) load_dr7(v)
#endif
#if defined(__NetBSD__)
#define x86_curthread_save_fpu() fpu_kern_enter()
#define x86_curthread_restore_fpu() fpu_kern_leave()
#define x86_save_fpu(a, m) fpu_area_save(a, m, true)
#define x86_restore_fpu(a, m) fpu_area_restore(a, m, true)
#elif defined(__DragonFly__)
#define x86_curthread_save_fpu()
#define x86_curthread_restore_fpu()
#define x86_save_fpu(a, m) \
({ \
fpusave((union savefpu *)(a), m); \
load_cr0(rcr0() | CR0_TS); \
})
#define x86_restore_fpu(a, m) \
({ \
__asm volatile("clts" ::: "memory"); \
fpurstor((union savefpu *)(a), m); \
})
#endif
static inline uint64_t
x86_get_xcr(uint32_t xcr)
{
uint32_t low, high;
__asm volatile (
"xgetbv"
: "=a" (low), "=d" (high)
: "c" (xcr)
);
return (low | ((uint64_t)high << 32));
}
static inline void
x86_set_xcr(uint32_t xcr, uint64_t val)
{
uint32_t low, high;
low = val;
high = val >> 32;
__asm volatile (
"xsetbv"
:
: "a" (low), "d" (high), "c" (xcr)
: "memory"
);
}
#if defined(__DragonFly__)
#define x86_xsave_features npx_xcr0_mask
#define x86_fpu_mxcsr_mask npx_mxcsr_mask
#endif
#endif