xen-vtx-unstable

annotate xen/arch/x86/vmx_io.c @ 6774:4d899a738d59

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