debuggers.hg

annotate xen/arch/x86/vmx_platform.c @ 3680:26a00896163a

bitkeeper revision 1.1159.240.3 (4202bd17uoTYqnlSeqvW9fHjznmCHg)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
author iap10@labyrinth.cl.cam.ac.uk
date Fri Feb 04 00:08:55 2005 +0000 (2005-02-04)
parents d9cdcc864e90 b66cde79fd78
children d3f0465c034e
rev   line source
iap10@3607 1 /*
iap10@3607 2 * vmx_platform.c: handling x86 platform related MMIO instructions
iap10@3607 3 * Copyright (c) 2004, Intel Corporation.
iap10@3607 4 *
iap10@3607 5 * This program is free software; you can redistribute it and/or modify it
iap10@3607 6 * under the terms and conditions of the GNU General Public License,
iap10@3607 7 * version 2, as published by the Free Software Foundation.
iap10@3607 8 *
iap10@3607 9 * This program is distributed in the hope it will be useful, but WITHOUT
iap10@3607 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
iap10@3607 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
iap10@3607 12 * more details.
iap10@3607 13 *
iap10@3607 14 * You should have received a copy of the GNU General Public License along with
iap10@3607 15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
iap10@3607 16 * Place - Suite 330, Boston, MA 02111-1307 USA.
iap10@3607 17 *
iap10@3607 18 */
iap10@3607 19
iap10@3607 20 #include <xen/config.h>
iap10@3607 21 #include <xen/types.h>
iap10@3607 22 #include <xen/mm.h>
iap10@3607 23 #include <asm/shadow.h>
iap10@3607 24 #include <asm/domain_page.h>
iap10@3607 25 #include <asm/page.h>
iap10@3607 26 #include <xen/event.h>
iap10@3607 27 #include <xen/trace.h>
iap10@3607 28 #include <asm/vmx.h>
iap10@3607 29 #include <asm/vmx_platform.h>
iap10@3607 30 #include <public/io/ioreq.h>
iap10@3607 31
iap10@3607 32 #include <xen/lib.h>
iap10@3607 33 #include <xen/sched.h>
iap10@3607 34 #include <asm/current.h>
iap10@3607 35
iap10@3607 36 #define DECODE_success 1
iap10@3607 37 #define DECODE_failure 0
iap10@3607 38
iap10@3607 39 #if defined (__x86_64__)
iap10@3607 40 static void store_xen_regs(struct xen_regs *regs)
iap10@3607 41 {
iap10@3607 42
iap10@3607 43 }
iap10@3607 44
iap10@3607 45 static long get_reg_value(int size, int index, int seg, struct xen_regs *regs)
iap10@3607 46 {
iap10@3607 47 return 0;
iap10@3607 48 }
iap10@3607 49 #elif defined (__i386__)
iap10@3607 50 static void store_xen_regs(struct xen_regs *regs)
iap10@3607 51 {
iap10@3607 52 __vmread(GUEST_SS_SELECTOR, &regs->ss);
iap10@3607 53 __vmread(GUEST_ESP, &regs->esp);
iap10@3607 54 __vmread(GUEST_EFLAGS, &regs->eflags);
iap10@3607 55 __vmread(GUEST_CS_SELECTOR, &regs->cs);
iap10@3607 56 __vmread(GUEST_EIP, &regs->eip);
iap10@3607 57 }
iap10@3607 58
iap10@3607 59 static long get_reg_value(int size, int index, int seg, struct xen_regs *regs)
iap10@3607 60 {
iap10@3607 61 /*
iap10@3607 62 * Reference the db_reg[] table
iap10@3607 63 */
iap10@3607 64 switch (size) {
iap10@3607 65 case BYTE:
iap10@3607 66 switch (index) {
iap10@3607 67 case 0: //%al
iap10@3607 68 return (char)(regs->eax & 0xFF);
iap10@3607 69 case 1: //%cl
iap10@3607 70 return (char)(regs->ecx & 0xFF);
iap10@3607 71 case 2: //%dl
iap10@3607 72 return (char)(regs->edx & 0xFF);
iap10@3607 73 case 3: //%bl
iap10@3607 74 return (char)(regs->ebx & 0xFF);
iap10@3607 75 case 4: //%ah
iap10@3607 76 return (char)((regs->eax & 0xFF00) >> 8);
iap10@3607 77 case 5: //%ch
iap10@3607 78 return (char)((regs->ecx & 0xFF00) >> 8);
iap10@3607 79 case 6: //%dh
iap10@3607 80 return (char)((regs->edx & 0xFF00) >> 8);
iap10@3607 81 case 7: //%bh
iap10@3607 82 return (char)((regs->ebx & 0xFF00) >> 8);
iap10@3607 83 default:
iap10@3607 84 printk("(get_reg_value)size case 0 error\n");
iap10@3607 85 return -1;
iap10@3607 86 }
iap10@3607 87 case WORD:
iap10@3607 88 switch (index) {
iap10@3607 89 case 0: //%ax
iap10@3607 90 return (short)(regs->eax & 0xFFFF);
iap10@3607 91 case 1: //%cx
iap10@3607 92 return (short)(regs->ecx & 0xFFFF);
iap10@3607 93 case 2: //%dx
iap10@3607 94 return (short)(regs->edx & 0xFFFF);
iap10@3607 95 case 3: //%bx
iap10@3607 96 return (short)(regs->ebx & 0xFFFF);
iap10@3607 97 case 4: //%sp
iap10@3607 98 return (short)(regs->esp & 0xFFFF);
iap10@3607 99 break;
iap10@3607 100 case 5: //%bp
iap10@3607 101 return (short)(regs->ebp & 0xFFFF);
iap10@3607 102 case 6: //%si
iap10@3607 103 return (short)(regs->esi & 0xFFFF);
iap10@3607 104 case 7: //%di
iap10@3607 105 return (short)(regs->edi & 0xFFFF);
iap10@3607 106 default:
iap10@3607 107 printk("(get_reg_value)size case 1 error\n");
iap10@3607 108 return -1;
iap10@3607 109 }
iap10@3607 110 case LONG:
iap10@3607 111 switch (index) {
iap10@3607 112 case 0: //%eax
iap10@3607 113 return regs->eax;
iap10@3607 114 case 1: //%ecx
iap10@3607 115 return regs->ecx;
iap10@3607 116 case 2: //%edx
iap10@3607 117 return regs->edx;
iap10@3607 118
iap10@3607 119 case 3: //%ebx
iap10@3607 120 return regs->ebx;
iap10@3607 121 case 4: //%esp
iap10@3607 122 return regs->esp;
iap10@3607 123 case 5: //%ebp
iap10@3607 124 return regs->ebp;
iap10@3607 125 case 6: //%esi
iap10@3607 126 return regs->esi;
iap10@3607 127 case 7: //%edi
iap10@3607 128 return regs->edi;
iap10@3607 129 default:
iap10@3607 130 printk("(get_reg_value)size case 2 error\n");
iap10@3607 131 return -1;
iap10@3607 132 }
iap10@3607 133 default:
iap10@3607 134 printk("(get_reg_value)size case error\n");
iap10@3607 135 return -1;
iap10@3607 136 }
iap10@3607 137 }
iap10@3607 138 #endif
iap10@3607 139
iap10@3607 140 static inline unsigned char *check_prefix(unsigned char *inst, struct instruction *thread_inst)
iap10@3607 141 {
iap10@3607 142 while (1) {
iap10@3607 143 switch (*inst) {
iap10@3607 144 case 0xf3: //REPZ
iap10@3607 145 case 0xf2: //REPNZ
iap10@3607 146 case 0xf0: //LOCK
iap10@3607 147 case 0x2e: //CS
iap10@3607 148 case 0x36: //SS
iap10@3607 149 case 0x3e: //DS
iap10@3607 150 case 0x26: //ES
iap10@3607 151 case 0x64: //FS
iap10@3607 152 case 0x65: //GS
iap10@3607 153 break;
iap10@3607 154 case 0x66: //32bit->16bit
iap10@3607 155 thread_inst->op_size = WORD;
iap10@3607 156 break;
iap10@3607 157 case 0x67:
iap10@3607 158 break;
iap10@3607 159 default:
iap10@3607 160 return inst;
iap10@3607 161 }
iap10@3607 162 inst++;
iap10@3607 163 }
iap10@3607 164 }
iap10@3607 165
iap10@3607 166 static inline unsigned long get_immediate(const unsigned char *inst, int op_size)
iap10@3607 167 {
iap10@3607 168 int mod, reg, rm;
iap10@3607 169 unsigned long val = 0;
iap10@3607 170 int i;
iap10@3607 171
iap10@3607 172 mod = (*inst >> 6) & 3;
iap10@3607 173 reg = (*inst >> 3) & 7;
iap10@3607 174 rm = *inst & 7;
iap10@3607 175
iap10@3607 176 inst++; //skip ModR/M byte
iap10@3607 177 if (mod != 3 && rm == 4) {
iap10@3607 178 inst++; //skip SIB byte
iap10@3607 179 }
iap10@3607 180
iap10@3607 181 switch(mod) {
iap10@3607 182 case 0:
iap10@3607 183 if (rm == 5) {
iap10@3607 184 inst = inst + 4; //disp32, skip 4 bytes
iap10@3607 185 }
iap10@3607 186 break;
iap10@3607 187 case 1:
iap10@3607 188 inst++; //disp8, skip 1 byte
iap10@3607 189 break;
iap10@3607 190 case 2:
iap10@3607 191 inst = inst + 4; //disp32, skip 4 bytes
iap10@3607 192 }
iap10@3607 193 for (i = 0; i < op_size; i++) {
iap10@3607 194 val |= (*inst++ & 0xff) << (8 * i);
iap10@3607 195 }
iap10@3607 196
iap10@3607 197 return val;
iap10@3607 198 }
iap10@3607 199
iap10@3607 200 static inline int get_index(const unsigned char *inst)
iap10@3607 201 {
iap10@3607 202 int mod, reg, rm;
iap10@3607 203
iap10@3607 204 mod = (*inst >> 6) & 3;
iap10@3607 205 reg = (*inst >> 3) & 7;
iap10@3607 206 rm = *inst & 7;
iap10@3607 207
iap10@3607 208 //Only one operand in the instruction is register
iap10@3607 209 if (mod == 3) {
iap10@3607 210 return rm;
iap10@3607 211 } else {
iap10@3607 212 return reg;
iap10@3607 213 }
iap10@3607 214 return 0;
iap10@3607 215 }
iap10@3607 216
iap10@3607 217 static int vmx_decode(const unsigned char *inst, struct instruction *thread_inst)
iap10@3607 218 {
iap10@3607 219 int index;
iap10@3607 220
iap10@3607 221 switch(*inst) {
iap10@3607 222 case 0x88:
iap10@3607 223 /* mov r8 to m8 */
iap10@3607 224 thread_inst->op_size = BYTE;
iap10@3607 225 index = get_index((inst + 1));
iap10@3607 226 thread_inst->operand[0] = mk_operand(BYTE, index, 0, REGISTER);
iap10@3607 227 break;
iap10@3607 228 case 0x89:
iap10@3607 229 /* mov r32/16 to m32/16 */
iap10@3607 230 index = get_index((inst + 1));
iap10@3607 231 if (thread_inst->op_size == WORD) {
iap10@3607 232 thread_inst->operand[0] = mk_operand(WORD, index, 0, REGISTER);
iap10@3607 233 } else {
iap10@3607 234 thread_inst->op_size = LONG;
iap10@3607 235 thread_inst->operand[0] = mk_operand(LONG, index, 0, REGISTER);
iap10@3607 236 }
iap10@3607 237 break;
iap10@3607 238 case 0x8a:
iap10@3607 239 /* mov m8 to r8 */
iap10@3607 240 thread_inst->op_size = BYTE;
iap10@3607 241 index = get_index((inst + 1));
iap10@3607 242 thread_inst->operand[1] = mk_operand(BYTE, index, 0, REGISTER);
iap10@3607 243 break;
iap10@3607 244 case 0x8b:
iap10@3607 245 /* mov r32/16 to m32/16 */
iap10@3607 246 index = get_index((inst + 1));
iap10@3607 247 if (thread_inst->op_size == WORD) {
iap10@3607 248 thread_inst->operand[1] = mk_operand(WORD, index, 0, REGISTER);
iap10@3607 249 } else {
iap10@3607 250 thread_inst->op_size = LONG;
iap10@3607 251 thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER);
iap10@3607 252 }
iap10@3607 253 break;
iap10@3607 254 case 0x8c:
iap10@3607 255 case 0x8e:
iap10@3607 256 printk("%x, This opcode hasn't been handled yet!", *inst);
iap10@3607 257 return DECODE_failure;
iap10@3607 258 /* Not handle it yet. */
iap10@3607 259
iap10@3607 260 case 0xa0:
iap10@3607 261 /* mov byte to al */
iap10@3607 262 thread_inst->op_size = BYTE;
iap10@3607 263 thread_inst->operand[1] = mk_operand(BYTE, 0, 0, REGISTER);
iap10@3607 264 break;
iap10@3607 265 case 0xa1:
iap10@3607 266 /* mov word/doubleword to ax/eax */
iap10@3607 267 if (thread_inst->op_size == WORD) {
iap10@3607 268 thread_inst->operand[1] = mk_operand(WORD, 0, 0, REGISTER);
iap10@3607 269 } else {
iap10@3607 270 thread_inst->op_size = LONG;
iap10@3607 271 thread_inst->operand[1] = mk_operand(LONG, 0, 0, REGISTER);
iap10@3607 272 }
iap10@3607 273 break;
iap10@3607 274 case 0xa2:
iap10@3607 275 /* mov al to (seg:offset) */
iap10@3607 276 thread_inst->op_size = BYTE;
iap10@3607 277 thread_inst->operand[0] = mk_operand(BYTE, 0, 0, REGISTER);
iap10@3607 278 break;
iap10@3607 279 case 0xa3:
iap10@3607 280 /* mov ax/eax to (seg:offset) */
iap10@3607 281 if (thread_inst->op_size == WORD) {
iap10@3607 282 thread_inst->operand[0] = mk_operand(WORD, 0, 0, REGISTER);
iap10@3607 283 } else {
iap10@3607 284 thread_inst->op_size = LONG;
iap10@3607 285 thread_inst->operand[0] = mk_operand(LONG, 0, 0, REGISTER);
iap10@3607 286 }
iap10@3607 287 break;
iap10@3607 288 case 0xa4:
iap10@3607 289 /* movsb */
iap10@3607 290 thread_inst->op_size = BYTE;
iap10@3607 291 strcpy(thread_inst->i_name, "movs");
iap10@3607 292
iap10@3607 293 return DECODE_success;
iap10@3607 294 case 0xa5:
iap10@3607 295 /* movsw/movsl */
iap10@3607 296 if (thread_inst->op_size == WORD) {
iap10@3607 297 } else {
iap10@3607 298 thread_inst->op_size = LONG;
iap10@3607 299 }
iap10@3607 300
iap10@3607 301 strcpy(thread_inst->i_name, "movs");
iap10@3607 302
iap10@3607 303 return DECODE_success;
iap10@3607 304
iap10@3607 305 case 0xc6:
iap10@3607 306 /* mov imm8 to m8 */
iap10@3607 307 thread_inst->op_size = BYTE;
iap10@3607 308 thread_inst->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
iap10@3607 309 thread_inst->immediate = get_immediate((inst+1), thread_inst->op_size);
iap10@3607 310 break;
iap10@3607 311 case 0xc7:
iap10@3607 312 /* mov imm16/32 to m16/32 */
iap10@3607 313 if (thread_inst->op_size == WORD) {
iap10@3607 314 thread_inst->operand[0] = mk_operand(WORD, 0, 0, IMMEDIATE);
iap10@3607 315 } else {
iap10@3607 316 thread_inst->op_size = LONG;
iap10@3607 317 thread_inst->operand[0] = mk_operand(LONG, 0, 0, IMMEDIATE);
iap10@3607 318 }
iap10@3607 319 thread_inst->immediate = get_immediate((inst+1), thread_inst->op_size);
iap10@3607 320 break;
iap10@3607 321
iap10@3607 322 case 0x0f:
iap10@3607 323 break;
iap10@3607 324 default:
iap10@3607 325 printk("%x, This opcode hasn't been handled yet!", *inst);
iap10@3607 326 return DECODE_failure;
iap10@3607 327 }
iap10@3607 328
iap10@3607 329 strcpy(thread_inst->i_name, "mov");
iap10@3607 330 if (*inst != 0x0f) {
iap10@3607 331 return DECODE_success;
iap10@3607 332 }
iap10@3607 333
iap10@3607 334 inst++;
iap10@3607 335 switch (*inst) {
iap10@3607 336
iap10@3607 337 /* movz */
iap10@3607 338 case 0xb7:
iap10@3607 339 index = get_index((inst + 1));
iap10@3607 340 thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER);
iap10@3607 341 strcpy(thread_inst->i_name, "movzw");
iap10@3607 342
iap10@3607 343 return DECODE_success;
iap10@3607 344 default:
iap10@3607 345 printk("0f %x, This opcode hasn't been handled yet!", *inst);
iap10@3607 346 return DECODE_failure;
iap10@3607 347 }
iap10@3607 348
iap10@3607 349 /* will never reach here */
iap10@3607 350 return DECODE_failure;
iap10@3607 351 }
iap10@3607 352
iap10@3607 353 static int inst_copy_from_guest(char *buf, unsigned long guest_eip, int inst_len)
iap10@3607 354 {
iap10@3607 355 unsigned long gpte;
iap10@3607 356 unsigned long mfn;
iap10@3607 357 unsigned long ma;
iap10@3607 358 unsigned char * inst_start;
iap10@3607 359
iap10@3607 360 if (inst_len > MAX_INST_LEN || inst_len <= 0) {
iap10@3607 361 return 0;
iap10@3607 362 }
iap10@3607 363
iap10@3607 364 if ((guest_eip & PAGE_MASK) == ((guest_eip + inst_len) & PAGE_MASK)) {
iap10@3607 365 if ( unlikely(__get_user(gpte, (unsigned long *)
iap10@3607 366 &linear_pg_table[guest_eip >> PAGE_SHIFT])) )
iap10@3607 367 {
iap10@3607 368 printk("inst_copy_from_guest- EXIT: read gpte faulted" );
iap10@3607 369 return 0;
iap10@3607 370 }
iap10@3607 371 mfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT];
iap10@3607 372 ma = (mfn << PAGE_SHIFT) | (guest_eip & (PAGE_SIZE - 1));
iap10@3607 373 inst_start = (unsigned char *)map_domain_mem(ma);
iap10@3607 374
iap10@3679 375 memcpy(buf, inst_start, inst_len);
iap10@3607 376 unmap_domain_mem(inst_start);
iap10@3607 377 } else {
iap10@3607 378 // Todo: In two page frames
iap10@3607 379 }
iap10@3607 380
iap10@3607 381 return inst_len;
iap10@3607 382 }
iap10@3607 383
iap10@3607 384 static void init_instruction(struct instruction *mmio_inst)
iap10@3607 385 {
iap10@3607 386 memset(mmio_inst->i_name, '0', I_NAME_LEN);
iap10@3607 387 mmio_inst->op_size = 0;
iap10@3607 388 mmio_inst->offset = 0;
iap10@3607 389 mmio_inst->immediate = 0;
iap10@3607 390 mmio_inst->seg_sel = 0;
iap10@3607 391 mmio_inst->op_num = 0;
iap10@3607 392
iap10@3607 393 mmio_inst->operand[0] = 0;
iap10@3607 394 mmio_inst->operand[1] = 0;
iap10@3607 395 mmio_inst->operand[2] = 0;
iap10@3607 396
iap10@3607 397 mmio_inst->flags = 0;
iap10@3607 398 }
iap10@3607 399
iap10@3607 400 static int read_from_mmio(struct instruction *inst_p)
iap10@3607 401 {
iap10@3607 402 // Only for mov instruction now!!!
iap10@3607 403 if (inst_p->operand[1] & REGISTER)
iap10@3607 404 return 1;
iap10@3607 405
iap10@3607 406 return 0;
iap10@3607 407 }
iap10@3607 408
iap10@3607 409 // dir: 1 read from mmio
iap10@3607 410 // 0 write to mmio
iap10@3607 411 static void send_mmio_req(unsigned long gpa,
iap10@3607 412 struct instruction *inst_p, long value, int dir, int pvalid)
iap10@3607 413 {
iap10@3607 414 struct exec_domain *d = current;
iap10@3607 415 vcpu_iodata_t *vio;
iap10@3607 416 ioreq_t *p;
iap10@3607 417 struct mi_per_cpu_info *mpci_p;
iap10@3607 418 struct xen_regs *inst_decoder_regs;
iap10@3607 419 extern inline unsigned long gva_to_gpa(unsigned long gva);
iap10@3607 420 extern long evtchn_send(int lport);
iap10@3607 421 extern long do_block(void);
iap10@3607 422
iap10@3607 423 mpci_p = &current->thread.arch_vmx.vmx_platform.mpci;
iap10@3607 424 inst_decoder_regs = mpci_p->inst_decoder_regs;
iap10@3607 425 vio = (vcpu_iodata_t *) d->thread.arch_vmx.vmx_platform.shared_page_va;
iap10@3607 426
iap10@3607 427 if (vio == NULL) {
iap10@3607 428 printk("bad shared page\n");
iap10@3607 429 domain_crash();
iap10@3607 430 }
iap10@3607 431 p = &vio->vp_ioreq;
iap10@3607 432
iap10@3607 433 set_bit(ARCH_VMX_IO_WAIT, &d->thread.arch_vmx.flags);
iap10@3607 434 p->dir = dir;
iap10@3607 435 p->pdata_valid = pvalid;
iap10@3607 436 p->count = 1;
iap10@3607 437
iap10@3607 438 p->port_mm = 1;
iap10@3607 439 p->size = inst_p->op_size;
iap10@3607 440 p->addr = gpa;
iap10@3607 441 p->u.data = value;
iap10@3607 442
iap10@3607 443 // p->state = STATE_UPSTREAM_SENDING;
iap10@3607 444 p->state = STATE_IOREQ_READY;
iap10@3607 445
iap10@3607 446 // Try to use ins/outs' framework
iap10@3607 447 if (pvalid) {
iap10@3607 448 // Handle "movs"
iap10@3607 449 p->u.pdata = (void *) ((p->dir == IOREQ_WRITE) ?
iap10@3607 450 inst_decoder_regs->esi
iap10@3607 451 : inst_decoder_regs->edi);
iap10@3607 452 p->u.pdata = (void *) gva_to_gpa(p->u.data);
iap10@3607 453 p->count = inst_decoder_regs->ecx;
iap10@3607 454 inst_decoder_regs->ecx = 0;
iap10@3607 455 p->df = (inst_decoder_regs->eflags & EF_DF) ? 1 : 0;
iap10@3607 456 }
iap10@3607 457
iap10@3607 458 evtchn_send(IOPACKET_PORT);
iap10@3607 459 do_block();
iap10@3607 460
iap10@3607 461 }
iap10@3607 462
iap10@3607 463 void handle_mmio(unsigned long va, unsigned long gpte, unsigned long gpa)
iap10@3607 464 {
iap10@3607 465 unsigned long eip;
iap10@3607 466 unsigned long inst_len;
iap10@3607 467 struct mi_per_cpu_info *mpci_p;
iap10@3607 468 struct xen_regs *inst_decoder_regs;
iap10@3607 469 struct instruction mmio_inst;
iap10@3607 470 unsigned char inst[MAX_INST_LEN];
iap10@3607 471 int ret;
iap10@3607 472
iap10@3607 473 mpci_p = &current->thread.arch_vmx.vmx_platform.mpci;
iap10@3607 474 inst_decoder_regs = mpci_p->inst_decoder_regs;
iap10@3607 475
iap10@3607 476 __vmread(GUEST_EIP, &eip);
iap10@3607 477 __vmread(INSTRUCTION_LEN, &inst_len);
iap10@3607 478
iap10@3607 479 memset(inst, '0', MAX_INST_LEN);
iap10@3607 480 ret = inst_copy_from_guest(inst, eip, inst_len);
iap10@3607 481 if (ret != inst_len) {
iap10@3607 482 printk("handle_mmio - EXIT: get guest instruction fault\n");
iap10@3607 483 domain_crash();
iap10@3607 484 }
iap10@3607 485
iap10@3607 486 init_instruction(&mmio_inst);
iap10@3607 487
iap10@3607 488 if (vmx_decode(check_prefix(inst, &mmio_inst), &mmio_inst) == DECODE_failure)
iap10@3607 489 domain_crash();
iap10@3607 490
iap10@3607 491 __vmwrite(GUEST_EIP, eip + inst_len);
iap10@3607 492 store_xen_regs(inst_decoder_regs);
iap10@3607 493
iap10@3607 494 // Only handle "mov" and "movs" instructions!
iap10@3607 495 if (!strncmp(mmio_inst.i_name, "movzw", 5)) {
iap10@3607 496 long value = 0;
iap10@3607 497 int index;
iap10@3607 498
iap10@3607 499 if (read_from_mmio(&mmio_inst)) {
iap10@3607 500 // Send the request and waiting for return value.
iap10@3607 501 mpci_p->mmio_target = mmio_inst.operand[1] | WZEROEXTEND;
iap10@3607 502 mmio_inst.op_size = WORD;
iap10@3607 503 send_mmio_req(gpa, &mmio_inst, value, 1, 0);
iap10@3607 504 } else {
iap10@3607 505 // Write to MMIO
iap10@3607 506 if (mmio_inst.operand[0] & IMMEDIATE) {
iap10@3607 507 value = mmio_inst.immediate;
iap10@3607 508 } else if (mmio_inst.operand[0] & REGISTER) {
iap10@3607 509 index = operand_index(mmio_inst.operand[0]);
iap10@3607 510 value = get_reg_value(WORD, index, 0, inst_decoder_regs);
iap10@3607 511 } else {
iap10@3607 512 domain_crash();
iap10@3607 513 }
iap10@3607 514 mmio_inst.op_size = WORD;
iap10@3607 515 send_mmio_req(gpa, &mmio_inst, value, 0, 0);
iap10@3607 516 return;
iap10@3607 517 }
iap10@3607 518 }
iap10@3607 519
iap10@3607 520 if (!strncmp(mmio_inst.i_name, "movs", 4)) {
iap10@3607 521 int tmp_dir;
iap10@3607 522
iap10@3607 523 tmp_dir = ((va == inst_decoder_regs->edi) ? IOREQ_WRITE : IOREQ_READ);
iap10@3607 524 send_mmio_req(gpa, &mmio_inst, 0, tmp_dir, 1);
iap10@3607 525 return;
iap10@3607 526 }
iap10@3607 527
iap10@3607 528 if (!strncmp(mmio_inst.i_name, "mov", 3)) {
iap10@3607 529 long value = 0;
iap10@3607 530 int size, index;
iap10@3607 531
iap10@3607 532 if (read_from_mmio(&mmio_inst)) {
iap10@3607 533 // Send the request and waiting for return value.
iap10@3607 534 mpci_p->mmio_target = mmio_inst.operand[1];
iap10@3607 535 send_mmio_req(gpa, &mmio_inst, value, 1, 0);
iap10@3607 536 } else {
iap10@3607 537 // Write to MMIO
iap10@3607 538 if (mmio_inst.operand[0] & IMMEDIATE) {
iap10@3607 539 value = mmio_inst.immediate;
iap10@3607 540 } else if (mmio_inst.operand[0] & REGISTER) {
iap10@3607 541 size = operand_size(mmio_inst.operand[0]);
iap10@3607 542 index = operand_index(mmio_inst.operand[0]);
iap10@3607 543 value = get_reg_value(size, index, 0, inst_decoder_regs);
iap10@3607 544 } else {
iap10@3607 545 domain_crash();
iap10@3607 546 }
iap10@3607 547 send_mmio_req(gpa, &mmio_inst, value, 0, 0);
iap10@3607 548 return;
iap10@3607 549 }
iap10@3607 550 domain_crash();
iap10@3607 551 }
iap10@3607 552 domain_crash();
iap10@3607 553 }
iap10@3607 554