ia64/xen-unstable

view xen/arch/x86/hvm/svm/intr.c @ 11696:a949bd6ceb85

[HVM][SVM] Do not delay ExtInt event injection if RFLAGS.IF==0.

AMD-V does not require the delaying of interrupt injection if the guest
IF_FLAG disallows interrupts. Remove the code in svm_intr_assist()
that was checking the guest IF in eflags.

This patch fixes the problem with HVM Windows guests, with observing a
very slow timer countdown on the initial boot menu, when there is more
than one boot option. Kbd response in this same Windows boot menu is
also acceptably responsive with this patch.

Signed-off-by: Tom Woller <thomas.woller@amd.com>=20
author kaf24@firebug.cl.cam.ac.uk
date Sat Sep 30 10:49:08 2006 +0100 (2006-09-30)
parents ef8df1e5884f
children 34b2348dfe4b
line source
1 /*
2 * intr.c: Interrupt handling for SVM.
3 * Copyright (c) 2005, AMD Inc.
4 * Copyright (c) 2004, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 */
21 #include <xen/config.h>
22 #include <xen/init.h>
23 #include <xen/mm.h>
24 #include <xen/lib.h>
25 #include <xen/trace.h>
26 #include <xen/errno.h>
27 #include <xen/shadow.h>
28 #include <asm/cpufeature.h>
29 #include <asm/processor.h>
30 #include <asm/msr.h>
31 #include <asm/hvm/hvm.h>
32 #include <asm/hvm/io.h>
33 #include <asm/hvm/support.h>
34 #include <asm/hvm/svm/svm.h>
35 #include <asm/hvm/svm/intr.h>
36 #include <xen/event.h>
37 #include <xen/kernel.h>
38 #include <public/hvm/ioreq.h>
39 #include <xen/domain_page.h>
41 /*
42 * Most of this code is copied from vmx_io.c and modified
43 * to be suitable for SVM.
44 */
46 static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
47 {
48 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
49 vintr_t intr;
51 ASSERT(vmcb);
53 /* Save all fields */
54 intr = vmcb->vintr;
55 /* Update only relevant fields */
56 intr.fields.irq = 1;
57 intr.fields.intr_masking = 1;
58 intr.fields.vector = trap;
59 intr.fields.prio = 0xF;
60 intr.fields.ign_tpr = 1;
61 vmcb->vintr = intr;
62 // printf( "IRQ = %d\n", trap );
63 return 0;
64 }
66 asmlinkage void svm_intr_assist(void)
67 {
68 struct vcpu *v = current;
69 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
70 struct hvm_domain *plat=&v->domain->arch.hvm_domain;
71 struct periodic_time *pt = &plat->pl_time.periodic_tm;
72 struct hvm_virpic *pic= &plat->vpic;
73 int callback_irq;
74 int intr_type = APIC_DM_EXTINT;
75 int intr_vector = -1;
76 int re_injecting = 0;
78 ASSERT(vmcb);
80 /* Check if an Injection is active */
81 /* Previous Interrupt delivery caused this Intercept? */
82 if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
83 v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
84 // printk("Injecting PF#: saving IRQ from ExitInfo\n");
85 vmcb->exitintinfo.bytes = 0;
86 re_injecting = 1;
87 }
89 /* Previous interrupt still pending? */
90 if (vmcb->vintr.fields.irq) {
91 // printk("Re-injecting IRQ from Vintr\n");
92 intr_vector = vmcb->vintr.fields.vector;
93 vmcb->vintr.bytes = 0;
94 re_injecting = 1;
95 }
96 /* Pending IRQ saved at last VMExit? */
97 else if ( v->arch.hvm_svm.saved_irq_vector >= 0) {
98 // printk("Re-Injecting saved IRQ\n");
99 intr_vector = v->arch.hvm_svm.saved_irq_vector;
100 v->arch.hvm_svm.saved_irq_vector = -1;
101 re_injecting = 1;
102 }
103 /* Now let's check for newer interrrupts */
104 else {
106 if ( v->vcpu_id == 0 )
107 hvm_pic_assist(v);
110 if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) {
111 pic_set_irq(pic, pt->irq, 0);
112 pic_set_irq(pic, pt->irq, 1);
113 }
115 if (v->vcpu_id == 0) {
116 callback_irq =
117 v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
118 if ( callback_irq != 0)
119 pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
120 }
122 if ( cpu_has_pending_irq(v) )
123 intr_vector = cpu_get_interrupt(v, &intr_type);
125 }
127 /* have we got an interrupt to inject? */
128 if (intr_vector >= 0) {
129 switch (intr_type) {
130 case APIC_DM_EXTINT:
131 case APIC_DM_FIXED:
132 case APIC_DM_LOWEST:
133 /* Re-injecting a PIT interruptt? */
134 if (re_injecting &&
135 is_pit_irq(v, intr_vector, intr_type)) {
136 ++pt->pending_intr_nr;
137 }
138 /* let's inject this interrupt */
139 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
140 svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
141 hvm_interrupt_post(v, intr_vector, intr_type);
142 break;
143 case APIC_DM_SMI:
144 case APIC_DM_NMI:
145 case APIC_DM_INIT:
146 case APIC_DM_STARTUP:
147 default:
148 printk("Unsupported interrupt type: %d\n", intr_type);
149 BUG();
150 break;
151 }
152 }
153 }
155 /*
156 * Local variables:
157 * mode: C
158 * c-set-style: "BSD"
159 * c-basic-offset: 4
160 * tab-width: 4
161 * indent-tabs-mode: nil
162 * End:
163 */