direct-io.hg

view xen/arch/x86/hvm/svm/intr.c @ 9462:48abab2ab719

SVM patch to update guest time with latest hvm modifications.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Mar 29 13:56:26 2006 +0100 (2006-03-29)
parents b7facd6aa72e
children 2a7a46dd3bd6
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 */
45 #define BSP_CPU(v) (!(v->vcpu_id))
47 u64 svm_get_guest_time(struct vcpu *v)
48 {
49 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
50 u64 host_tsc;
52 rdtscll(host_tsc);
53 return host_tsc + vpit->cache_tsc_offset;
54 }
56 void svm_set_guest_time(struct vcpu *v, u64 gtime)
57 {
58 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
59 u64 host_tsc;
61 rdtscll(host_tsc);
63 vpit->cache_tsc_offset = gtime - host_tsc;
64 v->arch.hvm_svm.vmcb->tsc_offset = vpit->cache_tsc_offset;
65 }
67 static inline void
68 interrupt_post_injection(struct vcpu * v, int vector, int type)
69 {
70 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
72 if ( is_pit_irq(v, vector, type) ) {
73 if ( !vpit->first_injected ) {
74 vpit->pending_intr_nr = 0;
75 vpit->last_pit_gtime = svm_get_guest_time(v);
76 vpit->scheduled = NOW() + vpit->period;
77 set_timer(&vpit->pit_timer, vpit->scheduled);
78 vpit->first_injected = 1;
79 } else {
80 vpit->pending_intr_nr--;
81 }
82 vpit->inject_point = NOW();
84 vpit->last_pit_gtime += vpit->period_cycles;
85 svm_set_guest_time(v, vpit->last_pit_gtime);
86 }
88 switch(type)
89 {
90 case VLAPIC_DELIV_MODE_EXT:
91 break;
93 default:
94 vlapic_post_injection(v, vector, type);
95 break;
96 }
97 }
99 static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
100 {
101 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
102 vintr_t intr;
104 ASSERT(vmcb);
106 /* Save all fields */
107 intr = vmcb->vintr;
108 /* Update only relevant fields */
109 intr.fields.irq = 1;
110 intr.fields.intr_masking = 1;
111 intr.fields.vector = trap;
112 intr.fields.prio = 0xF;
113 intr.fields.ign_tpr = 1;
114 vmcb->vintr = intr;
115 // printf( "IRQ = %d\n", trap );
116 return 0;
117 }
119 asmlinkage void svm_intr_assist(void)
120 {
121 struct vcpu *v = current;
122 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
123 struct hvm_domain *plat=&v->domain->arch.hvm_domain;
124 struct hvm_virpit *vpit = &plat->vpit;
125 struct hvm_virpic *pic= &plat->vpic;
126 int intr_type = VLAPIC_DELIV_MODE_EXT;
127 int intr_vector = -1;
128 int re_injecting = 0;
129 unsigned long rflags;
131 ASSERT(vmcb);
133 /* Check if an Injection is active */
134 if (v->arch.hvm_svm.injecting_event) {
135 /* Previous Interrupt delivery caused this Intercept? */
136 if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
137 v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
138 // printk("Injecting PF#: saving IRQ from ExitInfo\n");
139 vmcb->exitintinfo.bytes = 0;
141 /* bail out, we won't be injecting an interrupt this time */
142 return;
143 }
144 }
146 /* Guest's interrputs masked? */
147 rflags = vmcb->rflags;
148 if (irq_masked(rflags)) {
149 HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags);
150 /* bail out, we won't be injecting an interrupt this time */
151 return;
152 }
154 /* Interrupt delivery caused an Intercept? */
155 if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
156 // printk("Re-injecting IRQ from ExitInfo\n");
157 intr_vector = vmcb->exitintinfo.fields.vector;
158 vmcb->exitintinfo.bytes = 0;
159 re_injecting = 1;
160 }
161 /* Previous interrupt still pending? */
162 else if (vmcb->vintr.fields.irq) {
163 // printk("Re-injecting IRQ from Vintr\n");
164 intr_vector = vmcb->vintr.fields.vector;
165 vmcb->vintr.bytes = 0;
166 re_injecting = 1;
167 }
168 /* Pending IRQ saved at last VMExit? */
169 else if ( v->arch.hvm_svm.saved_irq_vector >= 0) {
170 // printk("Re-Injecting saved IRQ\n");
171 intr_vector = v->arch.hvm_svm.saved_irq_vector;
172 v->arch.hvm_svm.saved_irq_vector = -1;
173 re_injecting = 1;
174 }
175 /* Now let's check for newer interrrupts */
176 else {
178 if ( v->vcpu_id == 0 )
179 hvm_pic_assist(v);
181 /* Before we deal with PIT interrupts, let's check
182 for interrupts set by the device model.
183 */
184 if ( cpu_has_pending_irq(v) ) {
185 intr_vector = cpu_get_interrupt(v, &intr_type);
186 }
187 else if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) {
188 pic_set_irq(pic, 0, 0);
189 pic_set_irq(pic, 0, 1);
190 intr_vector = cpu_get_interrupt(v, &intr_type);
191 }
192 }
194 /* have we got an interrupt to inject? */
195 if (intr_vector >= 0) {
196 switch (intr_type) {
197 case VLAPIC_DELIV_MODE_EXT:
198 case VLAPIC_DELIV_MODE_FIXED:
199 case VLAPIC_DELIV_MODE_LPRI:
200 /* Re-injecting a PIT interruptt? */
201 if (re_injecting &&
202 is_pit_irq(v, intr_vector, intr_type)) {
203 ++vpit->pending_intr_nr;
204 }
205 /* let's inject this interrupt */
206 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
207 svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
208 interrupt_post_injection(v, intr_vector, intr_type);
209 break;
210 case VLAPIC_DELIV_MODE_SMI:
211 case VLAPIC_DELIV_MODE_NMI:
212 case VLAPIC_DELIV_MODE_INIT:
213 case VLAPIC_DELIV_MODE_STARTUP:
214 default:
215 printk("Unsupported interrupt type: %d\n", intr_type);
216 BUG();
217 break;
218 }
219 }
220 }
222 /*
223 * Local variables:
224 * mode: C
225 * c-set-style: "BSD"
226 * c-basic-offset: 4
227 * tab-width: 4
228 * indent-tabs-mode: nil
229 * End:
230 */