aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2007-09-17 15:57:50 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:46 -0500
commit7aa81cc04781b5b99a0647ec04533599d78cd219 (patch)
tree6ac8854faf3db2bc499e2c105fdfdab95df52170 /drivers/kvm/vmx.c
parentaca7f96600b170e470b3056aba0ed8d7df8d330d (diff)
KVM: Refactor hypercall infrastructure (v3)
This patch refactors the current hypercall infrastructure to better support live migration and SMP. It eliminates the hypercall page by trapping the UD exception that would occur if you used the wrong hypercall instruction for the underlying architecture and replacing it with the right one lazily. A fall-out of this patch is that the unhandled hypercalls no longer trap to userspace. There is very little reason though to use a hypercall to communicate with userspace as PIO or MMIO can be used. There is no code in tree that uses userspace hypercalls. [avi: fix #ud injection on vmx] Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 5b397b6c9f93..47c827d3007c 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -164,6 +164,13 @@ static inline int is_no_device(u32 intr_info)
164 (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK); 164 (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
165} 165}
166 166
167static inline int is_invalid_opcode(u32 intr_info)
168{
169 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
170 INTR_INFO_VALID_MASK)) ==
171 (INTR_TYPE_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
172}
173
167static inline int is_external_interrupt(u32 intr_info) 174static inline int is_external_interrupt(u32 intr_info)
168{ 175{
169 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 176 return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
@@ -315,7 +322,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
315{ 322{
316 u32 eb; 323 u32 eb;
317 324
318 eb = 1u << PF_VECTOR; 325 eb = (1u << PF_VECTOR) | (1u << UD_VECTOR);
319 if (!vcpu->fpu_active) 326 if (!vcpu->fpu_active)
320 eb |= 1u << NM_VECTOR; 327 eb |= 1u << NM_VECTOR;
321 if (vcpu->guest_debug.enabled) 328 if (vcpu->guest_debug.enabled)
@@ -560,6 +567,14 @@ static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
560 INTR_INFO_VALID_MASK); 567 INTR_INFO_VALID_MASK);
561} 568}
562 569
570static void vmx_inject_ud(struct kvm_vcpu *vcpu)
571{
572 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
573 UD_VECTOR |
574 INTR_TYPE_EXCEPTION |
575 INTR_INFO_VALID_MASK);
576}
577
563/* 578/*
564 * Swap MSR entry in host/guest MSR entry array. 579 * Swap MSR entry in host/guest MSR entry array.
565 */ 580 */
@@ -1771,6 +1786,14 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1771 return 1; 1786 return 1;
1772 } 1787 }
1773 1788
1789 if (is_invalid_opcode(intr_info)) {
1790 er = emulate_instruction(vcpu, kvm_run, 0, 0);
1791 if (er != EMULATE_DONE)
1792 vmx_inject_ud(vcpu);
1793
1794 return 1;
1795 }
1796
1774 error_code = 0; 1797 error_code = 0;
1775 rip = vmcs_readl(GUEST_RIP); 1798 rip = vmcs_readl(GUEST_RIP);
1776 if (intr_info & INTR_INFO_DELIEVER_CODE_MASK) 1799 if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
@@ -1873,7 +1896,6 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
1873 hypercall[0] = 0x0f; 1896 hypercall[0] = 0x0f;
1874 hypercall[1] = 0x01; 1897 hypercall[1] = 0x01;
1875 hypercall[2] = 0xc1; 1898 hypercall[2] = 0xc1;
1876 hypercall[3] = 0xc3;
1877} 1899}
1878 1900
1879static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1901static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -2059,7 +2081,8 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2059static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 2081static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2060{ 2082{
2061 skip_emulated_instruction(vcpu); 2083 skip_emulated_instruction(vcpu);
2062 return kvm_hypercall(vcpu, kvm_run); 2084 kvm_emulate_hypercall(vcpu);
2085 return 1;
2063} 2086}
2064 2087
2065/* 2088/*