# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 05f07acd3be2fac0c66ef6e9a94b129f7f7e37b5
# Parent 11a431a8b3d98f991d4d22b47baa226b1cd12e2a
[HVM][MMIO] Emulate more instructions: or/and/xor with byte width,
and load string (LODS) instructions.
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Yunfeng zhao <yunfeng.zhao@xxxxxxxxx>
Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>
xen-unstable changeset: 10292:7d37df6c324721647d5d6c930af09101f1165e23
xen-unstable date: Wed Jun 7 14:20:29 2006 +0100
[HVM][MMIO] Support decode of 0x83 opcode (or imm8,m32/64').
This instruction is used by both WinXP during an SMP installation and by
Sun Solaris. With this patch Sun Solaris UP is able to boot. Windows
SMP gets a bit further but still has issues.
Signed-off-by: Tom Woller <thomas.woller@xxxxxxx>
Signed-off-by: Travis Betak <tbetak.woller@xxxxxxx>
xen-unstable changeset: 10293:2049467adee349ad576e8afee5de77e23d8928d8
xen-unstable date: Wed Jun 7 14:21:49 2006 +0100
---
xen/arch/x86/hvm/io.c | 7 +++
xen/arch/x86/hvm/platform.c | 94 ++++++++++++++++++++++++++++++++-----------
xen/include/asm-x86/hvm/io.h | 7 +--
3 files changed, 83 insertions(+), 25 deletions(-)
diff -r 11a431a8b3d9 -r 05f07acd3be2 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c Wed Jun 07 14:17:26 2006 +0100
+++ b/xen/arch/x86/hvm/io.c Wed Jun 07 14:24:14 2006 +0100
@@ -505,6 +505,13 @@ static void hvm_mmio_assist(struct vcpu
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 -r 11a431a8b3d9 -r 05f07acd3be2 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Wed Jun 07 14:17:26 2006 +0100
+++ b/xen/arch/x86/hvm/platform.c Wed Jun 07 14:24:14 2006 +0100
@@ -364,6 +364,12 @@ static int hvm_decode(int realmode, unsi
}
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, unsi
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, unsi
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);
@@ -408,19 +426,30 @@ static int hvm_decode(int realmode, unsi
case 0x80:
case 0x81:
+ case 0x83:
{
unsigned char ins_subtype = (opcode[1] >> 3) & 7;
if (opcode[0] == 0x80) {
GET_OP_SIZE_FOR_BYTE(size_reg);
instr->op_size = BYTE;
- } else {
+ } else if (opcode[0] == 0x81) {
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
size_reg = instr->op_size;
+ } else if (opcode[0] == 0x83) {
+ GET_OP_SIZE_FOR_NONEBYTE(size_reg);
+ instr->op_size = size_reg;
}
+
+ /* opcode 0x83 always has a single byte operand */
+ if (opcode[0] == 0x83)
+ instr->immediate =
+ (signed char)get_immediate(realmode, opcode+1, BYTE);
+ else
+ instr->immediate =
+ get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(realmode, opcode+1,
instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
switch (ins_subtype) {
@@ -513,6 +542,16 @@ static int hvm_decode(int realmode, unsi
case 0xAB: /* stosw/stosl */
instr->instr = INSTR_STOS;
+ 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;
@@ -906,6 +945,17 @@ void handle_mmio(unsigned long va, unsig
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 +1004,26 @@ void handle_mmio(unsigned long va, unsig
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 -r 11a431a8b3d9 -r 05f07acd3be2 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h Wed Jun 07 14:17:26 2006 +0100
+++ b/xen/include/asm-x86/hvm/io.h Wed Jun 07 14:24:14 2006 +0100
@@ -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 */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|