diff options
author | neel <neel@FreeBSD.org> | 2014-05-22 17:22:37 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-05-22 17:22:37 +0000 |
commit | f33a3d02f096028127edfc305614e3ca6dd93d76 (patch) | |
tree | 749b05032101fa09dc1563198e9d56f399f9f007 /sys/amd64 | |
parent | e2d232a5cb39663205eba6914b85888b7a6075a6 (diff) | |
download | FreeBSD-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.c | 16 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmcs.h | 4 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 14 |
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 |