Page MenuHomeFreeBSD

D27375.id80000.diff
No OneTemporary

D27375.id80000.diff

Index: sys/amd64/include/vmm.h
===================================================================
--- sys/amd64/include/vmm.h
+++ sys/amd64/include/vmm.h
@@ -162,9 +162,9 @@
int *iptr; /* reqidle cookie */
};
-typedef int (*vmm_init_func_t)(int ipinum);
-typedef int (*vmm_cleanup_func_t)(void);
-typedef void (*vmm_resume_func_t)(void);
+typedef int (*vmm_modinit_func_t)(int ipinum);
+typedef int (*vmm_modcleanup_func_t)(void);
+typedef void (*vmm_modresume_func_t)(void);
typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
struct pmap *pmap, struct vm_eventinfo *info);
@@ -189,28 +189,28 @@
typedef int (*vmi_restore_tsc_t)(void *vmi, int vcpuid, uint64_t now);
struct vmm_ops {
- vmm_init_func_t init; /* module wide initialization */
- vmm_cleanup_func_t cleanup;
- vmm_resume_func_t resume;
-
- vmi_init_func_t vminit; /* vm-specific initialization */
- vmi_run_func_t vmrun;
- vmi_cleanup_func_t vmcleanup;
- vmi_get_register_t vmgetreg;
- vmi_set_register_t vmsetreg;
- vmi_get_desc_t vmgetdesc;
- vmi_set_desc_t vmsetdesc;
- vmi_get_cap_t vmgetcap;
- vmi_set_cap_t vmsetcap;
+ vmm_modinit_func_t modinit; /* module wide initialization */
+ vmm_modcleanup_func_t modcleanup;
+ vmm_modresume_func_t modresume;
+
+ vmi_init_func_t init; /* vm-specific initialization */
+ vmi_run_func_t run;
+ vmi_cleanup_func_t cleanup;
+ vmi_get_register_t getreg;
+ vmi_set_register_t setreg;
+ vmi_get_desc_t getdesc;
+ vmi_set_desc_t setdesc;
+ vmi_get_cap_t getcap;
+ vmi_set_cap_t setcap;
vmi_vmspace_alloc vmspace_alloc;
vmi_vmspace_free vmspace_free;
vmi_vlapic_init vlapic_init;
vmi_vlapic_cleanup vlapic_cleanup;
/* checkpoint operations */
- vmi_snapshot_t vmsnapshot;
+ vmi_snapshot_t snapshot;
vmi_snapshot_vmcx_t vmcx_snapshot;
- vmi_restore_tsc_t vm_restore_tsc;
+ vmi_restore_tsc_t restore_tsc;
};
extern struct vmm_ops vmm_ops_intel;
Index: sys/amd64/vmm/amd/svm.c
===================================================================
--- sys/amd64/vmm/amd/svm.c
+++ sys/amd64/vmm/amd/svm.c
@@ -2673,25 +2673,25 @@
#endif
struct vmm_ops vmm_ops_amd = {
- .init = svm_init,
- .cleanup = svm_cleanup,
- .resume = svm_restore,
- .vminit = svm_vminit,
- .vmrun = svm_vmrun,
- .vmcleanup = svm_vmcleanup,
- .vmgetreg = svm_getreg,
- .vmsetreg = svm_setreg,
- .vmgetdesc = vmcb_getdesc,
- .vmsetdesc = vmcb_setdesc,
- .vmgetcap = svm_getcap,
- .vmsetcap = svm_setcap,
+ .modinit = svm_init,
+ .modcleanup = svm_cleanup,
+ .modresume = svm_restore,
+ .init = svm_vminit,
+ .run = svm_vmrun,
+ .cleanup = svm_vmcleanup,
+ .getreg = svm_getreg,
+ .setreg = svm_setreg,
+ .getdesc = vmcb_getdesc,
+ .setdesc = vmcb_setdesc,
+ .getcap = svm_getcap,
+ .setcap = svm_setcap,
.vmspace_alloc = svm_npt_alloc,
.vmspace_free = svm_npt_free,
.vlapic_init = svm_vlapic_init,
.vlapic_cleanup = svm_vlapic_cleanup,
#ifdef BHYVE_SNAPSHOT
- .vmsnapshot = svm_snapshot_vmi,
+ .snapshot = svm_snapshot_vmi,
.vmcx_snapshot = svm_snapshot_vmcx,
- .vm_restore_tsc = svm_restore_tsc,
+ .restore_tsc = svm_restore_tsc,
#endif
};
Index: sys/amd64/vmm/intel/vmx.c
===================================================================
--- sys/amd64/vmm/intel/vmx.c
+++ sys/amd64/vmm/intel/vmx.c
@@ -4178,25 +4178,25 @@
#endif
struct vmm_ops vmm_ops_intel = {
- .init = vmx_init,
- .cleanup = vmx_cleanup,
- .resume = vmx_restore,
- .vminit = vmx_vminit,
- .vmrun = vmx_run,
- .vmcleanup = vmx_vmcleanup,
- .vmgetreg = vmx_getreg,
- .vmsetreg = vmx_setreg,
- .vmgetdesc = vmx_getdesc,
- .vmsetdesc = vmx_setdesc,
- .vmgetcap = vmx_getcap,
- .vmsetcap = vmx_setcap,
+ .modinit = vmx_init,
+ .modcleanup = vmx_cleanup,
+ .modresume = vmx_restore,
+ .init = vmx_vminit,
+ .run = vmx_run,
+ .cleanup = vmx_vmcleanup,
+ .getreg = vmx_getreg,
+ .setreg = vmx_setreg,
+ .getdesc = vmx_getdesc,
+ .setdesc = vmx_setdesc,
+ .getcap = vmx_getcap,
+ .setcap = vmx_setcap,
.vmspace_alloc = ept_vmspace_alloc,
.vmspace_free = ept_vmspace_free,
.vlapic_init = vmx_vlapic_init,
.vlapic_cleanup = vmx_vlapic_cleanup,
#ifdef BHYVE_SNAPSHOT
- .vmsnapshot = vmx_snapshot_vmi,
+ .snapshot = vmx_snapshot_vmi,
.vmcx_snapshot = vmx_snapshot_vmcx,
- .vm_restore_tsc = vmx_restore_tsc,
+ .restore_tsc = vmx_restore_tsc,
#endif
};
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -67,6 +67,7 @@
#include <machine/md_var.h>
#include <x86/psl.h>
#include <x86/apicreg.h>
+#include <x86/ifunc.h>
#include <machine/vmm.h>
#include <machine/vmm_dev.h>
@@ -184,42 +185,53 @@
static int vmm_initialized;
-static struct vmm_ops *ops;
-#define VMM_INIT(num) (ops != NULL ? (*ops->init)(num) : 0)
-#define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0)
-#define VMM_RESUME() (ops != NULL ? (*ops->resume)() : 0)
-
-#define VMINIT(vm, pmap) (ops != NULL ? (*ops->vminit)(vm, pmap): NULL)
-#define VMRUN(vmi, vcpu, rip, pmap, evinfo) \
- (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) : ENXIO)
-#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL)
-#define VMSPACE_ALLOC(min, max) \
- (ops != NULL ? (*ops->vmspace_alloc)(min, max) : NULL)
-#define VMSPACE_FREE(vmspace) \
- (ops != NULL ? (*ops->vmspace_free)(vmspace) : ENXIO)
-#define VMGETREG(vmi, vcpu, num, retval) \
- (ops != NULL ? (*ops->vmgetreg)(vmi, vcpu, num, retval) : ENXIO)
-#define VMSETREG(vmi, vcpu, num, val) \
- (ops != NULL ? (*ops->vmsetreg)(vmi, vcpu, num, val) : ENXIO)
-#define VMGETDESC(vmi, vcpu, num, desc) \
- (ops != NULL ? (*ops->vmgetdesc)(vmi, vcpu, num, desc) : ENXIO)
-#define VMSETDESC(vmi, vcpu, num, desc) \
- (ops != NULL ? (*ops->vmsetdesc)(vmi, vcpu, num, desc) : ENXIO)
-#define VMGETCAP(vmi, vcpu, num, retval) \
- (ops != NULL ? (*ops->vmgetcap)(vmi, vcpu, num, retval) : ENXIO)
-#define VMSETCAP(vmi, vcpu, num, val) \
- (ops != NULL ? (*ops->vmsetcap)(vmi, vcpu, num, val) : ENXIO)
-#define VLAPIC_INIT(vmi, vcpu) \
- (ops != NULL ? (*ops->vlapic_init)(vmi, vcpu) : NULL)
-#define VLAPIC_CLEANUP(vmi, vlapic) \
- (ops != NULL ? (*ops->vlapic_cleanup)(vmi, vlapic) : NULL)
+static void vmmops_panic(void);
+
+static void
+vmmops_panic(void)
+{
+ panic("vmm_ops func called when !vmm_is_intel() && !vmm_is_svm()");
+}
+
+#define DEFINE_VMMOPS_IFUNC(ret_type, opname, args) \
+ DEFINE_IFUNC(static, ret_type, vmmops_##opname, args) \
+ { \
+ if (vmm_is_intel()) \
+ return (vmm_ops_intel.opname); \
+ else if (vmm_is_svm()) \
+ return (vmm_ops_amd.opname); \
+ else \
+ return ((ret_type (*)args)vmmops_panic); \
+ }
+
+DEFINE_VMMOPS_IFUNC(int, modinit, (int ipinum))
+DEFINE_VMMOPS_IFUNC(int, modcleanup, (void))
+DEFINE_VMMOPS_IFUNC(void, modresume, (void))
+DEFINE_VMMOPS_IFUNC(void *, init, (struct vm *vm, struct pmap *pmap))
+DEFINE_VMMOPS_IFUNC(int, run, (void *vmi, int vcpu, register_t rip,
+ struct pmap *pmap, struct vm_eventinfo *info))
+DEFINE_VMMOPS_IFUNC(void, cleanup, (void *vmi))
+DEFINE_VMMOPS_IFUNC(int, getreg, (void *vmi, int vcpu, int num,
+ uint64_t *retval))
+DEFINE_VMMOPS_IFUNC(int, setreg, (void *vmi, int vcpu, int num,
+ uint64_t val))
+DEFINE_VMMOPS_IFUNC(int, getdesc, (void *vmi, int vcpu, int num,
+ struct seg_desc *desc))
+DEFINE_VMMOPS_IFUNC(int, setdesc, (void *vmi, int vcpu, int num,
+ struct seg_desc *desc))
+DEFINE_VMMOPS_IFUNC(int, getcap, (void *vmi, int vcpu, int num, int *retval))
+DEFINE_VMMOPS_IFUNC(int, setcap, (void *vmi, int vcpu, int num, int val))
+DEFINE_VMMOPS_IFUNC(struct vmspace *, vmspace_alloc, (vm_offset_t min,
+ vm_offset_t max))
+DEFINE_VMMOPS_IFUNC(void, vmspace_free, (struct vmspace *vmspace))
+DEFINE_VMMOPS_IFUNC(struct vlapic *, vlapic_init, (void *vmi, int vcpu))
+DEFINE_VMMOPS_IFUNC(void, vlapic_cleanup, (void *vmi, struct vlapic *vlapic))
#ifdef BHYVE_SNAPSHOT
-#define VM_SNAPSHOT_VMI(vmi, meta) \
- (ops != NULL ? (*ops->vmsnapshot)(vmi, meta) : ENXIO)
-#define VM_SNAPSHOT_VMCX(vmi, meta, vcpuid) \
- (ops != NULL ? (*ops->vmcx_snapshot)(vmi, meta, vcpuid) : ENXIO)
-#define VM_RESTORE_TSC(vmi, vcpuid, offset) \
- (ops != NULL ? (*ops->vm_restore_tsc)(vmi, vcpuid, offset) : ENXIO)
+DEFINE_VMMOPS_IFUNC(int, snapshot, (void *vmi, struct vm_snapshot_meta
+ *meta))
+DEFINE_VMMOPS_IFUNC(int, vmcx_snapshot, (void *vmi, struct vm_snapshot_meta
+ *meta, int vcpu))
+DEFINE_VMMOPS_IFUNC(int, restore_tsc, (void *vmi, int vcpuid, uint64_t now))
#endif
#define fpu_start_emulating() load_cr0(rcr0() | CR0_TS)
@@ -282,7 +294,7 @@
{
struct vcpu *vcpu = &vm->vcpu[i];
- VLAPIC_CLEANUP(vm->cookie, vcpu->vlapic);
+ vmmops_vlapic_cleanup(vm->cookie, vcpu->vlapic);
if (destroy) {
vmm_stat_free(vcpu->stats);
fpu_save_area_free(vcpu->guestfpu);
@@ -310,7 +322,7 @@
vcpu->tsc_offset = 0;
}
- vcpu->vlapic = VLAPIC_INIT(vm->cookie, vcpu_id);
+ vcpu->vlapic = vmmops_vlapic_init(vm->cookie, vcpu_id);
vm_set_x2apic_state(vm, vcpu_id, X2APIC_DISABLED);
vcpu->reqidle = 0;
vcpu->exitintinfo = 0;
@@ -342,17 +354,14 @@
return (&vcpu->exitinfo);
}
-static void
-vmm_resume(void)
-{
- VMM_RESUME();
-}
-
static int
vmm_init(void)
{
int error;
+ if (!vmm_is_hw_supported())
+ return (ENXIO);
+
vmm_host_state_init();
vmm_ipinum = lapic_ipi_alloc(pti ? &IDTVEC(justreturn1_pti) :
@@ -364,16 +373,9 @@
if (error)
return (error);
- if (vmm_is_intel())
- ops = &vmm_ops_intel;
- else if (vmm_is_svm())
- ops = &vmm_ops_amd;
- else
- return (ENXIO);
-
- vmm_resume_p = vmm_resume;
+ vmm_resume_p = vmmops_modresume;
- return (VMM_INIT(vmm_ipinum));
+ return (vmmops_modinit(vmm_ipinum));
}
static int
@@ -383,25 +385,33 @@
switch (what) {
case MOD_LOAD:
- vmmdev_init();
- error = vmm_init();
- if (error == 0)
- vmm_initialized = 1;
+ if (vmm_is_hw_supported()) {
+ vmmdev_init();
+ error = vmm_init();
+ if (error == 0)
+ vmm_initialized = 1;
+ } else {
+ error = ENXIO;
+ }
break;
case MOD_UNLOAD:
- error = vmmdev_cleanup();
- if (error == 0) {
- vmm_resume_p = NULL;
- iommu_cleanup();
- if (vmm_ipinum != IPI_AST)
- lapic_ipi_free(vmm_ipinum);
- error = VMM_CLEANUP();
- /*
- * Something bad happened - prevent new
- * VMs from being created
- */
- if (error)
- vmm_initialized = 0;
+ if (vmm_is_hw_supported()) {
+ error = vmmdev_cleanup();
+ if (error == 0) {
+ vmm_resume_p = NULL;
+ iommu_cleanup();
+ if (vmm_ipinum != IPI_AST)
+ lapic_ipi_free(vmm_ipinum);
+ error = vmmops_modcleanup();
+ /*
+ * Something bad happened - prevent new
+ * VMs from being created
+ */
+ if (error)
+ vmm_initialized = 0;
+ }
+ } else {
+ error = 0;
}
break;
default:
@@ -431,7 +441,7 @@
{
int i;
- vm->cookie = VMINIT(vm, vmspace_pmap(vm->vmspace));
+ vm->cookie = vmmops_init(vm, vmspace_pmap(vm->vmspace));
vm->iommu = NULL;
vm->vioapic = vioapic_init(vm);
vm->vhpet = vhpet_init(vm);
@@ -473,7 +483,7 @@
if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
return (EINVAL);
- vmspace = VMSPACE_ALLOC(0, VM_MAXUSER_ADDRESS);
+ vmspace = vmmops_vmspace_alloc(0, VM_MAXUSER_ADDRESS);
if (vmspace == NULL)
return (ENOMEM);
@@ -549,7 +559,7 @@
for (i = 0; i < vm->maxcpus; i++)
vcpu_cleanup(vm, i, destroy);
- VMCLEANUP(vm->cookie);
+ vmmops_cleanup(vm->cookie);
/*
* System memory is removed from the guest address space only when
@@ -569,7 +579,7 @@
for (i = 0; i < VM_MAX_MEMSEGS; i++)
vm_free_memseg(vm, i);
- VMSPACE_FREE(vm->vmspace);
+ vmmops_vmspace_free(vm->vmspace);
vm->vmspace = NULL;
}
}
@@ -1033,7 +1043,7 @@
if (reg >= VM_REG_LAST)
return (EINVAL);
- return (VMGETREG(vm->cookie, vcpu, reg, retval));
+ return (vmmops_getreg(vm->cookie, vcpu, reg, retval));
}
int
@@ -1048,7 +1058,7 @@
if (reg >= VM_REG_LAST)
return (EINVAL);
- error = VMSETREG(vm->cookie, vcpuid, reg, val);
+ error = vmmops_setreg(vm->cookie, vcpuid, reg, val);
if (error || reg != VM_REG_GUEST_RIP)
return (error);
@@ -1102,7 +1112,7 @@
if (!is_segment_register(reg) && !is_descriptor_table(reg))
return (EINVAL);
- return (VMGETDESC(vm->cookie, vcpu, reg, desc));
+ return (vmmops_getdesc(vm->cookie, vcpu, reg, desc));
}
int
@@ -1115,7 +1125,7 @@
if (!is_segment_register(reg) && !is_descriptor_table(reg))
return (EINVAL);
- return (VMSETDESC(vm->cookie, vcpu, reg, desc));
+ return (vmmops_setdesc(vm->cookie, vcpu, reg, desc));
}
static void
@@ -1333,7 +1343,7 @@
* software events that would cause this vcpu to wakeup.
*
* These interrupts/events could have happened after the
- * vcpu returned from VMRUN() and before it acquired the
+ * vcpu returned from vmmops_run() and before it acquired the
* vcpu lock above.
*/
if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle)
@@ -1730,7 +1740,7 @@
restore_guest_fpustate(vcpu);
vcpu_require_state(vm, vcpuid, VCPU_RUNNING);
- error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, &evinfo);
+ error = vmmops_run(vm->cookie, vcpuid, vcpu->nextrip, pmap, &evinfo);
vcpu_require_state(vm, vcpuid, VCPU_FROZEN);
save_guest_fpustate(vcpu);
@@ -1819,9 +1829,9 @@
} else if (state == VCPU_FROZEN) {
/*
* When a vcpu is "frozen" it is outside the critical section
- * around VMRUN() and 'nextrip' points to the next instruction.
- * Thus instruction restart is achieved by setting 'nextrip'
- * to the vcpu's %rip.
+ * around vmmops_run() and 'nextrip' points to the next
+ * instruction. Thus instruction restart is achieved by setting
+ * 'nextrip' to the vcpu's %rip.
*/
error = vm_get_register(vm, vcpuid, VM_REG_GUEST_RIP, &rip);
KASSERT(!error, ("%s: error %d getting rip", __func__, error));
@@ -2226,7 +2236,7 @@
if (type < 0 || type >= VM_CAP_MAX)
return (EINVAL);
- return (VMGETCAP(vm->cookie, vcpu, type, retval));
+ return (vmmops_getcap(vm->cookie, vcpu, type, retval));
}
int
@@ -2238,7 +2248,7 @@
if (type < 0 || type >= VM_CAP_MAX)
return (EINVAL);
- return (VMSETCAP(vm->cookie, vcpu, type, val));
+ return (vmmops_setcap(vm->cookie, vcpu, type, val));
}
struct vlapic *
@@ -2824,7 +2834,7 @@
error = 0;
for (i = 0; i < VM_MAXCPU; i++) {
- error = VM_SNAPSHOT_VMCX(vm->cookie, meta, i);
+ error = vmmops_vmcx_snapshot(vm->cookie, meta, i);
if (error != 0) {
printf("%s: failed to snapshot vmcs/vmcb data for "
"vCPU: %d; error: %d\n", __func__, i, error);
@@ -2846,7 +2856,7 @@
switch (meta->dev_req) {
case STRUCT_VMX:
- ret = VM_SNAPSHOT_VMI(vm->cookie, meta);
+ ret = vmmops_snapshot(vm->cookie, meta);
break;
case STRUCT_VMCX:
ret = vm_snapshot_vmcx(vm, meta);
@@ -2913,7 +2923,8 @@
for (i = 0; i < nitems(vm->vcpu); i++) {
vcpu = &vm->vcpu[i];
- error = VM_RESTORE_TSC(vm->cookie, i, vcpu->tsc_offset - now);
+ error = vmmops_restore_tsc(vm->cookie, i, vcpu->tsc_offset -
+ now);
if (error)
return (error);
}
Index: sys/amd64/vmm/vmm_util.h
===================================================================
--- sys/amd64/vmm/vmm_util.h
+++ sys/amd64/vmm/vmm_util.h
@@ -33,6 +33,7 @@
struct trapframe;
+bool vmm_is_hw_supported(void);
bool vmm_is_intel(void);
bool vmm_is_svm(void);
bool vmm_supports_1G_pages(void);
Index: sys/amd64/vmm/vmm_util.c
===================================================================
--- sys/amd64/vmm/vmm_util.c
+++ sys/amd64/vmm/vmm_util.c
@@ -38,6 +38,12 @@
#include "vmm_util.h"
+bool
+vmm_is_hw_supported(void)
+{
+ return (vmm_is_intel() || vmm_is_svm());
+}
+
bool
vmm_is_intel(void)
{

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 31, 8:47 AM (2 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35778076
Default Alt Text
D27375.id80000.diff (15 KB)

Event Timeline