aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Dong <eddie.dong@intel.com>2007-08-06 09:29:07 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:26 -0400
commit2a8067f17b8442ecce0b14e134823020ff33b4fa (patch)
treee7f65775b3ced0c42de2df8118a84e7ddb9fff7d
parent96ad2cc6132479aa0aea485d0838a13fda765bd5 (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>
-rw-r--r--drivers/kvm/kvm.h2
-rw-r--r--drivers/kvm/kvm_main.c20
-rw-r--r--drivers/kvm/svm.c19
-rw-r--r--drivers/kvm/vmx.c16
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
495extern struct kvm_arch_ops *kvm_arch_ops; 497extern 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
846static 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
846static void load_host_msrs(struct kvm_vcpu *vcpu) 856static 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
1323static 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
1313static void svm_intr_assist(struct vcpu_svm *svm) 1330static 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
1788static int __init svm_init(void) 1807static 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
793static 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
793static __init int cpu_has_kvm_support(void) 807static __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
2505static int __init vmx_init(void) 2521static int __init vmx_init(void)