xen-vtx-unstable

annotate xen/arch/x86/vmx_platform.c @ 6781:8ca0f98ba8e2

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:33:37 2005 +0000 (2005-09-13)
parents 3feb7fa331ed 4d899a738d59
children 72e4e2aab342
rev   line source
iap10@3569 1 /*
iap10@3569 2 * vmx_platform.c: handling x86 platform related MMIO instructions
iap10@3569 3 * Copyright (c) 2004, Intel Corporation.
iap10@3569 4 *
iap10@3569 5 * This program is free software; you can redistribute it and/or modify it
iap10@3569 6 * under the terms and conditions of the GNU General Public License,
iap10@3569 7 * version 2, as published by the Free Software Foundation.
iap10@3569 8 *
iap10@3569 9 * This program is distributed in the hope it will be useful, but WITHOUT
iap10@3569 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
iap10@3569 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
iap10@3569 12 * more details.
iap10@3569 13 *
iap10@3569 14 * You should have received a copy of the GNU General Public License along with
iap10@3569 15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
iap10@3569 16 * Place - Suite 330, Boston, MA 02111-1307 USA.
iap10@3569 17 *
iap10@3569 18 */
iap10@3569 19
iap10@3569 20 #include <xen/config.h>
iap10@3569 21 #include <xen/types.h>
iap10@3569 22 #include <xen/mm.h>
iap10@3569 23 #include <asm/shadow.h>
kaf24@5356 24 #include <xen/domain_page.h>
iap10@3569 25 #include <asm/page.h>
iap10@3569 26 #include <xen/event.h>
iap10@3569 27 #include <xen/trace.h>
iap10@3569 28 #include <asm/vmx.h>
iap10@3569 29 #include <asm/vmx_platform.h>
iap10@3569 30 #include <public/io/ioreq.h>
iap10@3569 31
iap10@3569 32 #include <xen/lib.h>
iap10@3569 33 #include <xen/sched.h>
iap10@3569 34 #include <asm/current.h>
kaf24@5909 35 #if CONFIG_PAGING_LEVELS >= 3
kaf24@5722 36 #include <asm/shadow_64.h>
kaf24@5722 37 #endif
mafetter@3717 38 #ifdef CONFIG_VMX
mafetter@3717 39
iap10@3569 40 #define DECODE_success 1
iap10@3569 41 #define DECODE_failure 0
iap10@3569 42
iap10@3569 43 #if defined (__x86_64__)
kaf24@5000 44 void store_cpu_user_regs(struct cpu_user_regs *regs)
iap10@3569 45 {
kaf24@5555 46 __vmread(GUEST_SS_SELECTOR, &regs->ss);
kaf24@5555 47 __vmread(GUEST_RSP, &regs->rsp);
kaf24@5555 48 __vmread(GUEST_RFLAGS, &regs->rflags);
kaf24@5555 49 __vmread(GUEST_CS_SELECTOR, &regs->cs);
kaf24@5555 50 __vmread(GUEST_DS_SELECTOR, &regs->ds);
kaf24@5555 51 __vmread(GUEST_ES_SELECTOR, &regs->es);
kaf24@5555 52 __vmread(GUEST_RIP, &regs->rip);
kaf24@5555 53 }
iap10@3569 54
kaf24@5555 55 static inline long __get_reg_value(unsigned long reg, int size)
kaf24@5555 56 {
kaf24@5555 57 switch(size) {
kaf24@6730 58 case BYTE_64:
kaf24@6730 59 return (char)(reg & 0xFF);
kaf24@6730 60 case WORD:
kaf24@6730 61 return (short)(reg & 0xFFFF);
kaf24@6730 62 case LONG:
kaf24@6730 63 return (int)(reg & 0xFFFFFFFF);
kaf24@6730 64 case QUAD:
kaf24@6730 65 return (long)(reg);
kaf24@6730 66 default:
kaf24@6730 67 printf("Error: (__get_reg_value) Invalid reg size\n");
kaf24@6730 68 domain_crash_synchronous();
kaf24@5555 69 }
iap10@3569 70 }
iap10@3569 71
kaf24@6594 72 long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
iap10@3569 73 {
kaf24@5555 74 if (size == BYTE) {
kaf24@5555 75 switch (index) {
kaf24@6730 76 case 0: /* %al */
kaf24@6730 77 return (char)(regs->rax & 0xFF);
kaf24@6730 78 case 1: /* %cl */
kaf24@6730 79 return (char)(regs->rcx & 0xFF);
kaf24@6730 80 case 2: /* %dl */
kaf24@6730 81 return (char)(regs->rdx & 0xFF);
kaf24@6730 82 case 3: /* %bl */
kaf24@6730 83 return (char)(regs->rbx & 0xFF);
kaf24@6730 84 case 4: /* %ah */
kaf24@6730 85 return (char)((regs->rax & 0xFF00) >> 8);
kaf24@6730 86 case 5: /* %ch */
kaf24@6730 87 return (char)((regs->rcx & 0xFF00) >> 8);
kaf24@6730 88 case 6: /* %dh */
kaf24@6730 89 return (char)((regs->rdx & 0xFF00) >> 8);
kaf24@6730 90 case 7: /* %bh */
kaf24@6730 91 return (char)((regs->rbx & 0xFF00) >> 8);
kaf24@6730 92 default:
kaf24@6730 93 printf("Error: (get_reg_value) Invalid index value\n");
kaf24@6730 94 domain_crash_synchronous();
kaf24@5555 95 }
kaf24@6730 96 /* NOTREACHED */
kaf24@6594 97 }
kaf24@5555 98
kaf24@5555 99 switch (index) {
kaf24@6730 100 case 0: return __get_reg_value(regs->rax, size);
kaf24@6730 101 case 1: return __get_reg_value(regs->rcx, size);
kaf24@6730 102 case 2: return __get_reg_value(regs->rdx, size);
kaf24@6730 103 case 3: return __get_reg_value(regs->rbx, size);
kaf24@6730 104 case 4: return __get_reg_value(regs->rsp, size);
kaf24@6730 105 case 5: return __get_reg_value(regs->rbp, size);
kaf24@6730 106 case 6: return __get_reg_value(regs->rsi, size);
kaf24@6730 107 case 7: return __get_reg_value(regs->rdi, size);
kaf24@6730 108 case 8: return __get_reg_value(regs->r8, size);
kaf24@6730 109 case 9: return __get_reg_value(regs->r9, size);
kaf24@6730 110 case 10: return __get_reg_value(regs->r10, size);
kaf24@6730 111 case 11: return __get_reg_value(regs->r11, size);
kaf24@6730 112 case 12: return __get_reg_value(regs->r12, size);
kaf24@6730 113 case 13: return __get_reg_value(regs->r13, size);
kaf24@6730 114 case 14: return __get_reg_value(regs->r14, size);
kaf24@6730 115 case 15: return __get_reg_value(regs->r15, size);
kaf24@6730 116 default:
kaf24@6730 117 printf("Error: (get_reg_value) Invalid index value\n");
kaf24@6730 118 domain_crash_synchronous();
kaf24@5555 119 }
iap10@3569 120 }
iap10@3569 121 #elif defined (__i386__)
arun@4999 122 void store_cpu_user_regs(struct cpu_user_regs *regs)
iap10@3569 123 {
iap10@3569 124 __vmread(GUEST_SS_SELECTOR, &regs->ss);
kaf24@5414 125 __vmread(GUEST_RSP, &regs->esp);
kaf24@5414 126 __vmread(GUEST_RFLAGS, &regs->eflags);
iap10@3569 127 __vmread(GUEST_CS_SELECTOR, &regs->cs);
leendert@4442 128 __vmread(GUEST_DS_SELECTOR, &regs->ds);
leendert@4442 129 __vmread(GUEST_ES_SELECTOR, &regs->es);
kaf24@5414 130 __vmread(GUEST_RIP, &regs->eip);
iap10@3569 131 }
iap10@3569 132
kaf24@6594 133 static inline long __get_reg_value(unsigned long reg, int size)
iap10@3569 134 {
kaf24@6594 135 switch(size) {
kaf24@6594 136 case WORD:
kaf24@6730 137 return (short)(reg & 0xFFFF);
kaf24@6594 138 case LONG:
kaf24@6730 139 return (int)(reg & 0xFFFFFFFF);
kaf24@6594 140 default:
kaf24@6730 141 printf("Error: (__get_reg_value) Invalid reg size\n");
kaf24@6730 142 domain_crash_synchronous();
kaf24@6594 143 }
kaf24@6594 144 }
kaf24@6594 145
kaf24@6594 146 long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
kaf24@6594 147 {
kaf24@6594 148 if (size == BYTE) {
iap10@3569 149 switch (index) {
kaf24@6730 150 case 0: /* %al */
iap10@3569 151 return (char)(regs->eax & 0xFF);
kaf24@6730 152 case 1: /* %cl */
iap10@3569 153 return (char)(regs->ecx & 0xFF);
kaf24@6730 154 case 2: /* %dl */
iap10@3569 155 return (char)(regs->edx & 0xFF);
kaf24@6730 156 case 3: /* %bl */
iap10@3569 157 return (char)(regs->ebx & 0xFF);
kaf24@6730 158 case 4: /* %ah */
iap10@3569 159 return (char)((regs->eax & 0xFF00) >> 8);
kaf24@6730 160 case 5: /* %ch */
iap10@3569 161 return (char)((regs->ecx & 0xFF00) >> 8);
kaf24@6730 162 case 6: /* %dh */
iap10@3569 163 return (char)((regs->edx & 0xFF00) >> 8);
kaf24@6730 164 case 7: /* %bh */
iap10@3569 165 return (char)((regs->ebx & 0xFF00) >> 8);
iap10@3569 166 default:
kaf24@6730 167 printf("Error: (get_reg_value) Invalid index value\n");
kaf24@5555 168 domain_crash_synchronous();
iap10@3569 169 }
kaf24@6730 170 }
kaf24@6594 171
kaf24@6730 172 switch (index) {
kaf24@6594 173 case 0: return __get_reg_value(regs->eax, size);
kaf24@6594 174 case 1: return __get_reg_value(regs->ecx, size);
kaf24@6594 175 case 2: return __get_reg_value(regs->edx, size);
kaf24@6594 176 case 3: return __get_reg_value(regs->ebx, size);
kaf24@6594 177 case 4: return __get_reg_value(regs->esp, size);
kaf24@6594 178 case 5: return __get_reg_value(regs->ebp, size);
kaf24@6594 179 case 6: return __get_reg_value(regs->esi, size);
kaf24@6594 180 case 7: return __get_reg_value(regs->edi, size);
iap10@3569 181 default:
kaf24@6730 182 printf("Error: (get_reg_value) Invalid index value\n");
kaf24@5555 183 domain_crash_synchronous();
iap10@3569 184 }
iap10@3569 185 }
iap10@3569 186 #endif
iap10@3569 187
kaf24@6594 188 static inline unsigned char *check_prefix(unsigned char *inst,
kaf24@6730 189 struct instruction *thread_inst, unsigned char *rex_p)
iap10@3569 190 {
iap10@3569 191 while (1) {
iap10@3569 192 switch (*inst) {
kaf24@6730 193 /* rex prefix for em64t instructions */
kaf24@6730 194 case 0x40 ... 0x4e:
kaf24@6730 195 *rex_p = *inst;
kaf24@6730 196 break;
kaf24@6594 197 case 0xf3: /* REPZ */
kaf24@6730 198 thread_inst->flags = REPZ;
kaf24@6730 199 break;
kaf24@6594 200 case 0xf2: /* REPNZ */
kaf24@6730 201 thread_inst->flags = REPNZ;
kaf24@6730 202 break;
kaf24@6594 203 case 0xf0: /* LOCK */
kaf24@6730 204 break;
kaf24@6594 205 case 0x2e: /* CS */
kaf24@6594 206 case 0x36: /* SS */
kaf24@6594 207 case 0x3e: /* DS */
kaf24@6594 208 case 0x26: /* ES */
kaf24@6594 209 case 0x64: /* FS */
kaf24@6594 210 case 0x65: /* GS */
kaf24@6730 211 thread_inst->seg_sel = *inst;
kaf24@6730 212 break;
kaf24@6594 213 case 0x66: /* 32bit->16bit */
kaf24@6730 214 thread_inst->op_size = WORD;
kaf24@6730 215 break;
kaf24@6730 216 case 0x67:
kaf24@6730 217 printf("Error: Not handling 0x67 (yet)\n");
kaf24@6730 218 domain_crash_synchronous();
kaf24@6730 219 break;
kaf24@6730 220 default:
kaf24@6730 221 return inst;
iap10@3569 222 }
iap10@3569 223 inst++;
iap10@3569 224 }
iap10@3569 225 }
iap10@3569 226
kaf24@6594 227 static inline unsigned long get_immediate(int op16,const unsigned char *inst, int op_size)
iap10@3569 228 {
iap10@3569 229 int mod, reg, rm;
iap10@3569 230 unsigned long val = 0;
iap10@3569 231 int i;
iap10@3569 232
iap10@3569 233 mod = (*inst >> 6) & 3;
iap10@3569 234 reg = (*inst >> 3) & 7;
iap10@3569 235 rm = *inst & 7;
iap10@3569 236
iap10@3569 237 inst++; //skip ModR/M byte
iap10@3569 238 if (mod != 3 && rm == 4) {
iap10@3569 239 inst++; //skip SIB byte
iap10@3569 240 }
iap10@3569 241
iap10@3569 242 switch(mod) {
kaf24@6730 243 case 0:
kaf24@6730 244 if (rm == 5 || rm == 4) {
kaf24@5555 245 if (op16)
leendert@4442 246 inst = inst + 2; //disp16, skip 2 bytes
kaf24@5555 247 else
leendert@4442 248 inst = inst + 4; //disp32, skip 4 bytes
kaf24@6730 249 }
kaf24@6730 250 break;
kaf24@6730 251 case 1:
kaf24@6730 252 inst++; //disp8, skip 1 byte
kaf24@6730 253 break;
kaf24@6730 254 case 2:
kaf24@6730 255 if (op16)
kaf24@6730 256 inst = inst + 2; //disp16, skip 2 bytes
kaf24@6730 257 else
kaf24@6730 258 inst = inst + 4; //disp32, skip 4 bytes
kaf24@6730 259 break;
iap10@3569 260 }
kaf24@5555 261
kaf24@5555 262 if (op_size == QUAD)
kaf24@5555 263 op_size = LONG;
kaf24@5555 264
iap10@3569 265 for (i = 0; i < op_size; i++) {
iap10@3569 266 val |= (*inst++ & 0xff) << (8 * i);
iap10@3569 267 }
kaf24@5555 268
iap10@3569 269 return val;
iap10@3569 270 }
iap10@3569 271
kaf24@5555 272 static inline int get_index(const unsigned char *inst, unsigned char rex)
iap10@3569 273 {
iap10@3569 274 int mod, reg, rm;
kaf24@5555 275 int rex_r, rex_b;
iap10@3569 276
iap10@3569 277 mod = (*inst >> 6) & 3;
iap10@3569 278 reg = (*inst >> 3) & 7;
iap10@3569 279 rm = *inst & 7;
iap10@3569 280
kaf24@5555 281 rex_r = (rex >> 2) & 1;
kaf24@5555 282 rex_b = rex & 1;
kaf24@5555 283
iap10@3569 284 //Only one operand in the instruction is register
iap10@3569 285 if (mod == 3) {
kaf24@5555 286 return (rm + (rex_b << 3));
iap10@3569 287 } else {
kaf24@5555 288 return (reg + (rex_r << 3));
iap10@3569 289 }
iap10@3569 290 return 0;
iap10@3569 291 }
iap10@3569 292
kaf24@5555 293 static void init_instruction(struct instruction *mmio_inst)
kaf24@5555 294 {
kaf24@6594 295 mmio_inst->instr = 0;
kaf24@6594 296 mmio_inst->op_size = 0;
kaf24@5555 297 mmio_inst->immediate = 0;
kaf24@5555 298 mmio_inst->seg_sel = 0;
kaf24@5555 299
kaf24@5555 300 mmio_inst->operand[0] = 0;
kaf24@5555 301 mmio_inst->operand[1] = 0;
kaf24@5555 302
kaf24@5555 303 mmio_inst->flags = 0;
kaf24@5555 304 }
kaf24@5555 305
kaf24@5555 306 #define GET_OP_SIZE_FOR_BYTE(op_size) \
kaf24@6730 307 do { \
kaf24@6730 308 if (rex) \
kaf24@6730 309 op_size = BYTE_64; \
kaf24@6730 310 else \
kaf24@6730 311 op_size = BYTE; \
kaf24@6594 312 } while(0)
kaf24@5555 313
kaf24@5555 314 #define GET_OP_SIZE_FOR_NONEBYTE(op_size) \
kaf24@6730 315 do { \
kaf24@6730 316 if (rex & 0x8) \
kaf24@6730 317 op_size = QUAD; \
kaf24@6730 318 else if (op_size != WORD) \
kaf24@6730 319 op_size = LONG; \
kaf24@6594 320 } while(0)
kaf24@6594 321
kaf24@6594 322
kaf24@6594 323 /*
kaf24@6594 324 * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
kaf24@6594 325 */
kaf24@6594 326 static int mem_acc(unsigned char size, struct instruction *instr)
kaf24@6594 327 {
kaf24@6594 328 instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
kaf24@6594 329 instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
kaf24@6594 330 return DECODE_success;
kaf24@6594 331 }
kaf24@6594 332
kaf24@6594 333 /*
kaf24@6594 334 * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
kaf24@6594 335 */
kaf24@6594 336 static int acc_mem(unsigned char size, struct instruction *instr)
kaf24@6594 337 {
kaf24@6594 338 instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
kaf24@6594 339 instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
kaf24@6594 340 return DECODE_success;
kaf24@6594 341 }
kaf24@5555 342
kaf24@6594 343 /*
kaf24@6594 344 * Decode mem,reg operands (as in <opcode> r32/16, m32/16)
kaf24@6594 345 */
kaf24@6594 346 static int mem_reg(unsigned char size, unsigned char *opcode,
kaf24@6730 347 struct instruction *instr, unsigned char rex)
kaf24@6594 348 {
kaf24@6594 349 int index = get_index(opcode + 1, rex);
kaf24@6594 350
kaf24@6594 351 instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
kaf24@6594 352 instr->operand[1] = mk_operand(size, index, 0, REGISTER);
kaf24@6594 353 return DECODE_success;
kaf24@6594 354 }
kaf24@6594 355
kaf24@6594 356 /*
kaf24@6594 357 * Decode reg,mem operands (as in <opcode> m32/16, r32/16)
kaf24@6594 358 */
kaf24@6594 359 static int reg_mem(unsigned char size, unsigned char *opcode,
kaf24@6730 360 struct instruction *instr, unsigned char rex)
kaf24@6594 361 {
kaf24@6594 362 int index = get_index(opcode + 1, rex);
kaf24@6594 363
kaf24@6594 364 instr->operand[0] = mk_operand(size, index, 0, REGISTER);
kaf24@6594 365 instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
kaf24@6594 366 return DECODE_success;
kaf24@6594 367 }
kaf24@6594 368
kaf24@6594 369 static int vmx_decode(unsigned char *opcode, struct instruction *instr)
iap10@3569 370 {
leendert@4442 371 unsigned long eflags;
leendert@4442 372 int index, vm86 = 0;
kaf24@5555 373 unsigned char rex = 0;
kaf24@5555 374 unsigned char tmp_size = 0;
kaf24@5555 375
kaf24@6594 376 init_instruction(instr);
kaf24@5555 377
kaf24@6594 378 opcode = check_prefix(opcode, instr, &rex);
leendert@4442 379
kaf24@5414 380 __vmread(GUEST_RFLAGS, &eflags);
leendert@4442 381 if (eflags & X86_EFLAGS_VM)
kaf24@5555 382 vm86 = 1;
leendert@4442 383
leendert@4442 384 if (vm86) { /* meaning is reversed */
kaf24@6730 385 if (instr->op_size == WORD)
kaf24@6730 386 instr->op_size = LONG;
kaf24@6730 387 else if (instr->op_size == LONG)
kaf24@6730 388 instr->op_size = WORD;
kaf24@6730 389 else if (instr->op_size == 0)
kaf24@6730 390 instr->op_size = WORD;
leendert@4442 391 }
iap10@3569 392
kaf24@6594 393 switch (*opcode) {
kaf24@6594 394 case 0x0B: /* or m32/16, r32/16 */
kaf24@6730 395 instr->instr = INSTR_OR;
kaf24@6730 396 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 397 return mem_reg(instr->op_size, opcode, instr, rex);
kaf24@6594 398
kaf24@6594 399 case 0x20: /* and r8, m8 */
kaf24@6730 400 instr->instr = INSTR_AND;
kaf24@6730 401 GET_OP_SIZE_FOR_BYTE(instr->op_size);
kaf24@6730 402 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@6594 403
kaf24@6594 404 case 0x21: /* and r32/16, m32/16 */
kaf24@6730 405 instr->instr = INSTR_AND;
kaf24@6730 406 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 407 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@5719 408
kaf24@6594 409 case 0x23: /* and m32/16, r32/16 */
kaf24@6730 410 instr->instr = INSTR_AND;
kaf24@6730 411 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 412 return mem_reg(instr->op_size, opcode, instr, rex);
kaf24@6594 413
kaf24@6594 414 case 0x30: /* xor r8, m8 */
kaf24@6730 415 instr->instr = INSTR_XOR;
kaf24@6730 416 GET_OP_SIZE_FOR_BYTE(instr->op_size);
kaf24@6730 417 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@5555 418
kaf24@6594 419 case 0x31: /* xor r32/16, m32/16 */
kaf24@6730 420 instr->instr = INSTR_XOR;
kaf24@6730 421 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 422 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@6594 423
kaf24@6594 424 case 0x39: /* cmp r32/16, m32/16 */
kaf24@6730 425 instr->instr = INSTR_CMP;
kaf24@6730 426 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 427 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@5555 428
kaf24@6717 429 case 0x80:
kaf24@6594 430 case 0x81:
kaf24@6730 431 if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */
kaf24@6730 432 instr->instr = INSTR_CMP;
kaf24@6594 433
kaf24@6730 434 if (opcode[0] == 0x80)
kaf24@6730 435 GET_OP_SIZE_FOR_BYTE(instr->op_size);
kaf24@6727 436 else
kaf24@6730 437 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6594 438
kaf24@6730 439 instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
kaf24@6730 440 instr->immediate = get_immediate(vm86, opcode+1, BYTE);
kaf24@6730 441 instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
kaf24@6594 442
kaf24@6594 443 return DECODE_success;
kaf24@6730 444 } else
kaf24@6730 445 return DECODE_failure;
kaf24@6594 446
kaf24@6594 447 case 0x84: /* test m8, r8 */
kaf24@6730 448 instr->instr = INSTR_TEST;
kaf24@6730 449 instr->op_size = BYTE;
kaf24@6730 450 GET_OP_SIZE_FOR_BYTE(tmp_size);
kaf24@6730 451 return mem_reg(tmp_size, opcode, instr, rex);
kaf24@6594 452
kaf24@6594 453 case 0x88: /* mov r8, m8 */
kaf24@6730 454 instr->instr = INSTR_MOV;
kaf24@6730 455 instr->op_size = BYTE;
kaf24@6594 456 GET_OP_SIZE_FOR_BYTE(tmp_size);
kaf24@6730 457 return reg_mem(tmp_size, opcode, instr, rex);
kaf24@6594 458
kaf24@6594 459 case 0x89: /* mov r32/16, m32/16 */
kaf24@6730 460 instr->instr = INSTR_MOV;
kaf24@6730 461 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 462 return reg_mem(instr->op_size, opcode, instr, rex);
kaf24@6594 463
kaf24@6594 464 case 0x8A: /* mov m8, r8 */
kaf24@6730 465 instr->instr = INSTR_MOV;
kaf24@6730 466 instr->op_size = BYTE;
kaf24@6594 467 GET_OP_SIZE_FOR_BYTE(tmp_size);
kaf24@6730 468 return mem_reg(tmp_size, opcode, instr, rex);
kaf24@6594 469
kaf24@6594 470 case 0x8B: /* mov m32/16, r32/16 */
kaf24@6730 471 instr->instr = INSTR_MOV;
kaf24@6730 472 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 473 return mem_reg(instr->op_size, opcode, instr, rex);
kaf24@5555 474
kaf24@6594 475 case 0xA0: /* mov <addr>, al */
kaf24@6730 476 instr->instr = INSTR_MOV;
kaf24@6730 477 instr->op_size = BYTE;
kaf24@6594 478 GET_OP_SIZE_FOR_BYTE(tmp_size);
kaf24@6730 479 return mem_acc(tmp_size, instr);
kaf24@6594 480
kaf24@6594 481 case 0xA1: /* mov <addr>, ax/eax */
kaf24@6730 482 instr->instr = INSTR_MOV;
kaf24@6730 483 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 484 return mem_acc(instr->op_size, instr);
kaf24@6594 485
kaf24@6594 486 case 0xA2: /* mov al, <addr> */
kaf24@6730 487 instr->instr = INSTR_MOV;
kaf24@6730 488 instr->op_size = BYTE;
kaf24@6594 489 GET_OP_SIZE_FOR_BYTE(tmp_size);
kaf24@6730 490 return acc_mem(tmp_size, instr);
kaf24@6594 491
kaf24@6594 492 case 0xA3: /* mov ax/eax, <addr> */
kaf24@6730 493 instr->instr = INSTR_MOV;
kaf24@6730 494 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 495 return acc_mem(instr->op_size, instr);
kaf24@6594 496
kaf24@6594 497 case 0xA4: /* movsb */
kaf24@6730 498 instr->instr = INSTR_MOVS;
kaf24@6730 499 instr->op_size = BYTE;
kaf24@6594 500 return DECODE_success;
kaf24@6594 501
kaf24@6594 502 case 0xA5: /* movsw/movsl */
kaf24@6730 503 instr->instr = INSTR_MOVS;
kaf24@6730 504 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 505 return DECODE_success;
kaf24@6594 506
kaf24@6594 507 case 0xAA: /* stosb */
kaf24@6730 508 instr->instr = INSTR_STOS;
kaf24@6730 509 instr->op_size = BYTE;
kaf24@6594 510 return DECODE_success;
kaf24@6594 511
kaf24@6594 512 case 0xAB: /* stosw/stosl */
kaf24@6730 513 instr->instr = INSTR_STOS;
kaf24@6730 514 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 515 return DECODE_success;
kaf24@6594 516
kaf24@6594 517 case 0xC6:
kaf24@6730 518 if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
kaf24@6730 519 instr->instr = INSTR_MOV;
kaf24@6730 520 instr->op_size = BYTE;
kaf24@6594 521
kaf24@6730 522 instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
kaf24@6730 523 instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
kaf24@6730 524 instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
kaf24@6594 525
iap10@3569 526 return DECODE_success;
kaf24@6730 527 } else
kaf24@6730 528 return DECODE_failure;
kaf24@6594 529
kaf24@6594 530 case 0xC7:
kaf24@6730 531 if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
kaf24@6730 532 instr->instr = INSTR_MOV;
kaf24@6730 533 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6594 534
kaf24@6730 535 instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
kaf24@6730 536 instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
kaf24@6730 537 instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
kaf24@6594 538
leendert@4442 539 return DECODE_success;
kaf24@6730 540 } else
kaf24@6730 541 return DECODE_failure;
kaf24@6594 542
kaf24@6594 543 case 0xF6:
kaf24@6730 544 if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */
kaf24@6730 545 instr->instr = INSTR_TEST;
kaf24@6730 546 instr->op_size = BYTE;
kaf24@6594 547
kaf24@6730 548 instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
kaf24@6730 549 instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
kaf24@6730 550 instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
kaf24@6594 551
kaf24@6730 552 return DECODE_success;
kaf24@6730 553 } else
kaf24@6730 554 return DECODE_failure;
kaf24@6594 555
kaf24@6594 556 case 0x0F:
kaf24@6730 557 break;
kaf24@6594 558
kaf24@6594 559 default:
kaf24@6730 560 printf("%x, This opcode isn't handled yet!\n", *opcode);
kaf24@6594 561 return DECODE_failure;
iap10@3569 562 }
iap10@3569 563
kaf24@6594 564 switch (*++opcode) {
kaf24@6594 565 case 0xB6: /* movz m8, r16/r32 */
kaf24@6730 566 instr->instr = INSTR_MOVZ;
kaf24@6730 567 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
kaf24@6730 568 index = get_index(opcode + 1, rex);
kaf24@6730 569 instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
kaf24@6730 570 instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
kaf24@6730 571 return DECODE_success;
kaf24@6594 572
kaf24@6594 573 case 0xB7: /* movz m16, r32 */
kaf24@6730 574 instr->instr = INSTR_MOVZ;
kaf24@6730 575 index = get_index(opcode + 1, rex);
kaf24@6730 576 if (rex & 0x8) {
kaf24@6730 577 instr->op_size = LONG;
kaf24@6730 578 instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
kaf24@6730 579 } else {
kaf24@6730 580 instr->op_size = WORD;
kaf24@6730 581 instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
kaf24@6730 582 }
kaf24@6730 583 instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
kaf24@6730 584 return DECODE_success;
kaf24@6594 585
kaf24@6594 586 default:
kaf24@6730 587 printf("0f %x, This opcode isn't handled yet\n", *opcode);
kaf24@6730 588 return DECODE_failure;
iap10@3569 589 }
iap10@3569 590 }
iap10@3569 591
kaf24@5555 592 int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len)
iap10@3569 593 {
kaf24@6634 594 if (inst_len > MAX_INST_LEN || inst_len <= 0)
iap10@3569 595 return 0;
kaf24@6634 596 if (!vmx_copy(buf, guest_eip, inst_len, VMX_COPY_IN))
kaf24@6634 597 return 0;
kaf24@6634 598 return inst_len;
iap10@3569 599 }
iap10@3569 600
kaf24@6594 601 void send_mmio_req(unsigned char type, unsigned long gpa,
kaf24@6730 602 unsigned long count, int size, long value, int dir, int pvalid)
iap10@3569 603 {
kaf24@5289 604 struct vcpu *d = current;
iap10@3569 605 vcpu_iodata_t *vio;
iap10@3569 606 ioreq_t *p;
leendert@4442 607 int vm86;
kaf24@6594 608 struct cpu_user_regs *regs;
iap10@3569 609 extern long evtchn_send(int lport);
iap10@3569 610
kaf24@6594 611 regs = current->domain->arch.vmx_platform.mpci.inst_decoder_regs;
leendert@4442 612
arun@5608 613 vio = get_vio(d->domain, d->vcpu_id);
iap10@3569 614 if (vio == NULL) {
kaf24@6594 615 printf("bad shared page\n");
kaf24@4325 616 domain_crash_synchronous();
iap10@3569 617 }
kaf24@6594 618
iap10@3569 619 p = &vio->vp_ioreq;
leendert@4442 620
kaf24@6594 621 vm86 = regs->eflags & X86_EFLAGS_VM;
leendert@4442 622
leendert@4602 623 if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
leendert@4602 624 printf("VMX I/O has not yet completed\n");
leendert@4602 625 domain_crash_synchronous();
leendert@4602 626 }
leendert@4602 627
kaf24@3677 628 set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags);
iap10@3569 629 p->dir = dir;
iap10@3569 630 p->pdata_valid = pvalid;
iap10@3569 631
kaf24@6594 632 p->type = type;
kaf24@6594 633 p->size = size;
iap10@3569 634 p->addr = gpa;
kaf24@6594 635 p->count = count;
kaf24@6594 636 p->df = regs->eflags & EF_DF ? 1 : 0;
kaf24@6594 637
kaf24@6594 638 if (pvalid) {
kaf24@6730 639 if (vmx_paging_enabled(current))
kaf24@6730 640 p->u.pdata = (void *) gva_to_gpa(value);
kaf24@6594 641 else
kaf24@6730 642 p->u.pdata = (void *) value; /* guest VA == guest PA */
kaf24@6594 643 } else
kaf24@6730 644 p->u.data = value;
iap10@3569 645
iap10@3569 646 p->state = STATE_IOREQ_READY;
iap10@3569 647
arun@5609 648 if (vmx_mmio_intercept(p)){
arun@5609 649 p->state = STATE_IORESP_READY;
arun@5609 650 vmx_io_assist(d);
arun@5609 651 return;
arun@5609 652 }
iap10@3569 653
arun@5608 654 evtchn_send(iopacket_port(d->domain));
arun@5185 655 vmx_wait_io();
iap10@3569 656 }
iap10@3569 657
kaf24@6594 658 static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
kaf24@6730 659 struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs)
kaf24@6594 660 {
kaf24@6594 661 unsigned long value = 0;
kaf24@6594 662 int index, size;
kaf24@6594 663
kaf24@6594 664 size = operand_size(inst->operand[0]);
kaf24@6594 665
kaf24@6594 666 mpcip->flags = inst->flags;
kaf24@6594 667 mpcip->instr = inst->instr;
kaf24@6594 668 mpcip->operand[0] = inst->operand[0]; /* source */
kaf24@6594 669 mpcip->operand[1] = inst->operand[1]; /* destination */
kaf24@6594 670
kaf24@6594 671 if (inst->operand[0] & REGISTER) { /* dest is memory */
kaf24@6730 672 index = operand_index(inst->operand[0]);
kaf24@6730 673 value = get_reg_value(size, index, 0, regs);
kaf24@6730 674 send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
kaf24@6594 675 } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
kaf24@6730 676 value = inst->immediate;
kaf24@6730 677 send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
kaf24@6594 678 } else if (inst->operand[0] & MEMORY) { /* dest is register */
kaf24@6730 679 /* send the request and wait for the value */
kaf24@6730 680 send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0);
kaf24@6594 681 } else {
kaf24@6730 682 printf("mmio_operands: invalid operand\n");
kaf24@6730 683 domain_crash_synchronous();
kaf24@6594 684 }
kaf24@6594 685 }
kaf24@6594 686
kaf24@6594 687 #define GET_REPEAT_COUNT() \
kaf24@6594 688 (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1)
kaf24@6730 689
iap10@3756 690 void handle_mmio(unsigned long va, unsigned long gpa)
iap10@3569 691 {
leendert@4442 692 unsigned long eip, eflags, cs;
leendert@4442 693 unsigned long inst_len, inst_addr;
kaf24@6594 694 struct mi_per_cpu_info *mpcip;
kaf24@6594 695 struct cpu_user_regs *regs;
iap10@3569 696 struct instruction mmio_inst;
iap10@3569 697 unsigned char inst[MAX_INST_LEN];
kaf24@6594 698 int i, vm86, ret;
iap10@3569 699
kaf24@6594 700 mpcip = &current->domain->arch.vmx_platform.mpci;
kaf24@6594 701 regs = mpcip->inst_decoder_regs;
iap10@3569 702
kaf24@5414 703 __vmread(GUEST_RIP, &eip);
adsharma@6526 704 __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
kaf24@5414 705 __vmread(GUEST_RFLAGS, &eflags);
leendert@4442 706 vm86 = eflags & X86_EFLAGS_VM;
leendert@4442 707
leendert@4442 708 if (vm86) {
leendert@4442 709 __vmread(GUEST_CS_SELECTOR, &cs);
leendert@5087 710 inst_addr = (cs << 4) + eip;
leendert@4442 711 } else
kaf24@6594 712 inst_addr = eip;
leendert@4442 713
kaf24@6594 714 memset(inst, 0, MAX_INST_LEN);
leendert@4442 715 ret = inst_copy_from_guest(inst, inst_addr, inst_len);
iap10@3569 716 if (ret != inst_len) {
kaf24@6594 717 printf("handle_mmio - EXIT: get guest instruction fault\n");
kaf24@4325 718 domain_crash_synchronous();
iap10@3569 719 }
iap10@3569 720
iap10@3569 721 init_instruction(&mmio_inst);
iap10@3569 722
kaf24@5716 723 if (vmx_decode(inst, &mmio_inst) == DECODE_failure) {
kaf24@6730 724 printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
kaf24@6730 725 va, gpa, inst_len);
kaf24@6730 726 for (i = 0; i < inst_len; i++)
kaf24@6730 727 printf(" %02x", inst[i] & 0xFF);
kaf24@6730 728 printf("\n");
kaf24@4325 729 domain_crash_synchronous();
kaf24@5716 730 }
iap10@3569 731
kaf24@6594 732 store_cpu_user_regs(regs);
kaf24@6594 733 regs->eip += inst_len; /* advance %eip */
iap10@3569 734
kaf24@6594 735 switch (mmio_inst.instr) {
kaf24@6594 736 case INSTR_MOV:
kaf24@6730 737 mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 738 break;
iap10@3569 739
kaf24@6594 740 case INSTR_MOVS:
kaf24@6594 741 {
kaf24@6730 742 unsigned long count = GET_REPEAT_COUNT();
kaf24@6730 743 unsigned long size = mmio_inst.op_size;
kaf24@6730 744 int sign = regs->eflags & EF_DF ? -1 : 1;
kaf24@6730 745 unsigned long addr = 0;
kaf24@6730 746 int dir;
leendert@4442 747
kaf24@6730 748 /* determine non-MMIO address */
kaf24@6730 749 if (vm86) {
kaf24@6730 750 unsigned long seg;
iap10@3569 751
kaf24@6730 752 __vmread(GUEST_ES_SELECTOR, &seg);
kaf24@6730 753 if (((seg << 4) + (regs->edi & 0xFFFF)) == va) {
kaf24@6730 754 dir = IOREQ_WRITE;
kaf24@6730 755 __vmread(GUEST_DS_SELECTOR, &seg);
kaf24@6730 756 addr = (seg << 4) + (regs->esi & 0xFFFF);
kaf24@6730 757 } else {
kaf24@6730 758 dir = IOREQ_READ;
kaf24@6730 759 addr = (seg << 4) + (regs->edi & 0xFFFF);
kaf24@6730 760 }
kaf24@6730 761 } else {
kaf24@6730 762 if (va == regs->edi) {
kaf24@6730 763 dir = IOREQ_WRITE;
kaf24@6730 764 addr = regs->esi;
kaf24@6730 765 } else {
kaf24@6730 766 dir = IOREQ_READ;
kaf24@6730 767 addr = regs->edi;
kaf24@6730 768 }
kaf24@6730 769 }
leendert@4442 770
kaf24@6730 771 mpcip->flags = mmio_inst.flags;
kaf24@6730 772 mpcip->instr = mmio_inst.instr;
kaf24@6594 773
kaf24@6730 774 /*
kaf24@6730 775 * In case of a movs spanning multiple pages, we break the accesses
kaf24@6730 776 * up into multiple pages (the device model works with non-continguous
kaf24@6730 777 * physical guest pages). To copy just one page, we adjust %ecx and
kaf24@6730 778 * do not advance %eip so that the next "rep movs" copies the next page.
kaf24@6730 779 * Unaligned accesses, for example movsl starting at PGSZ-2, are
kaf24@6730 780 * turned into a single copy where we handle the overlapping memory
kaf24@6730 781 * copy ourself. After this copy succeeds, "rep movs" is executed
kaf24@6730 782 * again.
kaf24@6730 783 */
kaf24@6730 784 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
kaf24@6730 785 unsigned long value = 0;
kaf24@6594 786
kaf24@6730 787 mpcip->flags |= OVERLAP;
kaf24@6594 788
kaf24@6730 789 regs->eip -= inst_len; /* do not advance %eip */
kaf24@6594 790
kaf24@6730 791 if (dir == IOREQ_WRITE)
kaf24@6730 792 vmx_copy(&value, addr, size, VMX_COPY_IN);
kaf24@6730 793 send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
kaf24@6730 794 } else {
kaf24@6730 795 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
kaf24@6730 796 regs->eip -= inst_len; /* do not advance %eip */
kaf24@6594 797
kaf24@6730 798 if (sign > 0)
kaf24@6730 799 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
kaf24@6730 800 else
kaf24@6730 801 count = (addr & ~PAGE_MASK) / size;
kaf24@6730 802 }
kaf24@6594 803
kaf24@6730 804 send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
kaf24@6730 805 }
kaf24@6594 806 break;
iap10@3569 807 }
iap10@3569 808
kaf24@6594 809 case INSTR_MOVZ:
kaf24@6730 810 mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 811 break;
kaf24@6594 812
kaf24@6594 813 case INSTR_STOS:
kaf24@6730 814 /*
kaf24@6730 815 * Since the destination is always in (contiguous) mmio space we don't
kaf24@6730 816 * need to break it up into pages.
kaf24@6730 817 */
kaf24@6730 818 mpcip->flags = mmio_inst.flags;
kaf24@6730 819 mpcip->instr = mmio_inst.instr;
kaf24@6594 820 send_mmio_req(IOREQ_TYPE_COPY, gpa,
kaf24@6730 821 GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
kaf24@6730 822 break;
kaf24@6594 823
kaf24@6594 824 case INSTR_OR:
kaf24@6730 825 mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 826 break;
iap10@3569 827
kaf24@6594 828 case INSTR_AND:
kaf24@6730 829 mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 830 break;
kaf24@6594 831
kaf24@6594 832 case INSTR_XOR:
kaf24@6730 833 mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 834 break;
kaf24@6594 835
kaf24@6594 836 case INSTR_CMP:
kaf24@6730 837 mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 838 break;
kaf24@6594 839
kaf24@6594 840 case INSTR_TEST:
kaf24@6730 841 mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
kaf24@6730 842 break;
kaf24@6594 843
kaf24@6594 844 default:
kaf24@6730 845 printf("Unhandled MMIO instruction\n");
kaf24@6730 846 domain_crash_synchronous();
iap10@3569 847 }
iap10@3569 848 }
iap10@3569 849
mafetter@3717 850 #endif /* CONFIG_VMX */
kaf24@3914 851
kaf24@3914 852 /*
kaf24@3914 853 * Local variables:
kaf24@3914 854 * mode: C
kaf24@3914 855 * c-set-style: "BSD"
kaf24@3914 856 * c-basic-offset: 4
kaf24@3914 857 * tab-width: 4
kaf24@3914 858 * indent-tabs-mode: nil
kaf24@3988 859 * End:
kaf24@3914 860 */