Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/amd/svm.c
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | |||||
#define AMD_CPUID_SVM_AVIC BIT(13) /* AVIC present */ | #define AMD_CPUID_SVM_AVIC BIT(13) /* AVIC present */ | ||||
#define VMCB_CACHE_DEFAULT (VMCB_CACHE_ASID | \ | #define VMCB_CACHE_DEFAULT (VMCB_CACHE_ASID | \ | ||||
VMCB_CACHE_IOPM | \ | VMCB_CACHE_IOPM | \ | ||||
VMCB_CACHE_I | \ | VMCB_CACHE_I | \ | ||||
VMCB_CACHE_TPR | \ | VMCB_CACHE_TPR | \ | ||||
VMCB_CACHE_CR2 | \ | VMCB_CACHE_CR2 | \ | ||||
VMCB_CACHE_CR | \ | VMCB_CACHE_CR | \ | ||||
VMCB_CACHE_DR | \ | |||||
VMCB_CACHE_DT | \ | VMCB_CACHE_DT | \ | ||||
VMCB_CACHE_SEG | \ | VMCB_CACHE_SEG | \ | ||||
VMCB_CACHE_NP) | VMCB_CACHE_NP) | ||||
static uint32_t vmcb_clean = VMCB_CACHE_DEFAULT; | static uint32_t vmcb_clean = VMCB_CACHE_DEFAULT; | ||||
SYSCTL_INT(_hw_vmm_svm, OID_AUTO, vmcb_clean, CTLFLAG_RDTUN, &vmcb_clean, | SYSCTL_INT(_hw_vmm_svm, OID_AUTO, vmcb_clean, CTLFLAG_RDTUN, &vmcb_clean, | ||||
0, NULL); | 0, NULL); | ||||
▲ Show 20 Lines • Show All 401 Lines • ▼ Show 20 Lines | vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa, | ||||
state->g_pat = PAT_VALUE(0, PAT_WRITE_BACK) | | state->g_pat = PAT_VALUE(0, PAT_WRITE_BACK) | | ||||
PAT_VALUE(1, PAT_WRITE_THROUGH) | | PAT_VALUE(1, PAT_WRITE_THROUGH) | | ||||
PAT_VALUE(2, PAT_UNCACHED) | | PAT_VALUE(2, PAT_UNCACHED) | | ||||
PAT_VALUE(3, PAT_UNCACHEABLE) | | PAT_VALUE(3, PAT_UNCACHEABLE) | | ||||
PAT_VALUE(4, PAT_WRITE_BACK) | | PAT_VALUE(4, PAT_WRITE_BACK) | | ||||
PAT_VALUE(5, PAT_WRITE_THROUGH) | | PAT_VALUE(5, PAT_WRITE_THROUGH) | | ||||
PAT_VALUE(6, PAT_UNCACHED) | | PAT_VALUE(6, PAT_UNCACHED) | | ||||
PAT_VALUE(7, PAT_UNCACHEABLE); | PAT_VALUE(7, PAT_UNCACHEABLE); | ||||
/* Set up DR6/7 to power-on state */ | |||||
state->dr6 = 0xffff0ff0; | |||||
state->dr7 = 0x400; | |||||
} | } | ||||
/* | /* | ||||
* Initialize a virtual machine. | * Initialize a virtual machine. | ||||
*/ | */ | ||||
static void * | static void * | ||||
svm_vminit(struct vm *vm, pmap_t pmap) | svm_vminit(struct vm *vm, pmap_t pmap) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,391 Lines • ▼ Show 20 Lines | |||||
static __inline void | static __inline void | ||||
enable_gintr(void) | enable_gintr(void) | ||||
{ | { | ||||
__asm __volatile("stgi"); | __asm __volatile("stgi"); | ||||
} | } | ||||
static __inline void | |||||
svm_dr_enter_guest(struct svm_regctx *gctx) | |||||
{ | |||||
/* Save host control debug registers. */ | |||||
gctx->host_dr7 = rdr7(); | |||||
gctx->host_debugctl = rdmsr(MSR_DEBUGCTLMSR); | |||||
/* | /* | ||||
* Disable debugging in DR7 and DEBUGCTL to avoid triggering | |||||
* exceptions in the host based on the guest DRx values. The | |||||
* guest DR6, DR7, and DEBUGCTL are saved/restored in the | |||||
* VMCB. | |||||
*/ | |||||
load_dr7(0); | |||||
wrmsr(MSR_DEBUGCTLMSR, 0); | |||||
/* Save host debug registers. */ | |||||
gctx->host_dr0 = rdr0(); | |||||
gctx->host_dr1 = rdr1(); | |||||
gctx->host_dr2 = rdr2(); | |||||
gctx->host_dr3 = rdr3(); | |||||
gctx->host_dr6 = rdr6(); | |||||
/* Restore guest debug registers. */ | |||||
load_dr0(gctx->sctx_dr0); | |||||
load_dr1(gctx->sctx_dr1); | |||||
load_dr2(gctx->sctx_dr2); | |||||
load_dr3(gctx->sctx_dr3); | |||||
} | |||||
static __inline void | |||||
svm_dr_leave_guest(struct svm_regctx *gctx) | |||||
{ | |||||
/* Save guest debug registers. */ | |||||
gctx->sctx_dr0 = rdr0(); | |||||
gctx->sctx_dr1 = rdr1(); | |||||
gctx->sctx_dr2 = rdr2(); | |||||
gctx->sctx_dr3 = rdr3(); | |||||
/* | |||||
* Restore host debug registers. Restore DR7 and DEBUGCTL | |||||
* last. | |||||
*/ | |||||
load_dr0(gctx->host_dr0); | |||||
load_dr1(gctx->host_dr1); | |||||
load_dr2(gctx->host_dr2); | |||||
load_dr3(gctx->host_dr3); | |||||
load_dr6(gctx->host_dr6); | |||||
wrmsr(MSR_DEBUGCTLMSR, gctx->host_debugctl); | |||||
load_dr7(gctx->host_dr7); | |||||
} | |||||
/* | |||||
* Start vcpu with specified RIP. | * Start vcpu with specified RIP. | ||||
*/ | */ | ||||
static int | static int | ||||
svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap, | svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap, | ||||
struct vm_eventinfo *evinfo) | struct vm_eventinfo *evinfo) | ||||
{ | { | ||||
struct svm_regctx *gctx; | struct svm_regctx *gctx; | ||||
struct svm_softc *svm_sc; | struct svm_softc *svm_sc; | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | do { | ||||
check_asid(svm_sc, vcpu, pmap, curcpu); | check_asid(svm_sc, vcpu, pmap, curcpu); | ||||
ctrl->vmcb_clean = vmcb_clean & ~vcpustate->dirty; | ctrl->vmcb_clean = vmcb_clean & ~vcpustate->dirty; | ||||
vcpustate->dirty = 0; | vcpustate->dirty = 0; | ||||
VCPU_CTR1(vm, vcpu, "vmcb clean %#x", ctrl->vmcb_clean); | VCPU_CTR1(vm, vcpu, "vmcb clean %#x", ctrl->vmcb_clean); | ||||
/* Launch Virtual Machine. */ | /* Launch Virtual Machine. */ | ||||
VCPU_CTR1(vm, vcpu, "Resume execution at %#lx", state->rip); | VCPU_CTR1(vm, vcpu, "Resume execution at %#lx", state->rip); | ||||
svm_dr_enter_guest(gctx); | |||||
svm_launch(vmcb_pa, gctx, &__pcpu[curcpu]); | svm_launch(vmcb_pa, gctx, &__pcpu[curcpu]); | ||||
svm_dr_leave_guest(gctx); | |||||
CPU_CLR_ATOMIC(curcpu, &pmap->pm_active); | CPU_CLR_ATOMIC(curcpu, &pmap->pm_active); | ||||
/* | /* | ||||
* The host GDTR and IDTR is saved by VMRUN and restored | * The host GDTR and IDTR is saved by VMRUN and restored | ||||
* automatically on #VMEXIT. However, the host TSS needs | * automatically on #VMEXIT. However, the host TSS needs | ||||
* to be restored explicitly. | * to be restored explicitly. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | swctx_regptr(struct svm_regctx *regctx, int reg) | ||||
case VM_REG_GUEST_R12: | case VM_REG_GUEST_R12: | ||||
return (®ctx->sctx_r12); | return (®ctx->sctx_r12); | ||||
case VM_REG_GUEST_R13: | case VM_REG_GUEST_R13: | ||||
return (®ctx->sctx_r13); | return (®ctx->sctx_r13); | ||||
case VM_REG_GUEST_R14: | case VM_REG_GUEST_R14: | ||||
return (®ctx->sctx_r14); | return (®ctx->sctx_r14); | ||||
case VM_REG_GUEST_R15: | case VM_REG_GUEST_R15: | ||||
return (®ctx->sctx_r15); | return (®ctx->sctx_r15); | ||||
case VM_REG_GUEST_DR0: | |||||
return (®ctx->sctx_dr0); | |||||
case VM_REG_GUEST_DR1: | |||||
return (®ctx->sctx_dr1); | |||||
case VM_REG_GUEST_DR2: | |||||
return (®ctx->sctx_dr2); | |||||
case VM_REG_GUEST_DR3: | |||||
return (®ctx->sctx_dr3); | |||||
default: | default: | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
svm_getreg(void *arg, int vcpu, int ident, uint64_t *val) | svm_getreg(void *arg, int vcpu, int ident, uint64_t *val) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 157 Lines • Show Last 20 Lines |