ia64/xen-unstable

view xen/arch/x86/vmx_io.c @ 3858:5b63436f25fe

bitkeeper revision 1.1205.1.2 (421527deX3t0INFwjrOweq0E7Le7pw)

Rename fields in arch_exec_domain to be more uniform.
Promote vmx_shadow_invlpg() to shadow_invlpg().
author maf46@burn.cl.cam.ac.uk
date Thu Feb 17 23:25:18 2005 +0000 (2005-02-17)
parents 0fe3bb5ed3aa
children ad1d06d64313
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /*
3 * vmx_io.c: handling I/O, interrupts related VMX entry/exit
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 */
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>
26 #include <asm/cpufeature.h>
27 #include <asm/processor.h>
28 #include <asm/msr.h>
29 #include <asm/vmx.h>
30 #include <asm/vmx_vmcs.h>
31 #include <xen/event.h>
32 #include <public/io/ioreq.h>
33 #include <asm/vmx_platform.h>
34 #include <asm/vmx_virpit.h>
36 #ifdef CONFIG_VMX
38 extern long do_block();
40 #if defined (__i386__)
41 static void load_xen_regs(struct xen_regs *regs)
42 {
43 /*
44 * Write the guest register value into VMCS
45 */
46 __vmwrite(GUEST_SS_SELECTOR, regs->ss);
47 __vmwrite(GUEST_ESP, regs->esp);
48 __vmwrite(GUEST_EFLAGS, regs->eflags);
49 __vmwrite(GUEST_CS_SELECTOR, regs->cs);
50 __vmwrite(GUEST_EIP, regs->eip);
51 }
53 static void set_reg_value (int size, int index, int seg, struct xen_regs *regs, long value)
54 {
55 switch (size) {
56 case BYTE:
57 switch (index) {
58 case 0:
59 regs->eax &= 0xFFFFFF00;
60 regs->eax |= (value & 0xFF);
61 break;
62 case 1:
63 regs->ecx &= 0xFFFFFF00;
64 regs->ecx |= (value & 0xFF);
65 break;
66 case 2:
67 regs->edx &= 0xFFFFFF00;
68 regs->edx |= (value & 0xFF);
69 break;
70 case 3:
71 regs->ebx &= 0xFFFFFF00;
72 regs->ebx |= (value & 0xFF);
73 break;
74 case 4:
75 regs->eax &= 0xFFFF00FF;
76 regs->eax |= ((value & 0xFF) << 8);
77 break;
78 case 5:
79 regs->ecx &= 0xFFFF00FF;
80 regs->ecx |= ((value & 0xFF) << 8);
81 break;
82 case 6:
83 regs->edx &= 0xFFFF00FF;
84 regs->edx |= ((value & 0xFF) << 8);
85 break;
86 case 7:
87 regs->ebx &= 0xFFFF00FF;
88 regs->ebx |= ((value & 0xFF) << 8);
89 break;
90 default:
91 printk("size:%x, index:%x are invalid!\n", size, index);
92 break;
94 }
95 break;
96 case WORD:
97 switch (index) {
98 case 0:
99 regs->eax &= 0xFFFF0000;
100 regs->eax |= (value & 0xFFFF);
101 break;
102 case 1:
103 regs->ecx &= 0xFFFF0000;
104 regs->ecx |= (value & 0xFFFF);
105 break;
106 case 2:
107 regs->edx &= 0xFFFF0000;
108 regs->edx |= (value & 0xFFFF);
109 break;
110 case 3:
111 regs->ebx &= 0xFFFF0000;
112 regs->ebx |= (value & 0xFFFF);
113 break;
114 case 4:
115 regs->esp &= 0xFFFF0000;
116 regs->esp |= (value & 0xFFFF);
117 break;
119 case 5:
120 regs->ebp &= 0xFFFF0000;
121 regs->ebp |= (value & 0xFFFF);
122 break;
123 case 6:
124 regs->esi &= 0xFFFF0000;
125 regs->esi |= (value & 0xFFFF);
126 break;
127 case 7:
128 regs->edi &= 0xFFFF0000;
129 regs->edi |= (value & 0xFFFF);
130 break;
131 default:
132 printk("size:%x, index:%x are invalid!\n", size, index);
133 break;
134 }
135 break;
136 case LONG:
137 switch (index) {
138 case 0:
139 regs->eax = value;
140 break;
141 case 1:
142 regs->ecx = value;
143 break;
144 case 2:
145 regs->edx = value;
146 break;
147 case 3:
148 regs->ebx = value;
149 break;
150 case 4:
151 regs->esp = value;
152 break;
153 case 5:
154 regs->ebp = value;
155 break;
156 case 6:
157 regs->esi = value;
158 break;
159 case 7:
160 regs->edi = value;
161 break;
162 default:
163 printk("size:%x, index:%x are invalid!\n", size, index);
164 break;
165 }
166 break;
167 default:
168 printk("size:%x, index:%x are invalid!\n", size, index);
169 break;
170 }
171 }
172 #endif
174 void vmx_io_assist(struct exec_domain *ed)
175 {
176 vcpu_iodata_t *vio;
177 ioreq_t *p;
178 struct domain *d = ed->domain;
179 execution_context_t *ec = get_execution_context();
180 unsigned long old_eax;
181 int sign;
182 struct mi_per_cpu_info *mpci_p;
183 struct xen_regs *inst_decoder_regs;
185 mpci_p = &ed->arch.arch_vmx.vmx_platform.mpci;
186 inst_decoder_regs = mpci_p->inst_decoder_regs;
188 /* clear the pending event */
189 ed->vcpu_info->evtchn_upcall_pending = 0;
190 /* clear the pending bit for port 2 */
191 clear_bit(IOPACKET_PORT>>5, &ed->vcpu_info->evtchn_pending_sel);
192 clear_bit(IOPACKET_PORT, &d->shared_info->evtchn_pending[0]);
194 vio = (vcpu_iodata_t *) ed->arch.arch_vmx.vmx_platform.shared_page_va;
195 if (vio == 0) {
196 VMX_DBG_LOG(DBG_LEVEL_1,
197 "bad shared page: %lx", (unsigned long) vio);
198 domain_crash();
199 }
200 p = &vio->vp_ioreq;
202 if (p->state == STATE_IORESP_HOOK){
203 vmx_hooks_assist(ed);
204 }
206 /* clear IO wait VMX flag */
207 if (test_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags)) {
208 if (p->state != STATE_IORESP_READY) {
209 printk("got a false I/O reponse\n");
210 do_block();
211 } else {
212 p->state = STATE_INVALID;
213 }
214 clear_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags);
215 } else {
216 return;
217 }
219 sign = (p->df) ? -1 : 1;
220 if (p->port_mm) {
221 if (p->pdata_valid) {
222 ec->esi += sign * p->count * p->size;
223 ec->edi += sign * p->count * p->size;
224 } else {
225 if (p->dir == IOREQ_WRITE) {
226 return;
227 }
228 int size = -1, index = -1;
230 size = operand_size(ed->arch.arch_vmx.vmx_platform.mpci.mmio_target);
231 index = operand_index(ed->arch.arch_vmx.vmx_platform.mpci.mmio_target);
233 if (ed->arch.arch_vmx.vmx_platform.mpci.mmio_target & WZEROEXTEND) {
234 p->u.data = p->u.data & 0xffff;
235 }
236 set_reg_value(size, index, 0, (struct xen_regs *)ec, p->u.data);
238 }
239 load_xen_regs((struct xen_regs *)ec);
240 return;
241 }
243 if (p->dir == IOREQ_WRITE) {
244 if (p->pdata_valid) {
245 ec->esi += sign * p->count * p->size;
246 ec->ecx -= p->count;
247 }
248 return;
249 } else {
250 if (p->pdata_valid) {
251 ec->edi += sign * p->count * p->size;
252 ec->ecx -= p->count;
253 return;
254 }
255 }
257 old_eax = ec->eax;
259 switch(p->size) {
260 case 1:
261 ec->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
262 break;
263 case 2:
264 ec->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
265 break;
266 case 4:
267 ec->eax = (p->u.data & 0xffffffff);
268 break;
269 default:
270 BUG();
271 }
272 }
274 static inline int __fls(unsigned long word)
275 {
276 int bit;
278 __asm__("bsrl %1,%0"
279 :"=r" (bit)
280 :"rm" (word));
281 return word ? bit : -1;
282 }
285 /* Simple minded Local APIC priority implementation. Fix later */
286 static __inline__ int find_highest_irq(unsigned long *pintr)
287 {
288 if (pintr[7])
289 return __fls(pintr[7]) + (256-32*1);
290 if (pintr[6])
291 return __fls(pintr[6]) + (256-32*2);
292 if (pintr[5])
293 return __fls(pintr[5]) + (256-32*3);
294 if (pintr[4])
295 return __fls(pintr[4]) + (256-32*4);
296 if (pintr[3])
297 return __fls(pintr[3]) + (256-32*5);
298 if (pintr[2])
299 return __fls(pintr[2]) + (256-32*6);
300 if (pintr[1])
301 return __fls(pintr[1]) + (256-32*7);
302 return __fls(pintr[0]);
303 }
305 /*
306 * Return 0-255 for pending irq.
307 * -1 when no pending.
308 */
309 static inline int find_highest_pending_irq(struct exec_domain *d)
310 {
311 vcpu_iodata_t *vio;
313 vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
314 if (vio == 0) {
315 VMX_DBG_LOG(DBG_LEVEL_1,
316 "bad shared page: %lx", (unsigned long) vio);
317 domain_crash();
318 }
320 return find_highest_irq(&vio->vp_intr[0]);
321 }
323 static inline void clear_highest_bit(struct exec_domain *d, int vector)
324 {
325 vcpu_iodata_t *vio;
327 vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
328 if (vio == 0) {
329 VMX_DBG_LOG(DBG_LEVEL_1,
330 "bad shared page: %lx", (unsigned long) vio);
331 domain_crash();
332 }
334 clear_bit(vector, &vio->vp_intr[0]);
335 }
337 static inline int irq_masked(unsigned long eflags)
338 {
339 return ((eflags & X86_EFLAGS_IF) == 0);
340 }
342 void vmx_intr_assist(struct exec_domain *d)
343 {
344 int highest_vector = find_highest_pending_irq(d);
345 unsigned long intr_fields, eflags;
346 struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit);
348 if (highest_vector == -1)
349 return;
351 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
352 if (intr_fields & INTR_INFO_VALID_MASK) {
353 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
354 intr_fields);
355 return;
356 }
358 __vmread(GUEST_EFLAGS, &eflags);
359 if (irq_masked(eflags)) {
360 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
361 highest_vector, eflags);
362 return;
363 }
365 if (vpit->pending_intr_nr && highest_vector == vpit->vector)
366 vpit->pending_intr_nr--;
367 else
368 clear_highest_bit(d, highest_vector);
370 intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
371 __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
373 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
375 if (highest_vector == vpit->vector)
376 vpit->inject_point = NOW();
378 return;
379 }
381 void vmx_do_resume(struct exec_domain *d)
382 {
383 if ( d->arch.guest_vtable )
384 __vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
385 else
386 // we haven't switched off the 1:1 pagetable yet...
387 __vmwrite(GUEST_CR3, pagetable_val(d->arch.guest_table));
389 __vmwrite(HOST_CR3, pagetable_val(d->arch.monitor_table));
390 __vmwrite(HOST_ESP, (unsigned long)get_stack_bottom());
392 if (event_pending(d)) {
393 if (test_bit(IOPACKET_PORT, &d->domain->shared_info->evtchn_pending[0]))
394 vmx_io_assist(d);
396 else if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
397 printk("got an event while blocked on I/O\n");
398 do_block();
399 }
401 /* Assumption: device model will not inject an interrupt
402 * while an ioreq_t is pending i.e. the response and
403 * interrupt can come together. But an interrupt without
404 * a response to ioreq_t is not ok.
405 */
406 }
407 if (!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
408 vmx_intr_assist(d);
409 }
411 #endif /* CONFIG_VMX */