[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Attached is the patch with
ChangeSet 1.1737, 2005/06/23 10:52:50+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx Attached is the patch with 1. Cleanup of code & correct error handling for MMIO instructions. 2. Decoding of 64bit instructions for MMIO. Signed-Off-By: Chengyuan Li <chengyuan.li@xxxxxxxxx> Signed-Off-By: Yunhong Jiang <hunhong.jiang@xxxxxxxxx> Signed-Off-By: Jun Nakajima <jun.nakajima@xxxxxxxxx> Signed-Off-By: Nitin A Kamble <nitin.a.kamble@xxxxxxxxx> tools/ioemu/exec.c | 3 xen/arch/x86/vmx_io.c | 148 +++++++++++++++++- xen/arch/x86/vmx_platform.c | 291 +++++++++++++++++++++++-------------- xen/include/asm-x86/vmx_platform.h | 1 4 files changed, 323 insertions(+), 120 deletions(-) diff -Nru a/tools/ioemu/exec.c b/tools/ioemu/exec.c --- a/tools/ioemu/exec.c 2005-06-23 07:06:07 -04:00 +++ b/tools/ioemu/exec.c 2005-06-23 07:06:07 -04:00 @@ -386,6 +386,9 @@ io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val); l = 2; } else { + if (l!=1){ + fprintf(logfile, "ERROR 8 bit mmio\n"); + } /* 8 bit access */ val = ldub_raw(buf); io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); diff -Nru a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c --- a/xen/arch/x86/vmx_io.c 2005-06-23 07:06:07 -04:00 +++ b/xen/arch/x86/vmx_io.c 2005-06-23 07:06:07 -04:00 @@ -86,7 +86,8 @@ regs->ebx |= ((value & 0xFF) << 8); break; default: - printk("size:%x, index:%x are invalid!\n", size, index); + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); break; } @@ -127,7 +128,8 @@ regs->edi |= (value & 0xFFFF); break; default: - printk("size:%x, index:%x are invalid!\n", size, index); + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); break; } break; @@ -158,25 +160,150 @@ regs->edi = value; break; default: - printk("size:%x, index:%x are invalid!\n", size, index); + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); break; } break; default: - printk("size:%x, index:%x are invalid!\n", size, index); + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); break; } } #else static void load_cpu_user_regs(struct cpu_user_regs *regs) -{ - /* XXX: TBD */ - return; +{ + __vmwrite(GUEST_SS_SELECTOR, regs->ss); + __vmwrite(GUEST_RSP, regs->rsp); + __vmwrite(GUEST_RFLAGS, regs->rflags); + __vmwrite(GUEST_CS_SELECTOR, regs->cs); + __vmwrite(GUEST_RIP, regs->rip); +} + +static inline void __set_reg_value(long *reg, int size, long value) +{ + switch (size) { + case BYTE_64: + *reg &= ~0xFF; + *reg |= (value & 0xFF); + break; + case WORD: + *reg &= ~0xFFFF; + *reg |= (value & 0xFFFF); + break; + + case LONG: + *reg &= ~0xFFFFFFFF; + *reg |= (value & 0xFFFFFFFF); + break; + case QUAD: + *reg = value; + break; + default: + printk("Error: <__set_reg_value> : Unknown size for register\n"); + domain_crash_synchronous(); + } } + static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value) { - /* XXX: TBD */ - return; + if (size == BYTE) { + switch (index) { + case 0: + regs->rax &= ~0xFF; + regs->rax |= (value & 0xFF); + break; + case 1: + regs->rcx &= ~0xFF; + regs->rcx |= (value & 0xFF); + break; + case 2: + regs->rdx &= ~0xFF; + regs->rdx |= (value & 0xFF); + break; + case 3: + regs->rbx &= ~0xFF; + regs->rbx |= (value & 0xFF); + break; + case 4: + regs->rax &= 0xFFFFFFFFFFFF00FF; + regs->rax |= ((value & 0xFF) << 8); + break; + case 5: + regs->rcx &= 0xFFFFFFFFFFFF00FF; + regs->rcx |= ((value & 0xFF) << 8); + break; + case 6: + regs->rdx &= 0xFFFFFFFFFFFF00FF; + regs->rdx |= ((value & 0xFF) << 8); + break; + case 7: + regs->rbx &= 0xFFFFFFFFFFFF00FF; + regs->rbx |= ((value & 0xFF) << 8); + break; + default: + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); + break; + } + + } + + switch (index) { + case 0: + __set_reg_value(®s->rax, size, value); + break; + case 1: + __set_reg_value(®s->rcx, size, value); + break; + case 2: + __set_reg_value(®s->rdx, size, value); + break; + case 3: + __set_reg_value(®s->rbx, size, value); + break; + case 4: + __set_reg_value(®s->rsp, size, value); + break; + case 5: + __set_reg_value(®s->rbp, size, value); + break; + case 6: + __set_reg_value(®s->rsi, size, value); + break; + case 7: + __set_reg_value(®s->rdi, size, value); + break; + case 8: + __set_reg_value(®s->r8, size, value); + break; + case 9: + __set_reg_value(®s->r9, size, value); + break; + case 10: + __set_reg_value(®s->r10, size, value); + break; + case 11: + __set_reg_value(®s->r11, size, value); + break; + case 12: + __set_reg_value(®s->r12, size, value); + break; + case 13: + __set_reg_value(®s->r13, size, value); + break; + case 14: + __set_reg_value(®s->r14, size, value); + break; + case 15: + __set_reg_value(®s->r15, size, value); + break; + default: + printk("Error: <set_reg_value> Invalid index\n"); + domain_crash_synchronous(); + } + return; } #endif @@ -269,7 +396,8 @@ regs->eax = (p->u.data & 0xffffffff); break; default: - BUG(); + printk("Error: %s unknwon port size\n", __FUNCTION__); + domain_crash_synchronous(); } } diff -Nru a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c --- a/xen/arch/x86/vmx_platform.c 2005-06-23 07:06:07 -04:00 +++ b/xen/arch/x86/vmx_platform.c 2005-06-23 07:06:07 -04:00 @@ -41,12 +41,79 @@ #if defined (__x86_64__) void store_cpu_user_regs(struct cpu_user_regs *regs) { + __vmread(GUEST_SS_SELECTOR, ®s->ss); + __vmread(GUEST_RSP, ®s->rsp); + __vmread(GUEST_RFLAGS, ®s->rflags); + __vmread(GUEST_CS_SELECTOR, ®s->cs); + __vmread(GUEST_DS_SELECTOR, ®s->ds); + __vmread(GUEST_ES_SELECTOR, ®s->es); + __vmread(GUEST_RIP, ®s->rip); +} +static inline long __get_reg_value(unsigned long reg, int size) +{ + switch(size) { + case BYTE_64: + return (char)(reg & 0xFF); + case WORD: + return (short)(reg & 0xFFFF); + case LONG: + return (int)(reg & 0xFFFFFFFF); + case QUAD: + return (long)(reg); + default: + printk("Error: <__get_reg_value>Invalid reg size\n"); + domain_crash_synchronous(); + } } static long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) { - return 0; + if (size == BYTE) { + switch (index) { + case 0: //%al + return (char)(regs->rax & 0xFF); + case 1: //%cl + return (char)(regs->rcx & 0xFF); + case 2: //%dl + return (char)(regs->rdx & 0xFF); + case 3: //%bl + return (char)(regs->rbx & 0xFF); + case 4: //%ah + return (char)((regs->rax & 0xFF00) >> 8); + case 5: //%ch + return (char)((regs->rcx & 0xFF00) >> 8); + case 6: //%dh + return (char)((regs->rdx & 0xFF00) >> 8); + case 7: //%bh + return (char)((regs->rbx & 0xFF00) >> 8); + default: + printk("Error: (get_reg_value)Invalid index value\n"); + domain_crash_synchronous(); + } + + } + switch (index) { + case 0: return __get_reg_value(regs->rax, size); + case 1: return __get_reg_value(regs->rcx, size); + case 2: return __get_reg_value(regs->rdx, size); + case 3: return __get_reg_value(regs->rbx, size); + case 4: return __get_reg_value(regs->rsp, size); + case 5: return __get_reg_value(regs->rbp, size); + case 6: return __get_reg_value(regs->rsi, size); + case 7: return __get_reg_value(regs->rdi, size); + case 8: return __get_reg_value(regs->r8, size); + case 9: return __get_reg_value(regs->r9, size); + case 10: return __get_reg_value(regs->r10, size); + case 11: return __get_reg_value(regs->r11, size); + case 12: return __get_reg_value(regs->r12, size); + case 13: return __get_reg_value(regs->r13, size); + case 14: return __get_reg_value(regs->r14, size); + case 15: return __get_reg_value(regs->r15, size); + default: + printk("Error: (get_reg_value)Invalid index value\n"); + domain_crash_synchronous(); + } } #elif defined (__i386__) void store_cpu_user_regs(struct cpu_user_regs *regs) @@ -85,8 +152,8 @@ case 7: //%bh return (char)((regs->ebx & 0xFF00) >> 8); default: - printk("(get_reg_value)size case 0 error\n"); - return -1; + printk("Error: (get_reg_value)size case 0 error\n"); + domain_crash_synchronous(); } case WORD: switch (index) { @@ -108,8 +175,8 @@ case 7: //%di return (short)(regs->edi & 0xFFFF); default: - printk("(get_reg_value)size case 1 error\n"); - return -1; + printk("Error: (get_reg_value)size case 1 error\n"); + domain_crash_synchronous(); } case LONG: switch (index) { @@ -131,42 +198,47 @@ case 7: //%edi return regs->edi; default: - printk("(get_reg_value)size case 2 error\n"); - return -1; + printk("Error: (get_reg_value)size case 2 error\n"); + domain_crash_synchronous(); } default: - printk("(get_reg_value)size case error\n"); - return -1; + printk("Error: (get_reg_value)size case error\n"); + domain_crash_synchronous(); } } #endif -static inline unsigned char *check_prefix(unsigned char *inst, struct instruction *thread_inst) +static inline const unsigned char *check_prefix(const unsigned char *inst, struct instruction *thread_inst, unsigned char *rex_p) { while (1) { switch (*inst) { + /* rex prefix for em64t instructions*/ + case 0x40 ... 0x4e: + *rex_p = *inst; + break; + case 0xf3: //REPZ - thread_inst->flags = REPZ; - break; + thread_inst->flags = REPZ; + break; case 0xf2: //REPNZ - thread_inst->flags = REPNZ; - break; + thread_inst->flags = REPNZ; + break; case 0xf0: //LOCK - break; + break; case 0x2e: //CS case 0x36: //SS case 0x3e: //DS case 0x26: //ES case 0x64: //FS case 0x65: //GS - thread_inst->seg_sel = *inst; + thread_inst->seg_sel = *inst; break; case 0x66: //32bit->16bit thread_inst->op_size = WORD; break; case 0x67: - printf("Not handling 0x67 (yet)\n"); - domain_crash_synchronous(); + printf("Error: Not handling 0x67 (yet)\n"); + domain_crash_synchronous(); break; default: return inst; @@ -193,9 +265,9 @@ switch(mod) { case 0: if (rm == 5) { - if (op16) + if (op16) inst = inst + 2; //disp16, skip 2 bytes - else + else inst = inst + 4; //disp32, skip 4 bytes } break; @@ -203,44 +275,81 @@ inst++; //disp8, skip 1 byte break; case 2: - if (op16) + if (op16) inst = inst + 2; //disp16, skip 2 bytes - else + else inst = inst + 4; //disp32, skip 4 bytes break; } + + if (op_size == QUAD) + op_size = LONG; + for (i = 0; i < op_size; i++) { val |= (*inst++ & 0xff) << (8 * i); } - + return val; } -static inline int get_index(const unsigned char *inst) +static inline int get_index(const unsigned char *inst, unsigned char rex) { int mod, reg, rm; + int rex_r, rex_b; mod = (*inst >> 6) & 3; reg = (*inst >> 3) & 7; rm = *inst & 7; + rex_r = (rex >> 2) & 1; + rex_b = rex & 1; + //Only one operand in the instruction is register if (mod == 3) { - return rm; + return (rm + (rex_b << 3)); } else { - return reg; + return (reg + (rex_r << 3)); } return 0; } +static void init_instruction(struct instruction *mmio_inst) +{ + memset(mmio_inst->i_name, '0', I_NAME_LEN); + mmio_inst->op_size = 0; + mmio_inst->offset = 0; + mmio_inst->immediate = 0; + mmio_inst->seg_sel = 0; + mmio_inst->op_num = 0; + + mmio_inst->operand[0] = 0; + mmio_inst->operand[1] = 0; + mmio_inst->operand[2] = 0; + + mmio_inst->flags = 0; +} + +#define GET_OP_SIZE_FOR_BYTE(op_size) \ + do {if (rex) op_size = BYTE_64;else op_size = BYTE;} while(0) + +#define GET_OP_SIZE_FOR_NONEBYTE(op_size) \ + do {if (rex & 0x8) op_size = QUAD; else if (op_size != WORD) op_size = LONG;} while(0) + static int vmx_decode(const unsigned char *inst, struct instruction *thread_inst) { unsigned long eflags; int index, vm86 = 0; + unsigned char rex = 0; + unsigned char tmp_size = 0; + + + init_instruction(thread_inst); + + inst = check_prefix(inst, thread_inst, &rex); __vmread(GUEST_RFLAGS, &eflags); if (eflags & X86_EFLAGS_VM) - vm86 = 1; + vm86 = 1; if (vm86) { /* meaning is reversed */ if (thread_inst->op_size == WORD) @@ -255,34 +364,30 @@ case 0x88: /* mov r8 to m8 */ thread_inst->op_size = BYTE; - index = get_index((inst + 1)); - thread_inst->operand[0] = mk_operand(BYTE, index, 0, REGISTER); + index = get_index((inst + 1), rex); + GET_OP_SIZE_FOR_BYTE(tmp_size); + thread_inst->operand[0] = mk_operand(tmp_size, index, 0, REGISTER); + break; case 0x89: /* mov r32/16 to m32/16 */ - index = get_index((inst + 1)); - if (thread_inst->op_size == WORD) { - thread_inst->operand[0] = mk_operand(WORD, index, 0, REGISTER); - } else { - thread_inst->op_size = LONG; - thread_inst->operand[0] = mk_operand(LONG, index, 0, REGISTER); - } + index = get_index((inst + 1), rex); + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[0] = mk_operand(thread_inst->op_size, index, 0, REGISTER); + break; case 0x8a: /* mov m8 to r8 */ thread_inst->op_size = BYTE; - index = get_index((inst + 1)); - thread_inst->operand[1] = mk_operand(BYTE, index, 0, REGISTER); + index = get_index((inst + 1), rex); + GET_OP_SIZE_FOR_BYTE(tmp_size); + thread_inst->operand[1] = mk_operand(tmp_size, index, 0, REGISTER); break; case 0x8b: /* mov r32/16 to m32/16 */ - index = get_index((inst + 1)); - if (thread_inst->op_size == WORD) { - thread_inst->operand[1] = mk_operand(WORD, index, 0, REGISTER); - } else { - thread_inst->op_size = LONG; - thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); - } + index = get_index((inst + 1), rex); + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 0, REGISTER); break; case 0x8c: case 0x8e: @@ -292,30 +397,25 @@ case 0xa0: /* mov byte to al */ thread_inst->op_size = BYTE; - thread_inst->operand[1] = mk_operand(BYTE, 0, 0, REGISTER); + GET_OP_SIZE_FOR_BYTE(tmp_size); + thread_inst->operand[1] = mk_operand(tmp_size, 0, 0, REGISTER); break; case 0xa1: /* mov word/doubleword to ax/eax */ - if (thread_inst->op_size == WORD) { - thread_inst->operand[1] = mk_operand(WORD, 0, 0, REGISTER); - } else { - thread_inst->op_size = LONG; - thread_inst->operand[1] = mk_operand(LONG, 0, 0, REGISTER); - } + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[1] = mk_operand(thread_inst->op_size, 0, 0, REGISTER); + break; case 0xa2: /* mov al to (seg:offset) */ thread_inst->op_size = BYTE; - thread_inst->operand[0] = mk_operand(BYTE, 0, 0, REGISTER); + GET_OP_SIZE_FOR_BYTE(tmp_size); + thread_inst->operand[0] = mk_operand(tmp_size, 0, 0, REGISTER); break; case 0xa3: /* mov ax/eax to (seg:offset) */ - if (thread_inst->op_size == WORD) { - thread_inst->operand[0] = mk_operand(WORD, 0, 0, REGISTER); - } else { - thread_inst->op_size = LONG; - thread_inst->operand[0] = mk_operand(LONG, 0, 0, REGISTER); - } + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, REGISTER); break; case 0xa4: /* movsb */ @@ -324,11 +424,8 @@ return DECODE_success; case 0xa5: /* movsw/movsl */ - if (thread_inst->op_size == WORD) { - } else { - thread_inst->op_size = LONG; - } - strcpy((char *)thread_inst->i_name, "movs"); + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + strcpy((char *)thread_inst->i_name, "movs"); return DECODE_success; case 0xaa: /* stosb */ @@ -353,14 +450,10 @@ break; case 0xc7: /* mov imm16/32 to m16/32 */ - if (thread_inst->op_size == WORD) { - thread_inst->operand[0] = mk_operand(WORD, 0, 0, IMMEDIATE); - } else { - thread_inst->op_size = LONG; - thread_inst->operand[0] = mk_operand(LONG, 0, 0, IMMEDIATE); - } - thread_inst->immediate = get_immediate(vm86, - (inst+1), thread_inst->op_size); + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, IMMEDIATE); + thread_inst->immediate = get_immediate(vm86, (inst+1), thread_inst->op_size); + break; case 0x0f: break; @@ -379,21 +472,23 @@ /* movz */ case 0xb6: - index = get_index((inst + 1)); - if (thread_inst->op_size == WORD) { - thread_inst->operand[1] = mk_operand(WORD, index, 0, REGISTER); - } else { - thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); - - } + index = get_index((inst + 1), rex); + GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size); + thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 0, REGISTER); thread_inst->op_size = BYTE; strcpy((char *)thread_inst->i_name, "movzb"); return DECODE_success; case 0xb7: - thread_inst->op_size = WORD; - index = get_index((inst + 1)); - thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); + index = get_index((inst + 1), rex); + if (rex & 0x8) { + thread_inst->op_size = LONG; + thread_inst->operand[1] = mk_operand(QUAD, index, 0, REGISTER); + } else { + thread_inst->op_size = WORD; + thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); + } + strcpy((char *)thread_inst->i_name, "movzw"); return DECODE_success; @@ -406,8 +501,7 @@ return DECODE_failure; } -int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, - int inst_len) +int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len) { l1_pgentry_t gpte; unsigned long mfn; @@ -449,22 +543,6 @@ return inst_len+remaining; } -static void init_instruction(struct instruction *mmio_inst) -{ - memset(mmio_inst->i_name, '0', I_NAME_LEN); - mmio_inst->op_size = 0; - mmio_inst->offset = 0; - mmio_inst->immediate = 0; - mmio_inst->seg_sel = 0; - mmio_inst->op_num = 0; - - mmio_inst->operand[0] = 0; - mmio_inst->operand[1] = 0; - mmio_inst->operand[2] = 0; - - mmio_inst->flags = 0; -} - static int read_from_mmio(struct instruction *inst_p) { // Only for mov instruction now!!! @@ -570,17 +648,10 @@ domain_crash_synchronous(); } -#if 0 - printk("handle_mmio: cs:eip 0x%lx:0x%lx(0x%lx): opcode", - cs, eip, inst_addr, inst_len); - for (ret = 0; ret < inst_len; ret++) - printk(" %02x", inst[ret]); - printk("\n"); -#endif init_instruction(&mmio_inst); - if (vmx_decode(check_prefix(inst, &mmio_inst), &mmio_inst) == DECODE_failure) + if (vmx_decode(inst, &mmio_inst) == DECODE_failure) domain_crash_synchronous(); __vmwrite(GUEST_RIP, eip + inst_len); @@ -654,8 +725,8 @@ } if (!strncmp((char *)mmio_inst.i_name, "stos", 4)) { - send_mmio_req(gpa, &mmio_inst, - inst_decoder_regs->eax, IOREQ_WRITE, 0); + send_mmio_req(gpa, &mmio_inst, + inst_decoder_regs->eax, IOREQ_WRITE, 0); } domain_crash_synchronous(); diff -Nru a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h --- a/xen/include/asm-x86/vmx_platform.h 2005-06-23 07:06:07 -04:00 +++ b/xen/include/asm-x86/vmx_platform.h 2005-06-23 07:06:07 -04:00 @@ -40,6 +40,7 @@ #define WORD 2 #define LONG 4 #define QUAD 8 +#define BYTE_64 16 //For instruction.operand[].flag #define REGISTER 0x1 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |