diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2007-09-17 15:57:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:46 -0500 |
commit | 7aa81cc04781b5b99a0647ec04533599d78cd219 (patch) | |
tree | 6ac8854faf3db2bc499e2c105fdfdab95df52170 /drivers/kvm/vmx.c | |
parent | aca7f96600b170e470b3056aba0ed8d7df8d330d (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.c | 29 |
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 | ||
167 | static 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 | |||
167 | static inline int is_external_interrupt(u32 intr_info) | 174 | static 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 | ||
570 | static 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 | ||
1879 | static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1901 | static 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) | |||
2059 | static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 2081 | static 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 | /* |