Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/intel/vmx.c
Show First 20 Lines • Show All 604 Lines • ▼ Show 20 Lines | if (vmxon_enabled[curcpu]) { | ||||
invvpid(INVVPID_TYPE_ALL_CONTEXTS, invvpid_desc); | invvpid(INVVPID_TYPE_ALL_CONTEXTS, invvpid_desc); | ||||
invept(INVEPT_TYPE_ALL_CONTEXTS, invept_desc); | invept(INVEPT_TYPE_ALL_CONTEXTS, invept_desc); | ||||
vmxoff(); | vmxoff(); | ||||
} | } | ||||
load_cr4(rcr4() & ~CR4_VMXE); | load_cr4(rcr4() & ~CR4_VMXE); | ||||
} | } | ||||
static int | static int | ||||
vmx_cleanup(void) | vmx_modcleanup(void) | ||||
{ | { | ||||
if (pirvec >= 0) | if (pirvec >= 0) | ||||
lapic_ipi_free(pirvec); | lapic_ipi_free(pirvec); | ||||
if (vpid_unr != NULL) { | if (vpid_unr != NULL) { | ||||
delete_unrhdr(vpid_unr); | delete_unrhdr(vpid_unr); | ||||
vpid_unr = NULL; | vpid_unr = NULL; | ||||
Show All 25 Lines | vmx_enable(void *arg __unused) | ||||
*(uint32_t *)vmxon_region[curcpu] = vmx_revision(); | *(uint32_t *)vmxon_region[curcpu] = vmx_revision(); | ||||
error = vmxon(vmxon_region[curcpu]); | error = vmxon(vmxon_region[curcpu]); | ||||
if (error == 0) | if (error == 0) | ||||
vmxon_enabled[curcpu] = 1; | vmxon_enabled[curcpu] = 1; | ||||
} | } | ||||
static void | static void | ||||
vmx_restore(void) | vmx_modresume(void) | ||||
{ | { | ||||
if (vmxon_enabled[curcpu]) | if (vmxon_enabled[curcpu]) | ||||
vmxon(vmxon_region[curcpu]); | vmxon(vmxon_region[curcpu]); | ||||
} | } | ||||
static int | static int | ||||
vmx_init(int ipinum) | vmx_modinit(int ipinum) | ||||
{ | { | ||||
int error; | int error; | ||||
uint64_t basic, fixed0, fixed1, feature_control; | uint64_t basic, fixed0, fixed1, feature_control; | ||||
uint32_t tmp, procbased2_vid_bits; | uint32_t tmp, procbased2_vid_bits; | ||||
/* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */ | /* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */ | ||||
if (!(cpu_feature2 & CPUID2_VMX)) { | if (!(cpu_feature2 & CPUID2_VMX)) { | ||||
printf("vmx_init: processor does not support VMX operation\n"); | printf("vmx_modinit: processor does not support VMX " | ||||
"operation\n"); | |||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* | /* | ||||
* Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits | * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits | ||||
* are set (bits 0 and 2 respectively). | * are set (bits 0 and 2 respectively). | ||||
*/ | */ | ||||
feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); | feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); | ||||
if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 1 && | if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 1 && | ||||
(feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { | (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { | ||||
printf("vmx_init: VMX operation disabled by BIOS\n"); | printf("vmx_modinit: VMX operation disabled by BIOS\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* | /* | ||||
* Verify capabilities MSR_VMX_BASIC: | * Verify capabilities MSR_VMX_BASIC: | ||||
* - bit 54 indicates support for INS/OUTS decoding | * - bit 54 indicates support for INS/OUTS decoding | ||||
*/ | */ | ||||
basic = rdmsr(MSR_VMX_BASIC); | basic = rdmsr(MSR_VMX_BASIC); | ||||
if ((basic & (1UL << 54)) == 0) { | if ((basic & (1UL << 54)) == 0) { | ||||
printf("vmx_init: processor does not support desired basic " | printf("vmx_modinit: processor does not support desired basic " | ||||
"capabilities\n"); | "capabilities\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Check support for primary processor-based VM-execution controls */ | /* Check support for primary processor-based VM-execution controls */ | ||||
error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS, | error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS, | ||||
MSR_VMX_TRUE_PROCBASED_CTLS, | MSR_VMX_TRUE_PROCBASED_CTLS, | ||||
PROCBASED_CTLS_ONE_SETTING, | PROCBASED_CTLS_ONE_SETTING, | ||||
PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls); | PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: processor does not support desired primary " | printf("vmx_modinit: processor does not support desired " | ||||
"processor-based controls\n"); | "primary processor-based controls\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Clear the processor-based ctl bits that are set on demand */ | /* Clear the processor-based ctl bits that are set on demand */ | ||||
procbased_ctls &= ~PROCBASED_CTLS_WINDOW_SETTING; | procbased_ctls &= ~PROCBASED_CTLS_WINDOW_SETTING; | ||||
/* Check support for secondary processor-based VM-execution controls */ | /* Check support for secondary processor-based VM-execution controls */ | ||||
error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, | error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, | ||||
MSR_VMX_PROCBASED_CTLS2, | MSR_VMX_PROCBASED_CTLS2, | ||||
PROCBASED_CTLS2_ONE_SETTING, | PROCBASED_CTLS2_ONE_SETTING, | ||||
PROCBASED_CTLS2_ZERO_SETTING, &procbased_ctls2); | PROCBASED_CTLS2_ZERO_SETTING, &procbased_ctls2); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: processor does not support desired secondary " | printf("vmx_modinit: processor does not support desired " | ||||
"processor-based controls\n"); | "secondary processor-based controls\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Check support for VPID */ | /* Check support for VPID */ | ||||
error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2, | error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2, | ||||
PROCBASED2_ENABLE_VPID, 0, &tmp); | PROCBASED2_ENABLE_VPID, 0, &tmp); | ||||
if (error == 0) | if (error == 0) | ||||
procbased_ctls2 |= PROCBASED2_ENABLE_VPID; | procbased_ctls2 |= PROCBASED2_ENABLE_VPID; | ||||
/* Check support for pin-based VM-execution controls */ | /* Check support for pin-based VM-execution controls */ | ||||
error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS, | error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS, | ||||
MSR_VMX_TRUE_PINBASED_CTLS, | MSR_VMX_TRUE_PINBASED_CTLS, | ||||
PINBASED_CTLS_ONE_SETTING, | PINBASED_CTLS_ONE_SETTING, | ||||
PINBASED_CTLS_ZERO_SETTING, &pinbased_ctls); | PINBASED_CTLS_ZERO_SETTING, &pinbased_ctls); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: processor does not support desired " | printf("vmx_modinit: processor does not support desired " | ||||
"pin-based controls\n"); | "pin-based controls\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Check support for VM-exit controls */ | /* Check support for VM-exit controls */ | ||||
error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS, | error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS, | ||||
VM_EXIT_CTLS_ONE_SETTING, | VM_EXIT_CTLS_ONE_SETTING, | ||||
VM_EXIT_CTLS_ZERO_SETTING, | VM_EXIT_CTLS_ZERO_SETTING, | ||||
&exit_ctls); | &exit_ctls); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: processor does not support desired " | printf("vmx_modinit: processor does not support desired " | ||||
"exit controls\n"); | "exit controls\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Check support for VM-entry controls */ | /* Check support for VM-entry controls */ | ||||
error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS, MSR_VMX_TRUE_ENTRY_CTLS, | error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS, MSR_VMX_TRUE_ENTRY_CTLS, | ||||
VM_ENTRY_CTLS_ONE_SETTING, VM_ENTRY_CTLS_ZERO_SETTING, | VM_ENTRY_CTLS_ONE_SETTING, VM_ENTRY_CTLS_ZERO_SETTING, | ||||
&entry_ctls); | &entry_ctls); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: processor does not support desired " | printf("vmx_modinit: processor does not support desired " | ||||
"entry controls\n"); | "entry controls\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Check support for optional features by testing them | * Check support for optional features by testing them | ||||
* as individual bits | * as individual bits | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | if (virtual_interrupt_delivery) { | ||||
error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS, | error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS, | ||||
MSR_VMX_TRUE_PINBASED_CTLS, PINBASED_POSTED_INTERRUPT, 0, | MSR_VMX_TRUE_PINBASED_CTLS, PINBASED_POSTED_INTERRUPT, 0, | ||||
&tmp); | &tmp); | ||||
if (error == 0) { | if (error == 0) { | ||||
pirvec = lapic_ipi_alloc(pti ? &IDTVEC(justreturn1_pti) : | pirvec = lapic_ipi_alloc(pti ? &IDTVEC(justreturn1_pti) : | ||||
&IDTVEC(justreturn)); | &IDTVEC(justreturn)); | ||||
if (pirvec < 0) { | if (pirvec < 0) { | ||||
if (bootverbose) { | if (bootverbose) { | ||||
printf("vmx_init: unable to allocate " | printf("vmx_modinit: unable to " | ||||
"posted interrupt vector\n"); | "allocate posted interrupt " | ||||
"vector\n"); | |||||
} | } | ||||
} else { | } else { | ||||
posted_interrupts = 1; | posted_interrupts = 1; | ||||
TUNABLE_INT_FETCH("hw.vmm.vmx.use_apic_pir", | TUNABLE_INT_FETCH("hw.vmm.vmx.use_apic_pir", | ||||
&posted_interrupts); | &posted_interrupts); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (posted_interrupts) | if (posted_interrupts) | ||||
pinbased_ctls |= PINBASED_POSTED_INTERRUPT; | pinbased_ctls |= PINBASED_POSTED_INTERRUPT; | ||||
/* Initialize EPT */ | /* Initialize EPT */ | ||||
error = ept_init(ipinum); | error = ept_init(ipinum); | ||||
if (error) { | if (error) { | ||||
printf("vmx_init: ept initialization failed (%d)\n", error); | printf("vmx_modinit: ept initialization failed (%d)\n", error); | ||||
return (error); | return (error); | ||||
} | } | ||||
guest_l1d_flush = (cpu_ia32_arch_caps & | guest_l1d_flush = (cpu_ia32_arch_caps & | ||||
IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY) == 0; | IA32_ARCH_CAP_SKIP_L1DFL_VMENTRY) == 0; | ||||
TUNABLE_INT_FETCH("hw.vmm.l1d_flush", &guest_l1d_flush); | TUNABLE_INT_FETCH("hw.vmm.l1d_flush", &guest_l1d_flush); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | if (error) | ||||
return (error); | return (error); | ||||
return (0); | return (0); | ||||
} | } | ||||
#define vmx_setup_cr0_shadow(vmcs,init) vmx_setup_cr_shadow(0, (vmcs), (init)) | #define vmx_setup_cr0_shadow(vmcs,init) vmx_setup_cr_shadow(0, (vmcs), (init)) | ||||
#define vmx_setup_cr4_shadow(vmcs,init) vmx_setup_cr_shadow(4, (vmcs), (init)) | #define vmx_setup_cr4_shadow(vmcs,init) vmx_setup_cr_shadow(4, (vmcs), (init)) | ||||
static void * | static void * | ||||
vmx_vminit(struct vm *vm, pmap_t pmap) | vmx_init(struct vm *vm, pmap_t pmap) | ||||
{ | { | ||||
uint16_t vpid[VM_MAXCPU]; | uint16_t vpid[VM_MAXCPU]; | ||||
int i, error; | int i, error; | ||||
struct vmx *vmx; | struct vmx *vmx; | ||||
struct vmcs *vmcs; | struct vmcs *vmcs; | ||||
uint32_t exc_bitmap; | uint32_t exc_bitmap; | ||||
uint16_t maxcpus; | uint16_t maxcpus; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | vmx_init(struct vm *vm, pmap_t pmap) | ||||
if (guest_msr_rw(vmx, MSR_GSBASE) || | if (guest_msr_rw(vmx, MSR_GSBASE) || | ||||
guest_msr_rw(vmx, MSR_FSBASE) || | guest_msr_rw(vmx, MSR_FSBASE) || | ||||
guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) || | guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) || | ||||
guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) || | guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) || | ||||
guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) || | guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) || | ||||
guest_msr_rw(vmx, MSR_EFER) || | guest_msr_rw(vmx, MSR_EFER) || | ||||
guest_msr_ro(vmx, MSR_TSC) || | guest_msr_ro(vmx, MSR_TSC) || | ||||
((cap_rdpid || cap_rdtscp) && guest_msr_ro(vmx, MSR_TSC_AUX))) | ((cap_rdpid || cap_rdtscp) && guest_msr_ro(vmx, MSR_TSC_AUX))) | ||||
panic("vmx_vminit: error setting guest msr access"); | panic("vmx_init: error setting guest msr access"); | ||||
vpid_alloc(vpid, VM_MAXCPU); | vpid_alloc(vpid, VM_MAXCPU); | ||||
if (virtual_interrupt_delivery) { | if (virtual_interrupt_delivery) { | ||||
error = vm_map_mmio(vm, DEFAULT_APIC_BASE, PAGE_SIZE, | error = vm_map_mmio(vm, DEFAULT_APIC_BASE, PAGE_SIZE, | ||||
APIC_ACCESS_ADDRESS); | APIC_ACCESS_ADDRESS); | ||||
/* XXX this should really return an error to the caller */ | /* XXX this should really return an error to the caller */ | ||||
KASSERT(error == 0, ("vm_map_mmio(apicbase) error %d", error)); | KASSERT(error == 0, ("vm_map_mmio(apicbase) error %d", error)); | ||||
} | } | ||||
maxcpus = vm_get_maxcpus(vm); | maxcpus = vm_get_maxcpus(vm); | ||||
for (i = 0; i < maxcpus; i++) { | for (i = 0; i < maxcpus; i++) { | ||||
vmcs = &vmx->vmcs[i]; | vmcs = &vmx->vmcs[i]; | ||||
vmcs->identifier = vmx_revision(); | vmcs->identifier = vmx_revision(); | ||||
error = vmclear(vmcs); | error = vmclear(vmcs); | ||||
if (error != 0) { | if (error != 0) { | ||||
panic("vmx_vminit: vmclear error %d on vcpu %d\n", | panic("vmx_init: vmclear error %d on vcpu %d\n", | ||||
error, i); | error, i); | ||||
} | } | ||||
vmx_msr_guest_init(vmx, i); | vmx_msr_guest_init(vmx, i); | ||||
error = vmcs_init(vmcs); | error = vmcs_init(vmcs); | ||||
KASSERT(error == 0, ("vmcs_init error %d", error)); | KASSERT(error == 0, ("vmcs_init error %d", error)); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (virtual_interrupt_delivery) { | ||||
error += vmwrite(VMCS_EOI_EXIT3, 0); | error += vmwrite(VMCS_EOI_EXIT3, 0); | ||||
} | } | ||||
if (posted_interrupts) { | if (posted_interrupts) { | ||||
error += vmwrite(VMCS_PIR_VECTOR, pirvec); | error += vmwrite(VMCS_PIR_VECTOR, pirvec); | ||||
error += vmwrite(VMCS_PIR_DESC, | error += vmwrite(VMCS_PIR_DESC, | ||||
vtophys(&vmx->pir_desc[i])); | vtophys(&vmx->pir_desc[i])); | ||||
} | } | ||||
VMCLEAR(vmcs); | VMCLEAR(vmcs); | ||||
KASSERT(error == 0, ("vmx_vminit: error customizing the vmcs")); | KASSERT(error == 0, ("vmx_init: error customizing the vmcs")); | ||||
vmx->cap[i].set = 0; | vmx->cap[i].set = 0; | ||||
vmx->cap[i].set |= cap_rdpid != 0 ? 1 << VM_CAP_RDPID : 0; | vmx->cap[i].set |= cap_rdpid != 0 ? 1 << VM_CAP_RDPID : 0; | ||||
vmx->cap[i].set |= cap_rdtscp != 0 ? 1 << VM_CAP_RDTSCP : 0; | vmx->cap[i].set |= cap_rdtscp != 0 ? 1 << VM_CAP_RDTSCP : 0; | ||||
vmx->cap[i].proc_ctls = procbased_ctls; | vmx->cap[i].proc_ctls = procbased_ctls; | ||||
vmx->cap[i].proc_ctls2 = procbased_ctls2; | vmx->cap[i].proc_ctls2 = procbased_ctls2; | ||||
vmx->cap[i].exc_bitmap = exc_bitmap; | vmx->cap[i].exc_bitmap = exc_bitmap; | ||||
▲ Show 20 Lines • Show All 1,826 Lines • ▼ Show 20 Lines | vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap, | ||||
VMPTRLD(vmcs); | VMPTRLD(vmcs); | ||||
/* | /* | ||||
* XXX | * XXX | ||||
* We do this every time because we may setup the virtual machine | * We do this every time because we may setup the virtual machine | ||||
* from a different process than the one that actually runs it. | * from a different process than the one that actually runs it. | ||||
* | * | ||||
* If the life of a virtual machine was spent entirely in the context | * If the life of a virtual machine was spent entirely in the context | ||||
* of a single process we could do this once in vmx_vminit(). | * of a single process we could do this once in vmx_init(). | ||||
*/ | */ | ||||
vmcs_write(VMCS_HOST_CR3, rcr3()); | vmcs_write(VMCS_HOST_CR3, rcr3()); | ||||
vmcs_write(VMCS_GUEST_RIP, rip); | vmcs_write(VMCS_GUEST_RIP, rip); | ||||
vmx_set_pcpu_defaults(vmx, vcpu, pmap); | vmx_set_pcpu_defaults(vmx, vcpu, pmap); | ||||
do { | do { | ||||
KASSERT(vmcs_guest_rip() == rip, ("%s: vmcs guest rip mismatch " | KASSERT(vmcs_guest_rip() == rip, ("%s: vmcs guest rip mismatch " | ||||
"%#lx/%#lx", __func__, vmcs_guest_rip(), rip)); | "%#lx/%#lx", __func__, vmcs_guest_rip(), rip)); | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap, | ||||
VMCLEAR(vmcs); | VMCLEAR(vmcs); | ||||
vmx_msr_guest_exit(vmx, vcpu); | vmx_msr_guest_exit(vmx, vcpu); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
vmx_vmcleanup(void *arg) | vmx_cleanup(void *arg) | ||||
{ | { | ||||
int i; | int i; | ||||
struct vmx *vmx = arg; | struct vmx *vmx = arg; | ||||
uint16_t maxcpus; | uint16_t maxcpus; | ||||
if (apic_access_virtualization(vmx, 0)) | if (apic_access_virtualization(vmx, 0)) | ||||
vm_unmap_mmio(vmx->vm, DEFAULT_APIC_BASE, PAGE_SIZE); | vm_unmap_mmio(vmx->vm, DEFAULT_APIC_BASE, PAGE_SIZE); | ||||
▲ Show 20 Lines • Show All 353 Lines • ▼ Show 20 Lines | case VM_CAP_PAUSE_EXIT: | ||||
} | } | ||||
break; | break; | ||||
case VM_CAP_RDPID: | case VM_CAP_RDPID: | ||||
case VM_CAP_RDTSCP: | case VM_CAP_RDTSCP: | ||||
if (cap_rdpid || cap_rdtscp) | if (cap_rdpid || cap_rdtscp) | ||||
/* | /* | ||||
* Choose not to support enabling/disabling | * Choose not to support enabling/disabling | ||||
* RDPID/RDTSCP via libvmmapi since, as per the | * RDPID/RDTSCP via libvmmapi since, as per the | ||||
* discussion in vmx_init(), RDPID/RDTSCP are | * discussion in vmx_modinit(), RDPID/RDTSCP are | ||||
* either always enabled or always disabled. | * either always enabled or always disabled. | ||||
*/ | */ | ||||
error = EOPNOTSUPP; | error = EOPNOTSUPP; | ||||
break; | break; | ||||
case VM_CAP_UNRESTRICTED_GUEST: | case VM_CAP_UNRESTRICTED_GUEST: | ||||
if (cap_unrestricted_guest) { | if (cap_unrestricted_guest) { | ||||
retval = 0; | retval = 0; | ||||
pptr = &vmx->cap[vcpu].proc_ctls2; | pptr = &vmx->cap[vcpu].proc_ctls2; | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | if (val) { | ||||
vmx->cap[vcpu].set |= (1 << type); | vmx->cap[vcpu].set |= (1 << type); | ||||
} else { | } else { | ||||
vmx->cap[vcpu].set &= ~(1 << type); | vmx->cap[vcpu].set &= ~(1 << type); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct vmspace * | |||||
vmx_vmspace_alloc(vm_offset_t min, vm_offset_t max) | |||||
{ | |||||
return (ept_vmspace_alloc(min, max)); | |||||
} | |||||
static void | |||||
vmx_vmspace_free(struct vmspace *vmspace) | |||||
{ | |||||
ept_vmspace_free(vmspace); | |||||
} | |||||
struct vlapic_vtx { | struct vlapic_vtx { | ||||
struct vlapic vlapic; | struct vlapic vlapic; | ||||
struct pir_desc *pir_desc; | struct pir_desc *pir_desc; | ||||
struct vmx *vmx; | struct vmx *vmx; | ||||
u_int pending_prio; | u_int pending_prio; | ||||
}; | }; | ||||
#define VPR_PRIO_BIT(vpr) (1 << ((vpr) >> 4)) | #define VPR_PRIO_BIT(vpr) (1 << ((vpr) >> 4)) | ||||
▲ Show 20 Lines • Show All 399 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
vlapic_cleanup(vlapic); | vlapic_cleanup(vlapic); | ||||
free(vlapic, M_VLAPIC); | free(vlapic, M_VLAPIC); | ||||
} | } | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
static int | static int | ||||
vmx_snapshot_vmi(void *arg, struct vm_snapshot_meta *meta) | vmx_snapshot(void *arg, struct vm_snapshot_meta *meta) | ||||
{ | { | ||||
struct vmx *vmx; | struct vmx *vmx; | ||||
struct vmxctx *vmxctx; | struct vmxctx *vmxctx; | ||||
int i; | int i; | ||||
int ret; | int ret; | ||||
vmx = arg; | vmx = arg; | ||||
Show All 27 Lines | for (i = 0; i < VM_MAXCPU; i++) { | ||||
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr6, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr6, meta, ret, done); | ||||
} | } | ||||
done: | done: | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
vmx_snapshot_vmcx(void *arg, struct vm_snapshot_meta *meta, int vcpu) | vmx_vmcx_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpu) | ||||
{ | { | ||||
struct vmcs *vmcs; | struct vmcs *vmcs; | ||||
struct vmx *vmx; | struct vmx *vmx; | ||||
int err, run, hostcpu; | int err, run, hostcpu; | ||||
vmx = (struct vmx *)arg; | vmx = (struct vmx *)arg; | ||||
err = 0; | err = 0; | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | vmx_restore_tsc(void *arg, int vcpu, uint64_t offset) | ||||
error = vmx_set_tsc_offset(vmx, vcpu, offset); | error = vmx_set_tsc_offset(vmx, vcpu, offset); | ||||
if (!running) | if (!running) | ||||
VMCLEAR(vmcs); | VMCLEAR(vmcs); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
struct vmm_ops vmm_ops_intel = { | const struct vmm_ops vmm_ops_intel = { | ||||
.modinit = vmx_modinit, | |||||
.modcleanup = vmx_modcleanup, | |||||
.modresume = vmx_modresume, | |||||
.init = vmx_init, | .init = vmx_init, | ||||
.run = vmx_run, | |||||
.cleanup = vmx_cleanup, | .cleanup = vmx_cleanup, | ||||
.resume = vmx_restore, | .getreg = vmx_getreg, | ||||
.vminit = vmx_vminit, | .setreg = vmx_setreg, | ||||
.vmrun = vmx_run, | .getdesc = vmx_getdesc, | ||||
.vmcleanup = vmx_vmcleanup, | .setdesc = vmx_setdesc, | ||||
markj: It's bugged me in the past that the naming is inconsistent here: vmx_run() vs. svm_vmrun(). | |||||
.vmgetreg = vmx_getreg, | .getcap = vmx_getcap, | ||||
.vmsetreg = vmx_setreg, | .setcap = vmx_setcap, | ||||
.vmgetdesc = vmx_getdesc, | .vmspace_alloc = vmx_vmspace_alloc, | ||||
.vmsetdesc = vmx_setdesc, | .vmspace_free = vmx_vmspace_free, | ||||
.vmgetcap = vmx_getcap, | |||||
.vmsetcap = vmx_setcap, | |||||
.vmspace_alloc = ept_vmspace_alloc, | |||||
.vmspace_free = ept_vmspace_free, | |||||
.vlapic_init = vmx_vlapic_init, | .vlapic_init = vmx_vlapic_init, | ||||
.vlapic_cleanup = vmx_vlapic_cleanup, | .vlapic_cleanup = vmx_vlapic_cleanup, | ||||
#ifdef BHYVE_SNAPSHOT | #ifdef BHYVE_SNAPSHOT | ||||
.vmsnapshot = vmx_snapshot_vmi, | .snapshot = vmx_snapshot, | ||||
.vmcx_snapshot = vmx_snapshot_vmcx, | .vmcx_snapshot = vmx_vmcx_snapshot, | ||||
.vm_restore_tsc = vmx_restore_tsc, | .restore_tsc = vmx_restore_tsc, | ||||
#endif | #endif | ||||
}; | }; |
It's bugged me in the past that the naming is inconsistent here: vmx_run() vs. svm_vmrun(). Since the op name is now just "run", I think vmx_run() is fine, but could you change the other VMX/SVM function names to match the corresponding op name? That makes it a bit easier to find function definitions with cscope or similar since the use of ifuncs breaks tag lookup.