summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-05-22 17:22:37 +0000
committerneel <neel@FreeBSD.org>2014-05-22 17:22:37 +0000
commitf33a3d02f096028127edfc305614e3ca6dd93d76 (patch)
tree749b05032101fa09dc1563198e9d56f399f9f007 /sys/amd64
parente2d232a5cb39663205eba6914b85888b7a6075a6 (diff)
downloadFreeBSD-src-f33a3d02f096028127edfc305614e3ca6dd93d76.zip
FreeBSD-src-f33a3d02f096028127edfc305614e3ca6dd93d76.tar.gz
Allow vmx_getdesc() and vmx_setdesc() to be called for a vcpu that is in the
VCPU_RUNNING state. This will let the VMX exit handler inspect the vcpu's segment descriptors without having to exit the critical section.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/vmm/intel/vmcs.c16
-rw-r--r--sys/amd64/vmm/intel/vmcs.h4
-rw-r--r--sys/amd64/vmm/intel/vmx.c14
3 files changed, 24 insertions, 10 deletions
diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c
index 1ddefe0..cc97d95 100644
--- a/sys/amd64/vmm/intel/vmcs.c
+++ b/sys/amd64/vmm/intel/vmcs.c
@@ -231,7 +231,7 @@ vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val)
}
int
-vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+vmcs_setdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc)
{
int error;
uint32_t base, limit, access;
@@ -240,7 +240,8 @@ vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
if (error != 0)
panic("vmcs_setdesc: invalid segment register %d", seg);
- VMPTRLD(vmcs);
+ if (!running)
+ VMPTRLD(vmcs);
if ((error = vmwrite(base, desc->base)) != 0)
goto done;
@@ -252,12 +253,13 @@ vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
goto done;
}
done:
- VMCLEAR(vmcs);
+ if (!running)
+ VMCLEAR(vmcs);
return (error);
}
int
-vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+vmcs_getdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc)
{
int error;
uint32_t base, limit, access;
@@ -267,7 +269,8 @@ vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
if (error != 0)
panic("vmcs_getdesc: invalid segment register %d", seg);
- VMPTRLD(vmcs);
+ if (!running)
+ VMPTRLD(vmcs);
if ((error = vmread(base, &u64)) != 0)
goto done;
desc->base = u64;
@@ -282,7 +285,8 @@ vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
desc->access = u64;
}
done:
- VMCLEAR(vmcs);
+ if (!running)
+ VMCLEAR(vmcs);
return (error);
}
diff --git a/sys/amd64/vmm/intel/vmcs.h b/sys/amd64/vmm/intel/vmcs.h
index 9cde999..657d5b0 100644
--- a/sys/amd64/vmm/intel/vmcs.h
+++ b/sys/amd64/vmm/intel/vmcs.h
@@ -49,9 +49,9 @@ int vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count);
int vmcs_init(struct vmcs *vmcs);
int vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *rv);
int vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val);
-int vmcs_getdesc(struct vmcs *vmcs, int ident,
+int vmcs_getdesc(struct vmcs *vmcs, int running, int ident,
struct seg_desc *desc);
-int vmcs_setdesc(struct vmcs *vmcs, int ident,
+int vmcs_setdesc(struct vmcs *vmcs, int running, int ident,
struct seg_desc *desc);
static __inline uint64_t
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 9f4e799..51f6615e 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -2409,17 +2409,27 @@ vmx_setreg(void *arg, int vcpu, int reg, uint64_t val)
static int
vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
{
+ int hostcpu, running;
struct vmx *vmx = arg;
- return (vmcs_getdesc(&vmx->vmcs[vcpu], reg, desc));
+ running = vcpu_is_running(vmx->vm, vcpu, &hostcpu);
+ if (running && hostcpu != curcpu)
+ panic("vmx_getdesc: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ return (vmcs_getdesc(&vmx->vmcs[vcpu], running, reg, desc));
}
static int
vmx_setdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
{
+ int hostcpu, running;
struct vmx *vmx = arg;
- return (vmcs_setdesc(&vmx->vmcs[vcpu], reg, desc));
+ running = vcpu_is_running(vmx->vm, vcpu, &hostcpu);
+ if (running && hostcpu != curcpu)
+ panic("vmx_setdesc: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ return (vmcs_setdesc(&vmx->vmcs[vcpu], running, reg, desc));
}
static int
OpenPOWER on IntegriCloud