ia64/xen-unstable

view xen/arch/x86/vmx_io.c @ 6747:21cbdb20ff4c

An FC4/i386 install inside VMX on an x86_64 system fails because byte
size is not handled by __set_reg_value. This patch adds that support.

This patch also reindents Chengyuan Li cmpb patch so that is aligns
with the rest of the code in that block.

Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun Sep 11 09:28:21 2005 +0000 (2005-09-11)
parents 8fc210e6a588
children 4508c22dc458
line source
1 /*
2 * vmx_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 */
19 #include <xen/config.h>
20 #include <xen/init.h>
21 #include <xen/mm.h>
22 #include <xen/lib.h>
23 #include <xen/errno.h>
24 #include <xen/trace.h>
25 #include <xen/event.h>
27 #include <asm/current.h>
28 #include <asm/cpufeature.h>
29 #include <asm/processor.h>
30 #include <asm/msr.h>
31 #include <asm/vmx.h>
32 #include <asm/vmx_vmcs.h>
33 #include <asm/vmx_platform.h>
34 #include <asm/vmx_virpit.h>
35 #include <asm/apic.h>
36 #include <asm/shadow.h>
38 #include <public/io/ioreq.h>
39 #include <public/io/vmx_vlapic.h>
41 #ifdef CONFIG_VMX
42 #if defined (__i386__)
43 void load_cpu_user_regs(struct cpu_user_regs *regs)
44 {
45 /*
46 * Write the guest register value into VMCS
47 */
48 __vmwrite(GUEST_SS_SELECTOR, regs->ss);
49 __vmwrite(GUEST_RSP, regs->esp);
51 __vmwrite(GUEST_RFLAGS, regs->eflags);
52 if (regs->eflags & EF_TF)
53 __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
54 else
55 __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
57 __vmwrite(GUEST_CS_SELECTOR, regs->cs);
58 __vmwrite(GUEST_RIP, regs->eip);
59 }
61 static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
62 {
63 switch (size) {
64 case BYTE:
65 switch (index) {
66 case 0:
67 regs->eax &= 0xFFFFFF00;
68 regs->eax |= (value & 0xFF);
69 break;
70 case 1:
71 regs->ecx &= 0xFFFFFF00;
72 regs->ecx |= (value & 0xFF);
73 break;
74 case 2:
75 regs->edx &= 0xFFFFFF00;
76 regs->edx |= (value & 0xFF);
77 break;
78 case 3:
79 regs->ebx &= 0xFFFFFF00;
80 regs->ebx |= (value & 0xFF);
81 break;
82 case 4:
83 regs->eax &= 0xFFFF00FF;
84 regs->eax |= ((value & 0xFF) << 8);
85 break;
86 case 5:
87 regs->ecx &= 0xFFFF00FF;
88 regs->ecx |= ((value & 0xFF) << 8);
89 break;
90 case 6:
91 regs->edx &= 0xFFFF00FF;
92 regs->edx |= ((value & 0xFF) << 8);
93 break;
94 case 7:
95 regs->ebx &= 0xFFFF00FF;
96 regs->ebx |= ((value & 0xFF) << 8);
97 break;
98 default:
99 printk("Error: size:%x, index:%x are invalid!\n", size, index);
100 domain_crash_synchronous();
101 break;
102 }
103 break;
104 case WORD:
105 switch (index) {
106 case 0:
107 regs->eax &= 0xFFFF0000;
108 regs->eax |= (value & 0xFFFF);
109 break;
110 case 1:
111 regs->ecx &= 0xFFFF0000;
112 regs->ecx |= (value & 0xFFFF);
113 break;
114 case 2:
115 regs->edx &= 0xFFFF0000;
116 regs->edx |= (value & 0xFFFF);
117 break;
118 case 3:
119 regs->ebx &= 0xFFFF0000;
120 regs->ebx |= (value & 0xFFFF);
121 break;
122 case 4:
123 regs->esp &= 0xFFFF0000;
124 regs->esp |= (value & 0xFFFF);
125 break;
126 case 5:
127 regs->ebp &= 0xFFFF0000;
128 regs->ebp |= (value & 0xFFFF);
129 break;
130 case 6:
131 regs->esi &= 0xFFFF0000;
132 regs->esi |= (value & 0xFFFF);
133 break;
134 case 7:
135 regs->edi &= 0xFFFF0000;
136 regs->edi |= (value & 0xFFFF);
137 break;
138 default:
139 printk("Error: size:%x, index:%x are invalid!\n", size, index);
140 domain_crash_synchronous();
141 break;
142 }
143 break;
144 case LONG:
145 switch (index) {
146 case 0:
147 regs->eax = value;
148 break;
149 case 1:
150 regs->ecx = value;
151 break;
152 case 2:
153 regs->edx = value;
154 break;
155 case 3:
156 regs->ebx = value;
157 break;
158 case 4:
159 regs->esp = value;
160 break;
161 case 5:
162 regs->ebp = value;
163 break;
164 case 6:
165 regs->esi = value;
166 break;
167 case 7:
168 regs->edi = value;
169 break;
170 default:
171 printk("Error: size:%x, index:%x are invalid!\n", size, index);
172 domain_crash_synchronous();
173 break;
174 }
175 break;
176 default:
177 printk("Error: size:%x, index:%x are invalid!\n", size, index);
178 domain_crash_synchronous();
179 break;
180 }
181 }
182 #else
183 void load_cpu_user_regs(struct cpu_user_regs *regs)
184 {
185 __vmwrite(GUEST_SS_SELECTOR, regs->ss);
186 __vmwrite(GUEST_RSP, regs->rsp);
188 __vmwrite(GUEST_RFLAGS, regs->rflags);
189 if (regs->rflags & EF_TF)
190 __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
191 else
192 __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
194 __vmwrite(GUEST_CS_SELECTOR, regs->cs);
195 __vmwrite(GUEST_RIP, regs->rip);
196 }
198 static inline void __set_reg_value(unsigned long *reg, int size, long value)
199 {
200 switch (size) {
201 case BYTE:
202 case BYTE_64:
203 *reg &= ~0xFF;
204 *reg |= (value & 0xFF);
205 break;
206 case WORD:
207 *reg &= ~0xFFFF;
208 *reg |= (value & 0xFFFF);
209 break;
210 case LONG:
211 *reg &= ~0xFFFFFFFF;
212 *reg |= (value & 0xFFFFFFFF);
213 break;
214 case QUAD:
215 *reg = value;
216 break;
217 default:
218 printk("Error: <__set_reg_value>: size:%x is invalid\n", size);
219 domain_crash_synchronous();
220 }
221 }
223 static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
224 {
225 if (size == BYTE) {
226 switch (index) {
227 case 0:
228 regs->rax &= ~0xFF;
229 regs->rax |= (value & 0xFF);
230 break;
231 case 1:
232 regs->rcx &= ~0xFF;
233 regs->rcx |= (value & 0xFF);
234 break;
235 case 2:
236 regs->rdx &= ~0xFF;
237 regs->rdx |= (value & 0xFF);
238 break;
239 case 3:
240 regs->rbx &= ~0xFF;
241 regs->rbx |= (value & 0xFF);
242 break;
243 case 4:
244 regs->rax &= 0xFFFFFFFFFFFF00FF;
245 regs->rax |= ((value & 0xFF) << 8);
246 break;
247 case 5:
248 regs->rcx &= 0xFFFFFFFFFFFF00FF;
249 regs->rcx |= ((value & 0xFF) << 8);
250 break;
251 case 6:
252 regs->rdx &= 0xFFFFFFFFFFFF00FF;
253 regs->rdx |= ((value & 0xFF) << 8);
254 break;
255 case 7:
256 regs->rbx &= 0xFFFFFFFFFFFF00FF;
257 regs->rbx |= ((value & 0xFF) << 8);
258 break;
259 default:
260 printk("Error: size:%x, index:%x are invalid!\n", size, index);
261 domain_crash_synchronous();
262 break;
263 }
264 return;
265 }
267 switch (index) {
268 case 0:
269 __set_reg_value(&regs->rax, size, value);
270 break;
271 case 1:
272 __set_reg_value(&regs->rcx, size, value);
273 break;
274 case 2:
275 __set_reg_value(&regs->rdx, size, value);
276 break;
277 case 3:
278 __set_reg_value(&regs->rbx, size, value);
279 break;
280 case 4:
281 __set_reg_value(&regs->rsp, size, value);
282 break;
283 case 5:
284 __set_reg_value(&regs->rbp, size, value);
285 break;
286 case 6:
287 __set_reg_value(&regs->rsi, size, value);
288 break;
289 case 7:
290 __set_reg_value(&regs->rdi, size, value);
291 break;
292 case 8:
293 __set_reg_value(&regs->r8, size, value);
294 break;
295 case 9:
296 __set_reg_value(&regs->r9, size, value);
297 break;
298 case 10:
299 __set_reg_value(&regs->r10, size, value);
300 break;
301 case 11:
302 __set_reg_value(&regs->r11, size, value);
303 break;
304 case 12:
305 __set_reg_value(&regs->r12, size, value);
306 break;
307 case 13:
308 __set_reg_value(&regs->r13, size, value);
309 break;
310 case 14:
311 __set_reg_value(&regs->r14, size, value);
312 break;
313 case 15:
314 __set_reg_value(&regs->r15, size, value);
315 break;
316 default:
317 printk("Error: <set_reg_value> Invalid index\n");
318 domain_crash_synchronous();
319 }
320 return;
321 }
322 #endif
324 extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
326 static inline void set_eflags_CF(int size, unsigned long v1,
327 unsigned long v2, struct cpu_user_regs *regs)
328 {
329 unsigned long mask = (1 << (8 * size)) - 1;
331 if ((v1 & mask) > (v2 & mask))
332 regs->eflags |= X86_EFLAGS_CF;
333 else
334 regs->eflags &= ~X86_EFLAGS_CF;
335 }
337 static inline void set_eflags_OF(int size, unsigned long v1,
338 unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
339 {
340 if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1)))
341 regs->eflags |= X86_EFLAGS_OF;
342 }
344 static inline void set_eflags_AF(int size, unsigned long v1,
345 unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
346 {
347 if ((v1 ^ v2 ^ v3) & 0x10)
348 regs->eflags |= X86_EFLAGS_AF;
349 }
351 static inline void set_eflags_ZF(int size, unsigned long v1,
352 struct cpu_user_regs *regs)
353 {
354 unsigned long mask = (1 << (8 * size)) - 1;
356 if ((v1 & mask) == 0)
357 regs->eflags |= X86_EFLAGS_ZF;
358 }
360 static inline void set_eflags_SF(int size, unsigned long v1,
361 struct cpu_user_regs *regs)
362 {
363 if (v1 & (1 << ((8 * size) - 1)))
364 regs->eflags |= X86_EFLAGS_SF;
365 }
367 static char parity_table[256] = {
368 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
369 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
370 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
371 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
372 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
373 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
374 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
375 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
376 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
377 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
378 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
379 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
380 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
381 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
382 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
383 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
384 };
386 static inline void set_eflags_PF(int size, unsigned long v1,
387 struct cpu_user_regs *regs)
388 {
389 if (parity_table[v1 & 0xFF])
390 regs->eflags |= X86_EFLAGS_PF;
391 }
393 static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
394 struct mi_per_cpu_info *mpcip)
395 {
396 unsigned long old_eax;
397 int sign = p->df ? -1 : 1;
399 if (p->dir == IOREQ_WRITE) {
400 if (p->pdata_valid) {
401 regs->esi += sign * p->count * p->size;
402 if (mpcip->flags & REPZ)
403 regs->ecx -= p->count;
404 }
405 } else {
406 if (mpcip->flags & OVERLAP) {
407 unsigned long addr;
409 regs->edi += sign * p->count * p->size;
410 if (mpcip->flags & REPZ)
411 regs->ecx -= p->count;
413 addr = regs->edi;
414 if (sign > 0)
415 addr -= p->size;
416 vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
417 } else if (p->pdata_valid) {
418 regs->edi += sign * p->count * p->size;
419 if (mpcip->flags & REPZ)
420 regs->ecx -= p->count;
421 } else {
422 old_eax = regs->eax;
423 switch (p->size) {
424 case 1:
425 regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
426 break;
427 case 2:
428 regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
429 break;
430 case 4:
431 regs->eax = (p->u.data & 0xffffffff);
432 break;
433 default:
434 printk("Error: %s unknown port size\n", __FUNCTION__);
435 domain_crash_synchronous();
436 }
437 }
438 }
439 }
441 static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
442 struct mi_per_cpu_info *mpcip)
443 {
444 int sign = p->df ? -1 : 1;
445 int size = -1, index = -1;
446 unsigned long value = 0, diff = 0;
447 unsigned long src, dst;
449 src = mpcip->operand[0];
450 dst = mpcip->operand[1];
451 size = operand_size(src);
453 switch (mpcip->instr) {
454 case INSTR_MOV:
455 if (dst & REGISTER) {
456 index = operand_index(dst);
457 set_reg_value(size, index, 0, regs, p->u.data);
458 }
459 break;
461 case INSTR_MOVZ:
462 if (dst & REGISTER) {
463 index = operand_index(dst);
464 switch (size) {
465 case BYTE: p->u.data = p->u.data & 0xFFULL; break;
466 case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
467 case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
468 }
469 set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
470 }
471 break;
473 case INSTR_MOVS:
474 sign = p->df ? -1 : 1;
475 regs->esi += sign * p->count * p->size;
476 regs->edi += sign * p->count * p->size;
478 if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) {
479 unsigned long addr = regs->edi;
481 if (sign > 0)
482 addr -= p->size;
483 vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
484 }
486 if (mpcip->flags & REPZ)
487 regs->ecx -= p->count;
488 break;
490 case INSTR_STOS:
491 sign = p->df ? -1 : 1;
492 regs->edi += sign * p->count * p->size;
493 if (mpcip->flags & REPZ)
494 regs->ecx -= p->count;
495 break;
497 case INSTR_AND:
498 if (src & REGISTER) {
499 index = operand_index(src);
500 value = get_reg_value(size, index, 0, regs);
501 diff = (unsigned long) p->u.data & value;
502 } else if (src & IMMEDIATE) {
503 value = mpcip->immediate;
504 diff = (unsigned long) p->u.data & value;
505 } else if (src & MEMORY) {
506 index = operand_index(dst);
507 value = get_reg_value(size, index, 0, regs);
508 diff = (unsigned long) p->u.data & value;
509 set_reg_value(size, index, 0, regs, diff);
510 }
512 /*
513 * The OF and CF flags are cleared; the SF, ZF, and PF
514 * flags are set according to the result. The state of
515 * the AF flag is undefined.
516 */
517 regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
518 X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
519 set_eflags_ZF(size, diff, regs);
520 set_eflags_SF(size, diff, regs);
521 set_eflags_PF(size, diff, regs);
522 break;
524 case INSTR_OR:
525 if (src & REGISTER) {
526 index = operand_index(src);
527 value = get_reg_value(size, index, 0, regs);
528 diff = (unsigned long) p->u.data | value;
529 } else if (src & IMMEDIATE) {
530 value = mpcip->immediate;
531 diff = (unsigned long) p->u.data | value;
532 } else if (src & MEMORY) {
533 index = operand_index(dst);
534 value = get_reg_value(size, index, 0, regs);
535 diff = (unsigned long) p->u.data | value;
536 set_reg_value(size, index, 0, regs, diff);
537 }
539 /*
540 * The OF and CF flags are cleared; the SF, ZF, and PF
541 * flags are set according to the result. The state of
542 * the AF flag is undefined.
543 */
544 regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
545 X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
546 set_eflags_ZF(size, diff, regs);
547 set_eflags_SF(size, diff, regs);
548 set_eflags_PF(size, diff, regs);
549 break;
551 case INSTR_XOR:
552 if (src & REGISTER) {
553 index = operand_index(src);
554 value = get_reg_value(size, index, 0, regs);
555 diff = (unsigned long) p->u.data ^ value;
556 } else if (src & IMMEDIATE) {
557 value = mpcip->immediate;
558 diff = (unsigned long) p->u.data ^ value;
559 } else if (src & MEMORY) {
560 index = operand_index(dst);
561 value = get_reg_value(size, index, 0, regs);
562 diff = (unsigned long) p->u.data ^ value;
563 set_reg_value(size, index, 0, regs, diff);
564 }
566 /*
567 * The OF and CF flags are cleared; the SF, ZF, and PF
568 * flags are set according to the result. The state of
569 * the AF flag is undefined.
570 */
571 regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
572 X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
573 set_eflags_ZF(size, diff, regs);
574 set_eflags_SF(size, diff, regs);
575 set_eflags_PF(size, diff, regs);
576 break;
578 case INSTR_CMP:
579 if (src & REGISTER) {
580 index = operand_index(src);
581 value = get_reg_value(size, index, 0, regs);
582 diff = (unsigned long) p->u.data - value;
583 } else if (src & IMMEDIATE) {
584 value = mpcip->immediate;
585 diff = (unsigned long) p->u.data - value;
586 } else if (src & MEMORY) {
587 index = operand_index(dst);
588 value = get_reg_value(size, index, 0, regs);
589 diff = value - (unsigned long) p->u.data;
590 }
592 /*
593 * The CF, OF, SF, ZF, AF, and PF flags are set according
594 * to the result
595 */
596 regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
597 X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
598 set_eflags_CF(size, value, (unsigned long) p->u.data, regs);
599 set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs);
600 set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs);
601 set_eflags_ZF(size, diff, regs);
602 set_eflags_SF(size, diff, regs);
603 set_eflags_PF(size, diff, regs);
604 break;
606 case INSTR_TEST:
607 if (src & REGISTER) {
608 index = operand_index(src);
609 value = get_reg_value(size, index, 0, regs);
610 } else if (src & IMMEDIATE) {
611 value = mpcip->immediate;
612 } else if (src & MEMORY) {
613 index = operand_index(dst);
614 value = get_reg_value(size, index, 0, regs);
615 }
616 diff = (unsigned long) p->u.data & value;
618 /*
619 * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
620 */
621 regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
622 X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
623 set_eflags_ZF(size, diff, regs);
624 set_eflags_SF(size, diff, regs);
625 set_eflags_PF(size, diff, regs);
626 break;
627 }
629 load_cpu_user_regs(regs);
630 }
632 void vmx_io_assist(struct vcpu *v)
633 {
634 vcpu_iodata_t *vio;
635 ioreq_t *p;
636 struct cpu_user_regs *regs = guest_cpu_user_regs();
637 struct mi_per_cpu_info *mpci_p;
638 struct cpu_user_regs *inst_decoder_regs;
640 mpci_p = &v->domain->arch.vmx_platform.mpci;
641 inst_decoder_regs = mpci_p->inst_decoder_regs;
643 vio = get_vio(v->domain, v->vcpu_id);
645 if (vio == 0) {
646 VMX_DBG_LOG(DBG_LEVEL_1,
647 "bad shared page: %lx", (unsigned long) vio);
648 printf("bad shared page: %lx\n", (unsigned long) vio);
649 domain_crash_synchronous();
650 }
652 p = &vio->vp_ioreq;
653 if (p->state == STATE_IORESP_HOOK)
654 vmx_hooks_assist(v);
656 /* clear IO wait VMX flag */
657 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
658 if (p->state == STATE_IORESP_READY) {
659 p->state = STATE_INVALID;
660 clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
662 if (p->type == IOREQ_TYPE_PIO)
663 vmx_pio_assist(regs, p, mpci_p);
664 else
665 vmx_mmio_assist(regs, p, mpci_p);
666 }
667 /* else an interrupt send event raced us */
668 }
669 }
671 int vmx_clear_pending_io_event(struct vcpu *v)
672 {
673 struct domain *d = v->domain;
674 int port = iopacket_port(d);
676 /* evtchn_pending is shared by other event channels in 0-31 range */
677 if (!d->shared_info->evtchn_pending[port>>5])
678 clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
680 /* Note: VMX domains may need upcalls as well */
681 if (!v->vcpu_info->evtchn_pending_sel)
682 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
684 /* clear the pending bit for port */
685 return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]);
686 }
688 /* Because we've cleared the pending events first, we need to guarantee that
689 * all events to be handled by xen for VMX domains are taken care of here.
690 *
691 * interrupts are guaranteed to be checked before resuming guest.
692 * VMX upcalls have been already arranged for if necessary.
693 */
694 void vmx_check_events(struct vcpu *d)
695 {
696 /* clear the event *before* checking for work. This should avoid
697 the set-and-check races */
698 if (vmx_clear_pending_io_event(current))
699 vmx_io_assist(d);
700 }
702 /* On exit from vmx_wait_io, we're guaranteed to have a I/O response from
703 the device model */
704 void vmx_wait_io()
705 {
706 extern void do_block();
707 int port = iopacket_port(current->domain);
709 do {
710 if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
711 do_block();
713 vmx_check_events(current);
714 if (!test_bit(ARCH_VMX_IO_WAIT, &current->arch.arch_vmx.flags))
715 break;
716 /* Events other than IOPACKET_PORT might have woken us up. In that
717 case, safely go back to sleep. */
718 clear_bit(port>>5, &current->vcpu_info->evtchn_pending_sel);
719 clear_bit(0, &current->vcpu_info->evtchn_upcall_pending);
720 } while(1);
721 }
723 #if defined(__i386__) || defined(__x86_64__)
724 static inline int __fls(u32 word)
725 {
726 int bit;
728 __asm__("bsrl %1,%0"
729 :"=r" (bit)
730 :"rm" (word));
731 return word ? bit : -1;
732 }
733 #else
734 #define __fls(x) generic_fls(x)
735 static __inline__ int generic_fls(u32 x)
736 {
737 int r = 31;
739 if (!x)
740 return -1;
741 if (!(x & 0xffff0000u)) {
742 x <<= 16;
743 r -= 16;
744 }
745 if (!(x & 0xff000000u)) {
746 x <<= 8;
747 r -= 8;
748 }
749 if (!(x & 0xf0000000u)) {
750 x <<= 4;
751 r -= 4;
752 }
753 if (!(x & 0xc0000000u)) {
754 x <<= 2;
755 r -= 2;
756 }
757 if (!(x & 0x80000000u)) {
758 x <<= 1;
759 r -= 1;
760 }
761 return r;
762 }
763 #endif
765 /* Simple minded Local APIC priority implementation. Fix later */
766 static __inline__ int find_highest_irq(u32 *pintr)
767 {
768 if (pintr[7])
769 return __fls(pintr[7]) + (256-32*1);
770 if (pintr[6])
771 return __fls(pintr[6]) + (256-32*2);
772 if (pintr[5])
773 return __fls(pintr[5]) + (256-32*3);
774 if (pintr[4])
775 return __fls(pintr[4]) + (256-32*4);
776 if (pintr[3])
777 return __fls(pintr[3]) + (256-32*5);
778 if (pintr[2])
779 return __fls(pintr[2]) + (256-32*6);
780 if (pintr[1])
781 return __fls(pintr[1]) + (256-32*7);
782 return __fls(pintr[0]);
783 }
785 #define BSP_CPU(d) (!(d->vcpu_id))
786 static inline void clear_extint(struct vcpu *v)
787 {
788 global_iodata_t *spg;
789 int i;
790 spg = &get_sp(v->domain)->sp_global;
792 for(i = 0; i < INTR_LEN; i++)
793 spg->pic_intr[i] = 0;
794 }
796 static inline void clear_highest_bit(struct vcpu *v, int vector)
797 {
798 global_iodata_t *spg;
800 spg = &get_sp(v->domain)->sp_global;
802 clear_bit(vector, &spg->pic_intr[0]);
803 }
805 static inline int find_highest_pic_irq(struct vcpu *v)
806 {
807 u64 intr[INTR_LEN];
808 global_iodata_t *spg;
809 int i;
811 if(!BSP_CPU(v))
812 return -1;
814 spg = &get_sp(v->domain)->sp_global;
816 for(i = 0; i < INTR_LEN; i++){
817 intr[i] = spg->pic_intr[i] & ~spg->pic_mask[i];
818 }
820 return find_highest_irq((u32 *)&intr[0]);
821 }
823 /*
824 * Return 0-255 for pending irq.
825 * -1 when no pending.
826 */
827 static inline int find_highest_pending_irq(struct vcpu *v, int *type)
828 {
829 int result = -1;
830 if ((result = find_highest_pic_irq(v)) != -1){
831 *type = VLAPIC_DELIV_MODE_EXT;
832 return result;
833 }
834 return result;
835 }
837 static inline void
838 interrupt_post_injection(struct vcpu * v, int vector, int type)
839 {
840 struct vmx_virpit_t *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
841 switch(type)
842 {
843 case VLAPIC_DELIV_MODE_EXT:
844 if (vpit->pending_intr_nr && vector == vpit->vector)
845 vpit->pending_intr_nr--;
846 else
847 clear_highest_bit(v, vector);
849 if (vector == vpit->vector && !vpit->first_injected){
850 vpit->first_injected = 1;
851 vpit->pending_intr_nr = 0;
852 }
853 if (vector == vpit->vector)
854 vpit->inject_point = NOW();
855 break;
857 default:
858 printk("Not support interrupt type\n");
859 break;
860 }
861 }
863 static inline void
864 enable_irq_window(unsigned long cpu_exec_control)
865 {
866 if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
867 cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
868 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
869 }
870 }
872 static inline void
873 disable_irq_window(unsigned long cpu_exec_control)
874 {
875 if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
876 cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
877 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
878 }
879 }
881 static inline int irq_masked(unsigned long eflags)
882 {
883 return ((eflags & X86_EFLAGS_IF) == 0);
884 }
886 asmlinkage void vmx_intr_assist(void)
887 {
888 int intr_type = 0;
889 int highest_vector;
890 unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
891 struct vcpu *v = current;
893 highest_vector = find_highest_pending_irq(v, &intr_type);
894 __vmread(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
896 if (highest_vector == -1) {
897 disable_irq_window(cpu_exec_control);
898 return;
899 }
901 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
903 if (intr_fields & INTR_INFO_VALID_MASK) {
904 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
905 intr_fields);
906 return;
907 }
909 __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
911 if (interruptibility) {
912 enable_irq_window(cpu_exec_control);
913 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx",
914 highest_vector, interruptibility);
915 return;
916 }
918 __vmread(GUEST_RFLAGS, &eflags);
920 switch (intr_type) {
921 case VLAPIC_DELIV_MODE_EXT:
922 if (irq_masked(eflags)) {
923 enable_irq_window(cpu_exec_control);
924 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx",
925 highest_vector, eflags);
926 return;
927 }
929 vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
930 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
931 break;
932 case VLAPIC_DELIV_MODE_FIXED:
933 case VLAPIC_DELIV_MODE_LPRI:
934 case VLAPIC_DELIV_MODE_SMI:
935 case VLAPIC_DELIV_MODE_NMI:
936 case VLAPIC_DELIV_MODE_INIT:
937 case VLAPIC_DELIV_MODE_STARTUP:
938 default:
939 printk("Unsupported interrupt type\n");
940 BUG();
941 break;
942 }
944 interrupt_post_injection(v, highest_vector, intr_type);
945 return;
946 }
948 void vmx_do_resume(struct vcpu *d)
949 {
950 vmx_stts();
951 if ( vmx_paging_enabled(d) )
952 __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table));
953 else
954 // paging is not enabled in the guest
955 __vmwrite(GUEST_CR3, pagetable_get_paddr(d->domain->arch.phys_table));
957 __vmwrite(HOST_CR3, pagetable_get_paddr(d->arch.monitor_table));
958 __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
960 if (event_pending(d)) {
961 vmx_check_events(d);
963 if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
964 vmx_wait_io();
965 }
967 /* We can't resume the guest if we're waiting on I/O */
968 ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags));
969 }
971 #endif /* CONFIG_VMX */
973 /*
974 * Local variables:
975 * mode: C
976 * c-set-style: "BSD"
977 * c-basic-offset: 4
978 * tab-width: 4
979 * indent-tabs-mode: nil
980 * End:
981 */