From: kaf24@firebug.cl.cam.ac.uk Date: Wed, 7 Jun 2006 13:20:29 +0000 (+0100) Subject: [HVM][MMIO] Emulate more instructions: or/and/xor with byte width, X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15972^2~43 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a47f6548d9d23e84ca021dff85bb5354aed2f1b1;p=xen.git [HVM][MMIO] Emulate more instructions: or/and/xor with byte width, and load string (LODS) instructions. Signed-off-by: Yunhong Jiang Signed-off-by: Yunfeng zhao Signed-off-by: Xin Li --- diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 18bd59ebfd..95253fa976 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -507,6 +507,13 @@ static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs, regs->ecx -= p->count; break; + case INSTR_LODS: + sign = p->df ? -1 : 1; + regs->esi += sign * p->count * p->size; + if (mmio_opp->flags & REPZ) + regs->ecx -= p->count; + break; + case INSTR_AND: if (src & REGISTER) { index = operand_index(src); diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 20779414fa..15d5a44e73 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -364,6 +364,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i } switch (*opcode) { + case 0x0A: /* or r8, m8 */ + instr->instr = INSTR_OR; + instr->op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + return mem_reg(size_reg, opcode, instr, rex); + case 0x0B: /* or m32/16, r32/16 */ instr->instr = INSTR_OR; GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); @@ -380,6 +386,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); return reg_mem(instr->op_size, opcode, instr, rex); + case 0x22: /* and m8, r8 */ + instr->instr = INSTR_AND; + instr->op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + return mem_reg(size_reg, opcode, instr, rex); + case 0x23: /* and m32/16, r32/16 */ instr->instr = INSTR_AND; GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); @@ -396,6 +408,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); return reg_mem(instr->op_size, opcode, instr, rex); + case 0x32: /* xor m8, r8*/ + instr->instr = INSTR_XOR; + instr->op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + return mem_reg(size_reg, opcode, instr, rex); + case 0x39: /* cmp r32/16, m32/16 */ instr->instr = INSTR_CMP; GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); @@ -516,6 +534,16 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); return DECODE_success; + case 0xAC: /* lodsb */ + instr->instr = INSTR_LODS; + instr->op_size = BYTE; + return DECODE_success; + + case 0xAD: /* lodsw/lodsl */ + instr->instr = INSTR_LODS; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return DECODE_success; + case 0xC6: if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */ instr->instr = INSTR_MOV; @@ -906,6 +934,17 @@ void handle_mmio(unsigned long va, unsigned long gpa) GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0); break; + case INSTR_LODS: + /* + * Since the source is always in (contiguous) mmio space we don't + * need to break it up into pages. + */ + mmio_opp->flags = mmio_inst.flags; + mmio_opp->instr = mmio_inst.instr; + send_mmio_req(IOREQ_TYPE_COPY, gpa, + GET_REPEAT_COUNT(), mmio_inst.op_size, 0, IOREQ_READ, 0); + break; + case INSTR_OR: mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mmio_opp, regs); break; @@ -954,26 +993,26 @@ void handle_mmio(unsigned long va, unsigned long gpa) mmio_opp->instr = mmio_inst.instr; mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */ mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */ - if (mmio_inst.operand[0] & REGISTER) { - long value; - unsigned long operand = mmio_inst.operand[0]; - value = get_reg_value(operand_size(operand), - operand_index(operand), 0, - mmio_opp->inst_decoder_regs); - /* send the request and wait for the value */ - send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1, - mmio_inst.op_size, value, IOREQ_WRITE, 0); - } else { - /* the destination is a register */ - long value; - unsigned long operand = mmio_inst.operand[1]; - value = get_reg_value(operand_size(operand), - operand_index(operand), 0, - mmio_opp->inst_decoder_regs); - /* send the request and wait for the value */ - send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1, - mmio_inst.op_size, value, IOREQ_WRITE, 0); - } + if ( mmio_inst.operand[0] & REGISTER ) { + long value; + unsigned long operand = mmio_inst.operand[0]; + value = get_reg_value(operand_size(operand), + operand_index(operand), 0, + mmio_opp->inst_decoder_regs); + /* send the request and wait for the value */ + send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1, + mmio_inst.op_size, value, IOREQ_WRITE, 0); + } else { + /* the destination is a register */ + long value; + unsigned long operand = mmio_inst.operand[1]; + value = get_reg_value(operand_size(operand), + operand_index(operand), 0, + mmio_opp->inst_decoder_regs); + /* send the request and wait for the value */ + send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1, + mmio_inst.op_size, value, IOREQ_WRITE, 0); + } break; default: diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 0d4b36b0ad..c07470394f 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -64,9 +64,10 @@ #define INSTR_MOVZX 8 #define INSTR_MOVSX 9 #define INSTR_STOS 10 -#define INSTR_TEST 11 -#define INSTR_BT 12 -#define INSTR_XCHG 13 +#define INSTR_LODS 11 +#define INSTR_TEST 12 +#define INSTR_BT 13 +#define INSTR_XCHG 14 struct instruction { __s8 instr; /* instruction type */