ia64/xen-unstable

changeset 10330:7d37df6c3247

[HVM][MMIO] Emulate more instructions: or/and/xor with byte width,
and load string (LODS) instructions.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Yunfeng zhao <yunfeng.zhao@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jun 07 14:20:29 2006 +0100 (2006-06-07)
parents 2fd2fd4b7c6a
children 2049467adee3
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/platform.c xen/include/asm-x86/hvm/io.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Wed Jun 07 14:13:22 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/io.c	Wed Jun 07 14:20:29 2006 +0100
     1.3 @@ -507,6 +507,13 @@ static void hvm_mmio_assist(struct vcpu 
     1.4              regs->ecx -= p->count;
     1.5          break;
     1.6  
     1.7 +    case INSTR_LODS:
     1.8 +        sign = p->df ? -1 : 1;
     1.9 +        regs->esi += sign * p->count * p->size;
    1.10 +        if (mmio_opp->flags & REPZ)
    1.11 +            regs->ecx -= p->count;
    1.12 +        break;
    1.13 +
    1.14      case INSTR_AND:
    1.15          if (src & REGISTER) {
    1.16              index = operand_index(src);
     2.1 --- a/xen/arch/x86/hvm/platform.c	Wed Jun 07 14:13:22 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/platform.c	Wed Jun 07 14:20:29 2006 +0100
     2.3 @@ -364,6 +364,12 @@ static int hvm_decode(int realmode, unsi
     2.4      }
     2.5  
     2.6      switch (*opcode) {
     2.7 +    case 0x0A: /* or r8, m8 */
     2.8 +        instr->instr = INSTR_OR;
     2.9 +        instr->op_size = BYTE;
    2.10 +        GET_OP_SIZE_FOR_BYTE(size_reg);
    2.11 +        return mem_reg(size_reg, opcode, instr, rex);
    2.12 +
    2.13      case 0x0B: /* or m32/16, r32/16 */
    2.14          instr->instr = INSTR_OR;
    2.15          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.16 @@ -380,6 +386,12 @@ static int hvm_decode(int realmode, unsi
    2.17          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.18          return reg_mem(instr->op_size, opcode, instr, rex);
    2.19  
    2.20 +    case 0x22: /* and m8, r8 */
    2.21 +        instr->instr = INSTR_AND;
    2.22 +        instr->op_size = BYTE;
    2.23 +        GET_OP_SIZE_FOR_BYTE(size_reg);
    2.24 +        return mem_reg(size_reg, opcode, instr, rex);
    2.25 +
    2.26      case 0x23: /* and m32/16, r32/16 */
    2.27          instr->instr = INSTR_AND;
    2.28          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.29 @@ -396,6 +408,12 @@ static int hvm_decode(int realmode, unsi
    2.30          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.31          return reg_mem(instr->op_size, opcode, instr, rex);
    2.32  
    2.33 +    case 0x32: /* xor m8, r8*/
    2.34 +        instr->instr = INSTR_XOR;
    2.35 +        instr->op_size = BYTE;
    2.36 +        GET_OP_SIZE_FOR_BYTE(size_reg);
    2.37 +        return mem_reg(size_reg, opcode, instr, rex);
    2.38 +
    2.39      case 0x39: /* cmp r32/16, m32/16 */
    2.40          instr->instr = INSTR_CMP;
    2.41          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.42 @@ -516,6 +534,16 @@ static int hvm_decode(int realmode, unsi
    2.43          GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.44          return DECODE_success;
    2.45  
    2.46 +    case 0xAC: /* lodsb */
    2.47 +        instr->instr = INSTR_LODS;
    2.48 +        instr->op_size = BYTE;
    2.49 +        return DECODE_success;
    2.50 +
    2.51 +    case 0xAD: /* lodsw/lodsl */
    2.52 +        instr->instr = INSTR_LODS;
    2.53 +        GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
    2.54 +        return DECODE_success;
    2.55 +
    2.56      case 0xC6:
    2.57          if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
    2.58              instr->instr = INSTR_MOV;
    2.59 @@ -906,6 +934,17 @@ void handle_mmio(unsigned long va, unsig
    2.60                        GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
    2.61          break;
    2.62  
    2.63 +    case INSTR_LODS:
    2.64 +        /*
    2.65 +         * Since the source is always in (contiguous) mmio space we don't
    2.66 +         * need to break it up into pages.
    2.67 +         */
    2.68 +        mmio_opp->flags = mmio_inst.flags;
    2.69 +        mmio_opp->instr = mmio_inst.instr;
    2.70 +        send_mmio_req(IOREQ_TYPE_COPY, gpa,
    2.71 +                      GET_REPEAT_COUNT(), mmio_inst.op_size, 0, IOREQ_READ, 0);
    2.72 +        break;
    2.73 +
    2.74      case INSTR_OR:
    2.75          mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mmio_opp, regs);
    2.76          break;
    2.77 @@ -954,26 +993,26 @@ void handle_mmio(unsigned long va, unsig
    2.78          mmio_opp->instr = mmio_inst.instr;
    2.79          mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
    2.80          mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
    2.81 -	if (mmio_inst.operand[0] & REGISTER) {
    2.82 -		long value;
    2.83 -		unsigned long operand = mmio_inst.operand[0];
    2.84 -		value = get_reg_value(operand_size(operand), 
    2.85 -				      operand_index(operand), 0,
    2.86 -                    		      mmio_opp->inst_decoder_regs);
    2.87 -        	/* send the request and wait for the value */
    2.88 -        	send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.89 -                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
    2.90 -	} else {
    2.91 -		/* the destination is a register */
    2.92 -		long value;
    2.93 -		unsigned long operand = mmio_inst.operand[1];
    2.94 -		value = get_reg_value(operand_size(operand), 
    2.95 -				      operand_index(operand), 0,
    2.96 -                    		      mmio_opp->inst_decoder_regs);
    2.97 -        	/* send the request and wait for the value */
    2.98 -        	send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.99 -                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
   2.100 -	}
   2.101 +        if ( mmio_inst.operand[0] & REGISTER ) {
   2.102 +            long value;
   2.103 +            unsigned long operand = mmio_inst.operand[0];
   2.104 +            value = get_reg_value(operand_size(operand),
   2.105 +                                  operand_index(operand), 0,
   2.106 +                                  mmio_opp->inst_decoder_regs);
   2.107 +            /* send the request and wait for the value */
   2.108 +            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
   2.109 +                          mmio_inst.op_size, value, IOREQ_WRITE, 0);
   2.110 +        } else {
   2.111 +            /* the destination is a register */
   2.112 +            long value;
   2.113 +            unsigned long operand = mmio_inst.operand[1];
   2.114 +            value = get_reg_value(operand_size(operand),
   2.115 +                                  operand_index(operand), 0,
   2.116 +                                  mmio_opp->inst_decoder_regs);
   2.117 +            /* send the request and wait for the value */
   2.118 +            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
   2.119 +                          mmio_inst.op_size, value, IOREQ_WRITE, 0);
   2.120 +        }
   2.121          break;
   2.122  
   2.123      default:
     3.1 --- a/xen/include/asm-x86/hvm/io.h	Wed Jun 07 14:13:22 2006 +0100
     3.2 +++ b/xen/include/asm-x86/hvm/io.h	Wed Jun 07 14:20:29 2006 +0100
     3.3 @@ -64,9 +64,10 @@
     3.4  #define INSTR_MOVZX 8
     3.5  #define INSTR_MOVSX 9
     3.6  #define INSTR_STOS  10
     3.7 -#define INSTR_TEST  11
     3.8 -#define INSTR_BT    12
     3.9 -#define INSTR_XCHG  13
    3.10 +#define INSTR_LODS  11
    3.11 +#define INSTR_TEST  12
    3.12 +#define INSTR_BT    13
    3.13 +#define INSTR_XCHG  14
    3.14  
    3.15  struct instruction {
    3.16      __s8    instr;        /* instruction type */