ia64/xen-unstable

view xen/arch/x86/hvm/vmx/io.c @ 9016:cf1c1bb9f6d2

Bring up AP of VMX domain.
1) add INIT-SIPI-SIPI IPI sequence handling code to HVM virtual lapic
code.
2) add an new interface init_ap_context to hvm_funcs, and implement the
VMX side.
3) add a hvm generic function hvm_bringup_ap, which in turn calls
init_ap_context.

Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Feb 24 17:32:58 2006 +0100 (2006-02-24)
parents b5bb9920bf48
children 00061c916dbb
line source
1 /*
2 * io.c: handling I/O, interrupts related VMX entry/exit
3 * Copyright (c) 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 */
20 #include <xen/config.h>
21 #include <xen/init.h>
22 #include <xen/mm.h>
23 #include <xen/lib.h>
24 #include <xen/errno.h>
25 #include <xen/trace.h>
26 #include <xen/event.h>
28 #include <asm/current.h>
29 #include <asm/cpufeature.h>
30 #include <asm/processor.h>
31 #include <asm/msr.h>
32 #include <asm/hvm/hvm.h>
33 #include <asm/hvm/io.h>
34 #include <asm/hvm/support.h>
35 #include <asm/hvm/vmx/vmx.h>
36 #include <asm/hvm/vmx/vmcs.h>
37 #include <asm/hvm/vpic.h>
38 #include <asm/hvm/vlapic.h>
39 #include <public/hvm/ioreq.h>
41 #define BSP_CPU(v) (!(v->vcpu_id))
43 void vmx_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit)
44 {
45 u64 drift;
47 if ( vpit->first_injected )
48 drift = vpit->period_cycles * vpit->pending_intr_nr;
49 else
50 drift = 0;
51 vpit->shift = v->arch.hvm_vmx.tsc_offset - drift;
52 __vmwrite(TSC_OFFSET, vpit->shift);
54 #if defined (__i386__)
55 __vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>> 32));
56 #endif
57 }
59 static inline void
60 interrupt_post_injection(struct vcpu * v, int vector, int type)
61 {
62 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
64 if ( is_pit_irq(v, vector, type) ) {
65 if ( !vpit->first_injected ) {
66 vpit->pending_intr_nr = 0;
67 vpit->scheduled = NOW() + vpit->period;
68 set_timer(&vpit->pit_timer, vpit->scheduled);
69 vpit->first_injected = 1;
70 } else {
71 vpit->pending_intr_nr--;
72 }
73 vpit->inject_point = NOW();
74 vmx_set_tsc_shift (v, vpit);
75 }
77 switch(type)
78 {
79 case VLAPIC_DELIV_MODE_EXT:
80 break;
82 default:
83 vlapic_post_injection(v, vector, type);
84 break;
85 }
86 }
88 static inline void
89 enable_irq_window(unsigned long cpu_exec_control)
90 {
91 if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
92 cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
93 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
94 }
95 }
97 static inline void
98 disable_irq_window(unsigned long cpu_exec_control)
99 {
100 if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
101 cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
102 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
103 }
104 }
106 asmlinkage void vmx_intr_assist(void)
107 {
108 int intr_type = 0;
109 int highest_vector;
110 unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
111 struct vcpu *v = current;
112 struct hvm_domain *plat=&v->domain->arch.hvm_domain;
113 struct hvm_virpit *vpit = &plat->vpit;
114 struct hvm_virpic *pic= &plat->vpic;
116 if ( v->vcpu_id == 0 )
117 hvm_pic_assist(v);
119 if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) {
120 pic_set_irq(pic, 0, 0);
121 pic_set_irq(pic, 0, 1);
122 }
124 __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
125 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
127 if (intr_fields & INTR_INFO_VALID_MASK) {
128 enable_irq_window(cpu_exec_control);
129 HVM_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
130 intr_fields);
131 return;
132 }
134 __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
136 if (interruptibility) {
137 enable_irq_window(cpu_exec_control);
138 HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
139 return;
140 }
142 __vmread(GUEST_RFLAGS, &eflags);
143 if (irq_masked(eflags)) {
144 enable_irq_window(cpu_exec_control);
145 return;
146 }
148 highest_vector = cpu_get_interrupt(v, &intr_type);
150 if (highest_vector == -1) {
151 disable_irq_window(cpu_exec_control);
152 return;
153 }
155 switch (intr_type) {
156 case VLAPIC_DELIV_MODE_EXT:
157 case VLAPIC_DELIV_MODE_FIXED:
158 case VLAPIC_DELIV_MODE_LPRI:
159 vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
160 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
161 break;
162 case VLAPIC_DELIV_MODE_SMI:
163 case VLAPIC_DELIV_MODE_NMI:
164 case VLAPIC_DELIV_MODE_INIT:
165 case VLAPIC_DELIV_MODE_STARTUP:
166 default:
167 printk("Unsupported interrupt type\n");
168 BUG();
169 break;
170 }
172 interrupt_post_injection(v, highest_vector, intr_type);
173 return;
174 }
176 void vmx_do_resume(struct vcpu *v)
177 {
178 struct domain *d = v->domain;
179 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
181 vmx_stts();
183 if ( test_bit(iopacket_port(v), &d->shared_info->evtchn_pending[0]) ||
184 test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
185 hvm_wait_io();
187 /* pick up the elapsed PIT ticks and re-enable pit_timer */
188 if ( vpit->first_injected )
189 pickup_deactive_ticks(vpit);
190 vmx_set_tsc_shift(v, vpit);
192 /* We can't resume the guest if we're waiting on I/O */
193 ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
194 }
196 /*
197 * Local variables:
198 * mode: C
199 * c-set-style: "BSD"
200 * c-basic-offset: 4
201 * tab-width: 4
202 * indent-tabs-mode: nil
203 * End:
204 */