ia64/xen-unstable

view xen/arch/x86/hvm/svm/intr.c @ 10908:a6cb8ba24a91

[HVM] Place all APIC registers into one page in native format.
With this change we can re-use code at include/asm-x86/apicdef.h,
making the code much cleaner. Also it help for future enhancement.

This patch does not change any logic except the change to
CONTROL_REG_ACCESS_NUM, which should be 0xf for CR8 access.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com
author kfraser@localhost.localdomain
date Wed Aug 02 10:07:03 2006 +0100 (2006-08-02)
parents dc5f894d6834
children 4ee64035c0a3
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 void svm_set_guest_time(struct vcpu *v, u64 gtime)
48 {
49 u64 host_tsc;
51 rdtscll(host_tsc);
53 v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
54 v->arch.hvm_svm.vmcb->tsc_offset = v->arch.hvm_vcpu.cache_tsc_offset;
55 }
57 static inline void
58 interrupt_post_injection(struct vcpu * v, int vector, int type)
59 {
60 struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
62 if ( is_pit_irq(v, vector, type) ) {
63 if ( !pt->first_injected ) {
64 pt->pending_intr_nr = 0;
65 pt->last_plt_gtime = hvm_get_guest_time(v);
66 pt->scheduled = NOW() + pt->period;
67 set_timer(&pt->timer, pt->scheduled);
68 pt->first_injected = 1;
69 } else {
70 pt->pending_intr_nr--;
71 pt->last_plt_gtime += pt->period_cycles;
72 svm_set_guest_time(v, pt->last_plt_gtime);
73 pit_time_fired(v, pt->priv);
74 }
75 }
77 switch(type)
78 {
79 case APIC_DM_EXTINT:
80 break;
82 default:
83 vlapic_post_injection(v, vector, type);
84 break;
85 }
86 }
88 static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
89 {
90 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
91 vintr_t intr;
93 ASSERT(vmcb);
95 /* Save all fields */
96 intr = vmcb->vintr;
97 /* Update only relevant fields */
98 intr.fields.irq = 1;
99 intr.fields.intr_masking = 1;
100 intr.fields.vector = trap;
101 intr.fields.prio = 0xF;
102 intr.fields.ign_tpr = 1;
103 vmcb->vintr = intr;
104 // printf( "IRQ = %d\n", trap );
105 return 0;
106 }
108 asmlinkage void svm_intr_assist(void)
109 {
110 struct vcpu *v = current;
111 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
112 struct hvm_domain *plat=&v->domain->arch.hvm_domain;
113 struct periodic_time *pt = &plat->pl_time.periodic_tm;
114 struct hvm_virpic *pic= &plat->vpic;
115 int intr_type = APIC_DM_EXTINT;
116 int intr_vector = -1;
117 int re_injecting = 0;
118 unsigned long rflags;
120 ASSERT(vmcb);
122 /* Check if an Injection is active */
123 /* Previous Interrupt delivery caused this Intercept? */
124 if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
125 v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
126 // printk("Injecting PF#: saving IRQ from ExitInfo\n");
127 vmcb->exitintinfo.bytes = 0;
128 re_injecting = 1;
129 }
131 /* Guest's interrputs masked? */
132 rflags = vmcb->rflags;
133 if (irq_masked(rflags)) {
134 HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags);
135 /* bail out, we won't be injecting an interrupt this time */
136 return;
137 }
139 /* Previous interrupt still pending? */
140 if (vmcb->vintr.fields.irq) {
141 // printk("Re-injecting IRQ from Vintr\n");
142 intr_vector = vmcb->vintr.fields.vector;
143 vmcb->vintr.bytes = 0;
144 re_injecting = 1;
145 }
146 /* Pending IRQ saved at last VMExit? */
147 else if ( v->arch.hvm_svm.saved_irq_vector >= 0) {
148 // printk("Re-Injecting saved IRQ\n");
149 intr_vector = v->arch.hvm_svm.saved_irq_vector;
150 v->arch.hvm_svm.saved_irq_vector = -1;
151 re_injecting = 1;
152 }
153 /* Now let's check for newer interrrupts */
154 else {
156 if ( v->vcpu_id == 0 )
157 hvm_pic_assist(v);
159 /* Before we deal with PIT interrupts, let's check
160 for interrupts set by the device model.
161 */
162 if ( cpu_has_pending_irq(v) ) {
163 intr_vector = cpu_get_interrupt(v, &intr_type);
164 }
165 else if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) {
166 pic_set_irq(pic, pt->irq, 0);
167 pic_set_irq(pic, pt->irq, 1);
168 intr_vector = cpu_get_interrupt(v, &intr_type);
169 }
170 }
172 /* have we got an interrupt to inject? */
173 if (intr_vector >= 0) {
174 switch (intr_type) {
175 case APIC_DM_EXTINT:
176 case APIC_DM_FIXED:
177 case APIC_DM_LOWEST:
178 /* Re-injecting a PIT interruptt? */
179 if (re_injecting &&
180 is_pit_irq(v, intr_vector, intr_type)) {
181 ++pt->pending_intr_nr;
182 }
183 /* let's inject this interrupt */
184 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
185 svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
186 interrupt_post_injection(v, intr_vector, intr_type);
187 break;
188 case APIC_DM_SMI:
189 case APIC_DM_NMI:
190 case APIC_DM_INIT:
191 case APIC_DM_STARTUP:
192 default:
193 printk("Unsupported interrupt type: %d\n", intr_type);
194 BUG();
195 break;
196 }
197 }
198 }
200 /*
201 * Local variables:
202 * mode: C
203 * c-set-style: "BSD"
204 * c-basic-offset: 4
205 * tab-width: 4
206 * indent-tabs-mode: nil
207 * End:
208 */