diff options
| author | Eddie Dong <eddie.dong@intel.com> | 2007-08-06 09:29:07 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:26 -0400 |
| commit | 2a8067f17b8442ecce0b14e134823020ff33b4fa (patch) | |
| tree | e7f65775b3ced0c42de2df8118a84e7ddb9fff7d /drivers/kvm | |
| parent | 96ad2cc6132479aa0aea485d0838a13fda765bd5 (diff) | |
KVM: pending irq save/restore
Add in kernel irqchip save/restore support for pending vectors.
[avi: fix compile warning on i386]
[avi: remove printk]
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
Signed-off-by: Qing He <qing.he@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm')
| -rw-r--r-- | drivers/kvm/kvm.h | 2 | ||||
| -rw-r--r-- | drivers/kvm/kvm_main.c | 20 | ||||
| -rw-r--r-- | drivers/kvm/svm.c | 19 | ||||
| -rw-r--r-- | drivers/kvm/vmx.c | 16 |
4 files changed, 54 insertions, 3 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index bb506b71797d..f8fe87d3ddbd 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
| @@ -490,6 +490,8 @@ struct kvm_arch_ops { | |||
| 490 | void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); | 490 | void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); |
| 491 | void (*patch_hypercall)(struct kvm_vcpu *vcpu, | 491 | void (*patch_hypercall)(struct kvm_vcpu *vcpu, |
| 492 | unsigned char *hypercall_addr); | 492 | unsigned char *hypercall_addr); |
| 493 | int (*get_irq)(struct kvm_vcpu *vcpu); | ||
| 494 | void (*set_irq)(struct kvm_vcpu *vcpu, int vec); | ||
| 493 | }; | 495 | }; |
| 494 | 496 | ||
| 495 | extern struct kvm_arch_ops *kvm_arch_ops; | 497 | extern struct kvm_arch_ops *kvm_arch_ops; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a012d70d9eff..d56964a6eb80 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
| @@ -2126,6 +2126,7 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
| 2126 | struct kvm_sregs *sregs) | 2126 | struct kvm_sregs *sregs) |
| 2127 | { | 2127 | { |
| 2128 | struct descriptor_table dt; | 2128 | struct descriptor_table dt; |
| 2129 | int pending_vec; | ||
| 2129 | 2130 | ||
| 2130 | vcpu_load(vcpu); | 2131 | vcpu_load(vcpu); |
| 2131 | 2132 | ||
| @@ -2155,10 +2156,13 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
| 2155 | sregs->efer = vcpu->shadow_efer; | 2156 | sregs->efer = vcpu->shadow_efer; |
| 2156 | sregs->apic_base = kvm_get_apic_base(vcpu); | 2157 | sregs->apic_base = kvm_get_apic_base(vcpu); |
| 2157 | 2158 | ||
| 2158 | if (irqchip_in_kernel(vcpu->kvm)) | 2159 | if (irqchip_in_kernel(vcpu->kvm)) { |
| 2159 | memset(sregs->interrupt_bitmap, 0, | 2160 | memset(sregs->interrupt_bitmap, 0, |
| 2160 | sizeof sregs->interrupt_bitmap); | 2161 | sizeof sregs->interrupt_bitmap); |
| 2161 | else | 2162 | pending_vec = kvm_arch_ops->get_irq(vcpu); |
| 2163 | if (pending_vec >= 0) | ||
| 2164 | set_bit(pending_vec, (unsigned long *)sregs->interrupt_bitmap); | ||
| 2165 | } else | ||
| 2162 | memcpy(sregs->interrupt_bitmap, vcpu->irq_pending, | 2166 | memcpy(sregs->interrupt_bitmap, vcpu->irq_pending, |
| 2163 | sizeof sregs->interrupt_bitmap); | 2167 | sizeof sregs->interrupt_bitmap); |
| 2164 | 2168 | ||
| @@ -2177,7 +2181,7 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
| 2177 | struct kvm_sregs *sregs) | 2181 | struct kvm_sregs *sregs) |
| 2178 | { | 2182 | { |
| 2179 | int mmu_reset_needed = 0; | 2183 | int mmu_reset_needed = 0; |
| 2180 | int i; | 2184 | int i, pending_vec, max_bits; |
| 2181 | struct descriptor_table dt; | 2185 | struct descriptor_table dt; |
| 2182 | 2186 | ||
| 2183 | vcpu_load(vcpu); | 2187 | vcpu_load(vcpu); |
| @@ -2221,6 +2225,16 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
| 2221 | for (i = 0; i < ARRAY_SIZE(vcpu->irq_pending); ++i) | 2225 | for (i = 0; i < ARRAY_SIZE(vcpu->irq_pending); ++i) |
| 2222 | if (vcpu->irq_pending[i]) | 2226 | if (vcpu->irq_pending[i]) |
| 2223 | __set_bit(i, &vcpu->irq_summary); | 2227 | __set_bit(i, &vcpu->irq_summary); |
| 2228 | } else { | ||
| 2229 | max_bits = (sizeof sregs->interrupt_bitmap) << 3; | ||
| 2230 | pending_vec = find_first_bit( | ||
| 2231 | (const unsigned long *)sregs->interrupt_bitmap, | ||
| 2232 | max_bits); | ||
| 2233 | /* Only pending external irq is handled here */ | ||
| 2234 | if (pending_vec < max_bits) { | ||
| 2235 | kvm_arch_ops->set_irq(vcpu, pending_vec); | ||
| 2236 | printk("Set back pending irq %d\n", pending_vec); | ||
| 2237 | } | ||
| 2224 | } | 2238 | } |
| 2225 | 2239 | ||
| 2226 | set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); | 2240 | set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index a347b61644cd..c8cd242f36ff 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
| @@ -843,6 +843,16 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | |||
| 843 | return -EOPNOTSUPP; | 843 | return -EOPNOTSUPP; |
| 844 | } | 844 | } |
| 845 | 845 | ||
| 846 | static int svm_get_irq(struct kvm_vcpu *vcpu) | ||
| 847 | { | ||
| 848 | struct vcpu_svm *svm = to_svm(vcpu); | ||
| 849 | u32 exit_int_info = svm->vmcb->control.exit_int_info; | ||
| 850 | |||
| 851 | if (is_external_interrupt(exit_int_info)) | ||
| 852 | return exit_int_info & SVM_EVTINJ_VEC_MASK; | ||
| 853 | return -1; | ||
| 854 | } | ||
| 855 | |||
| 846 | static void load_host_msrs(struct kvm_vcpu *vcpu) | 856 | static void load_host_msrs(struct kvm_vcpu *vcpu) |
| 847 | { | 857 | { |
| 848 | #ifdef CONFIG_X86_64 | 858 | #ifdef CONFIG_X86_64 |
| @@ -1310,6 +1320,13 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq) | |||
| 1310 | ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); | 1320 | ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); |
| 1311 | } | 1321 | } |
| 1312 | 1322 | ||
| 1323 | static void svm_set_irq(struct kvm_vcpu *vcpu, int irq) | ||
| 1324 | { | ||
| 1325 | struct vcpu_svm *svm = to_svm(vcpu); | ||
| 1326 | |||
| 1327 | svm_inject_irq(svm, irq); | ||
| 1328 | } | ||
| 1329 | |||
| 1313 | static void svm_intr_assist(struct vcpu_svm *svm) | 1330 | static void svm_intr_assist(struct vcpu_svm *svm) |
| 1314 | { | 1331 | { |
| 1315 | struct vmcb *vmcb = svm->vmcb; | 1332 | struct vmcb *vmcb = svm->vmcb; |
| @@ -1783,6 +1800,8 @@ static struct kvm_arch_ops svm_arch_ops = { | |||
| 1783 | .run = svm_vcpu_run, | 1800 | .run = svm_vcpu_run, |
| 1784 | .skip_emulated_instruction = skip_emulated_instruction, | 1801 | .skip_emulated_instruction = skip_emulated_instruction, |
| 1785 | .patch_hypercall = svm_patch_hypercall, | 1802 | .patch_hypercall = svm_patch_hypercall, |
| 1803 | .get_irq = svm_get_irq, | ||
| 1804 | .set_irq = svm_set_irq, | ||
| 1786 | }; | 1805 | }; |
| 1787 | 1806 | ||
| 1788 | static int __init svm_init(void) | 1807 | static int __init svm_init(void) |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 7ec8cf84e6ea..6c371ea21046 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
| @@ -790,6 +790,20 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | |||
| 790 | return 0; | 790 | return 0; |
| 791 | } | 791 | } |
| 792 | 792 | ||
| 793 | static int vmx_get_irq(struct kvm_vcpu *vcpu) | ||
| 794 | { | ||
| 795 | u32 idtv_info_field; | ||
| 796 | |||
| 797 | idtv_info_field = vmcs_read32(IDT_VECTORING_INFO_FIELD); | ||
| 798 | if (idtv_info_field & INTR_INFO_VALID_MASK) { | ||
| 799 | if (is_external_interrupt(idtv_info_field)) | ||
| 800 | return idtv_info_field & VECTORING_INFO_VECTOR_MASK; | ||
| 801 | else | ||
| 802 | printk("pending exception: not handled yet\n"); | ||
| 803 | } | ||
| 804 | return -1; | ||
| 805 | } | ||
| 806 | |||
| 793 | static __init int cpu_has_kvm_support(void) | 807 | static __init int cpu_has_kvm_support(void) |
| 794 | { | 808 | { |
| 795 | unsigned long ecx = cpuid_ecx(1); | 809 | unsigned long ecx = cpuid_ecx(1); |
| @@ -2500,6 +2514,8 @@ static struct kvm_arch_ops vmx_arch_ops = { | |||
| 2500 | .run = vmx_vcpu_run, | 2514 | .run = vmx_vcpu_run, |
| 2501 | .skip_emulated_instruction = skip_emulated_instruction, | 2515 | .skip_emulated_instruction = skip_emulated_instruction, |
| 2502 | .patch_hypercall = vmx_patch_hypercall, | 2516 | .patch_hypercall = vmx_patch_hypercall, |
| 2517 | .get_irq = vmx_get_irq, | ||
| 2518 | .set_irq = vmx_inject_irq, | ||
| 2503 | }; | 2519 | }; |
| 2504 | 2520 | ||
| 2505 | static int __init vmx_init(void) | 2521 | static int __init vmx_init(void) |
