move all x86_emulate_memop() to a structure
PATCH RESEND 2/5 move all x86_emulate_memop() to a structure
move all x86_emulate_memop() common variables between decode and execute to a structure decode_cache.
struct decode_cache {
u8 twobyte;
u8 b;
u8 lock_prefix;
u8 rep_prefix;
u8 op_bytes;
u8 ad_bytes;
struct operand src;
struct operand dst;
unsigned long *override_base;
unsigned int d;
unsigned long regs[NR_VCPU_REGS];
unsigned long eip;
/* modrm */
u8 modrm;
u8 modrm_mod;
u8 modrm_reg;
u8 modrm_rm;
u8 use_modrm_ea;
unsigned long modrm_ea;
unsigned long modrm_val;
};drivers/kvm/x86_emulate.c +507 -424
@@ -221,13 +221,6 @@ static u16 twobyte_table[256] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; -/* Type, address-of, and value of an instruction's operand. */ -struct operand { -enum {OP_REG ,OP_MEM ,OP_IMM } type; -unsigned int bytes; -unsigned long val, orig_val, *ptr; -}; -/* EFLAGS bit definitions. */ #define EFLG_OF (1<<11)#define EFLG_DF (1<<10)
@@ -430,25 +423,28 @@ struct operand {/* Access/update address held in a register, based on addressing mode. */ #define address_mask (reg) \ - ((ad_bytes == sizeof(unsigned long)) ? \ - (reg) : ((reg) & ((1UL << (ad_bytes << 3)) - 1))) + ((decode->ad_bytes == sizeof(unsigned long)) ? \ + (reg) : ((reg) & ((1UL << (decode->ad_bytes << 3)) - 1)))#define register_address (base, reg) \ ((base) + address_mask(reg)) #define register_address_increment(reg, inc) \ do { \ /* signed type ensures sign extension to long */ \ int _inc = (inc); \ - if ( ad_bytes == sizeof(unsigned long) ) \ + if (decode->ad_bytes == sizeof(unsigned long)) \ (reg) += _inc; \ else \ - (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ - (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ + (reg) = ((reg) & \ + ~((1UL << (decode->ad_bytes << 3)) - 1)) | \ + (((reg) + _inc) & \ + ((1UL << (decode->ad_bytes << 3)) - 1)); \ } while (0)#define JMP_REL (rel) \ do { \ - _eip += (int)(rel); \ - _eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \ + decode->eip += (int)(rel); \ + decode->eip = ((decode->op_bytes == 2) ? \ + (uint16_t)decode->eip : (uint32_t)decode->eip); \ } while (0)/*
@@ -524,39 +520,35 @@ static int test_cc(unsigned int conditioint x86_emulate_memop (struct x86_emulate_ctxt *ctxt,struct x86_emulate_ops *ops) { -unsigned d; -u8 b, sib, twobyte =0 , rex_prefix =0 ; -u8 modrm, modrm_mod =0 , modrm_reg =0 , modrm_rm =0 ; -unsigned long *override_base =NULL ; -unsigned int op_bytes, ad_bytes, lock_prefix =0 , rep_prefix =0 , i; +struct decode_cache *decode = &ctxt->decode; +u8 sib, rex_prefix =0 ; +unsigned int i;int rc =0 ; -struct operand src, dst;unsigned long cr2 = ctxt->cr2;int mode = ctxt->mode; -unsigned long modrm_ea; -int use_modrm_ea, index_reg =0 , base_reg =0 , scale, rip_relative =0 ; +int index_reg =0 , base_reg =0 , scale, rip_relative =0 ;int no_wb =0 ;u64 msr_data;/* Shadow copy of register state. Committed on successful emulation. */ -unsigned long _regs[NR_VCPU_REGS ]; -unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags; -unsigned long modrm_val =0 ; +unsigned long _eflags = ctxt->eflags; -memcpy (_regs, ctxt->vcpu->regs,sizeof _regs); +memset (decode,0 ,sizeof (struct decode_cache )); + decode->eip = ctxt->vcpu->rip; +memcpy (decode->regs, ctxt->vcpu->regs,sizeof decode->regs);switch (mode) {case X86EMUL_MODE_REAL :case X86EMUL_MODE_PROT16 : - op_bytes = ad_bytes =2 ; + decode->op_bytes = decode->ad_bytes =2 ;break ;case X86EMUL_MODE_PROT32 : - op_bytes = ad_bytes =4 ; + decode->op_bytes = decode->ad_bytes =4 ;break ;#ifdef CONFIG_X86_64 case X86EMUL_MODE_PROT64 : - op_bytes =4 ; - ad_bytes =8 ; + decode->op_bytes =4 ; + decode->ad_bytes =8 ;break ;#endif default :
@@ -565,39 +557,41 @@ x86_emulate_memop(struct x86_emulate_ctx/* Legacy prefixes. */ for (i =0 ; i <8 ; i++) { -switch (b =insn_fetch (u8,1 , _eip)) { +switch (decode->b =insn_fetch (u8,1 , decode->eip)) {case 0x66 :/* operand-size override */ - op_bytes ^=6 ;/* switch between 2/4 bytes */ + decode->op_bytes ^=6 ;/* switch between 2/4 bytes */ break ;case 0x67 :/* address-size override */ if (mode ==X86EMUL_MODE_PROT64 ) - ad_bytes ^=12 ;/* switch between 4/8 bytes */ +/* switch between 4/8 bytes */ + decode->ad_bytes ^=12 ;else - ad_bytes ^=6 ;/* switch between 2/4 bytes */ +/* switch between 2/4 bytes */ + decode->ad_bytes ^=6 ;break ;case 0x2e :/* CS override */ - override_base = &ctxt->cs_base; + decode->override_base = &ctxt->cs_base;break ;case 0x3e :/* DS override */ - override_base = &ctxt->ds_base; + decode->override_base = &ctxt->ds_base;break ;case 0x26 :/* ES override */ - override_base = &ctxt->es_base; + decode->override_base = &ctxt->es_base;break ;case 0x64 :/* FS override */ - override_base = &ctxt->fs_base; + decode->override_base = &ctxt->fs_base;break ;case 0x65 :/* GS override */ - override_base = &ctxt->gs_base; + decode->override_base = &ctxt->gs_base;break ;case 0x36 :/* SS override */ - override_base = &ctxt->ss_base; + decode->override_base = &ctxt->ss_base;break ;case 0xf0 :/* LOCK */ - lock_prefix =1 ; + decode->lock_prefix =1 ;break ;case 0xf3 :/* REP/REPE/REPZ */ - rep_prefix =1 ; + decode->rep_prefix =1 ;break ;case 0xf2 :/* REPNE/REPNZ */ break ;
@@ -609,177 +603,193 @@ x86_emulate_memop(struct x86_emulate_ctx done_prefixes:/* REX prefix. */ -if ((mode ==X86EMUL_MODE_PROT64 ) && ((b &0xf0 ) ==0x40 )) { - rex_prefix = b; -if (b &8 ) - op_bytes =8 ;/* REX.W */ - modrm_reg = (b &4 ) <<1 ;/* REX.R */ - index_reg = (b &2 ) <<2 ;/* REX.X */ - modrm_rm = base_reg = (b &1 ) <<3 ;/* REG.B */ - b =insn_fetch (u8,1 , _eip); +if ((mode ==X86EMUL_MODE_PROT64 ) && ((decode->b &0xf0 ) ==0x40 )) { + rex_prefix = decode->b; +if (decode->b &8 ) + decode->op_bytes =8 ;/* REX.W */ + decode->modrm_reg = (decode->b &4 ) <<1 ;/* REX.R */ + index_reg = (decode->b &2 ) <<2 ;/* REX.X */ + decode->modrm_rm = base_reg = (decode->b &1 ) <<3 ;/* REG.B */ + decode->b =insn_fetch (u8,1 , decode->eip); }/* Opcode byte(s). */ - d = opcode_table[b]; -if (d ==0 ) { + decode->d = opcode_table[decode->b]; +if (decode->d ==0 ) {/* Two-byte opcode? */ -if (b ==0x0f ) { - twobyte =1 ; - b =insn_fetch (u8,1 , _eip); - d = twobyte_table[b]; +if (decode->b ==0x0f ) { + decode->twobyte =1 ; + decode->b =insn_fetch (u8,1 , decode->eip); + decode->d = twobyte_table[decode->b]; }/* Unrecognised? */ -if (d ==0 ) +if (decode->d ==0 ) goto cannot_emulate; }/* ModRM and SIB bytes. */ -if (d & ModRM) { - modrm =insn_fetch (u8,1 , _eip); - modrm_mod |= (modrm &0xc0 ) >>6 ; - modrm_reg |= (modrm &0x38 ) >>3 ; - modrm_rm |= (modrm &0x07 ); - modrm_ea =0 ; - use_modrm_ea =1 ; - -if (modrm_mod ==3 ) { - modrm_val = *(unsigned long *) -decode_register (modrm_rm, _regs, d & ByteOp); +if (decode->d & ModRM) { + decode->modrm =insn_fetch (u8,1 , decode->eip); + decode->modrm_mod |= (decode->modrm &0xc0 ) >>6 ; + decode->modrm_reg |= (decode->modrm &0x38 ) >>3 ; + decode->modrm_rm |= (decode->modrm &0x07 ); + decode->modrm_ea =0 ; + decode->use_modrm_ea =1 ; + +if (decode->modrm_mod ==3 ) { + decode->modrm_val = *(unsigned long *) +decode_register (decode->modrm_rm, + decode->regs, + decode->d & ByteOp); goto modrm_done; } -if (ad_bytes ==2 ) { -unsigned bx = _regs[VCPU_REGS_RBX ]; -unsigned bp = _regs[VCPU_REGS_RBP ]; -unsigned si = _regs[VCPU_REGS_RSI ]; -unsigned di = _regs[VCPU_REGS_RDI ]; +if (decode->ad_bytes ==2 ) { +unsigned bx = decode->regs[VCPU_REGS_RBX ]; +unsigned bp = decode->regs[VCPU_REGS_RBP ]; +unsigned si = decode->regs[VCPU_REGS_RSI ]; +unsigned di = decode->regs[VCPU_REGS_RDI ];/* 16-bit ModR/M decode. */ -switch (modrm_mod) { +switch (decode->modrm_mod) {case 0 : -if (modrm_rm ==6 ) - modrm_ea +=insn_fetch (u16,2 , _eip); +if (decode->modrm_rm ==6 ) + decode->modrm_ea += +insn_fetch (u16,2 , decode->eip);break ;case 1 : - modrm_ea +=insn_fetch (s8,1 , _eip); + decode->modrm_ea += +insn_fetch (s8,1 , decode->eip);break ;case 2 : - modrm_ea +=insn_fetch (u16,2 , _eip); + decode->modrm_ea += +insn_fetch (u16,2 , decode->eip);break ; } -switch (modrm_rm) { +switch (decode->modrm_rm) {case 0 : - modrm_ea += bx + si; + decode->modrm_ea += bx + si;break ;case 1 : - modrm_ea += bx + di; + decode->modrm_ea += bx + di;break ;case 2 : - modrm_ea += bp + si; + decode->modrm_ea += bp + si;break ;case 3 : - modrm_ea += bp + di; + decode->modrm_ea += bp + di;break ;case 4 : - modrm_ea += si; + decode->modrm_ea += si;break ;case 5 : - modrm_ea += di; + decode->modrm_ea += di;break ;case 6 : -if (modrm_mod !=0 ) - modrm_ea += bp; +if (decode->modrm_mod !=0 ) + decode->modrm_ea += bp;break ;case 7 : - modrm_ea += bx; + decode->modrm_ea += bx;break ; } -if (modrm_rm ==2 || modrm_rm ==3 || - (modrm_rm ==6 && modrm_mod !=0 )) -if (!override_base) - override_base = &ctxt->ss_base; - modrm_ea = (u16 )modrm_ea; +if (decode->modrm_rm ==2 || decode->modrm_rm ==3 || + (decode->modrm_rm ==6 && decode->modrm_mod !=0 )) +if (!decode->override_base) + decode->override_base = &ctxt->ss_base; + decode->modrm_ea = (u16 )decode->modrm_ea; }else {/* 32/64-bit ModR/M decode. */ -switch (modrm_rm) { +switch (decode->modrm_rm) {case 4 :case 12 : - sib =insn_fetch (u8,1 , _eip); + sib =insn_fetch (u8,1 , decode->eip); index_reg |= (sib >>3 ) &7 ; base_reg |= sib &7 ; scale = sib >>6 ;switch (base_reg) {case 5 : -if (modrm_mod !=0 ) - modrm_ea += _regs[base_reg]; +if (decode->modrm_mod !=0 ) + decode->modrm_ea += + decode->regs[base_reg];else - modrm_ea +=insn_fetch (s32,4 , _eip); + decode->modrm_ea += +insn_fetch (s32,4 , + decode->eip);break ;default : - modrm_ea += _regs[base_reg]; + decode->modrm_ea += + decode->regs[base_reg]; }switch (index_reg) {case 4 :break ;default : - modrm_ea += _regs[index_reg] << scale; + decode->modrm_ea += + decode->regs[index_reg] << scale; }break ;case 5 : -if (modrm_mod !=0 ) - modrm_ea += _regs[modrm_rm]; +if (decode->modrm_mod !=0 ) + decode->modrm_ea += + decode->regs[decode->modrm_rm];else if (mode ==X86EMUL_MODE_PROT64 ) rip_relative =1 ;break ;default : - modrm_ea += _regs[modrm_rm]; + decode->modrm_ea += + decode->regs[decode->modrm_rm];break ; } -switch (modrm_mod) { +switch (decode->modrm_mod) {case 0 : -if (modrm_rm ==5 ) - modrm_ea +=insn_fetch (s32,4 , _eip); +if (decode->modrm_rm ==5 ) + decode->modrm_ea += +insn_fetch (s32,4 , decode->eip);break ;case 1 : - modrm_ea +=insn_fetch (s8,1 , _eip); + decode->modrm_ea += +insn_fetch (s8,1 , decode->eip);break ;case 2 : - modrm_ea +=insn_fetch (s32,4 , _eip); + decode->modrm_ea += +insn_fetch (s32,4 , decode->eip);break ; } } -if (!override_base) - override_base = &ctxt->ds_base; +if (!decode->override_base) + decode->override_base = &ctxt->ds_base;if (mode ==X86EMUL_MODE_PROT64 && - override_base != &ctxt->fs_base && - override_base != &ctxt->gs_base) - override_base =NULL ; + decode->override_base != &ctxt->fs_base && + decode->override_base != &ctxt->gs_base) + decode->override_base =NULL ; -if (override_base) - modrm_ea += *override_base; +if (decode->override_base) + decode->modrm_ea += *decode->override_base;if (rip_relative) { - modrm_ea += _eip; -switch (d & SrcMask) { + decode->modrm_ea += decode->eip; +switch (decode->d & SrcMask) {case SrcImmByte: - modrm_ea +=1 ; + decode->modrm_ea +=1 ;break ;case SrcImm: -if (d & ByteOp) - modrm_ea +=1 ; +if (decode->d & ByteOp) + decode->modrm_ea +=1 ;else -if (op_bytes ==8 ) - modrm_ea +=4 ; +if (decode->op_bytes ==8 ) + decode->modrm_ea +=4 ;else - modrm_ea += op_bytes; + decode->modrm_ea += + decode->op_bytes; } } -if (ad_bytes !=8 ) - modrm_ea = (u32 )modrm_ea; - cr2 = modrm_ea; +if (decode->ad_bytes !=8 ) + decode->modrm_ea = (u32 )decode->modrm_ea; + cr2 = decode->modrm_ea; modrm_done: ; }
@@ -788,195 +798,212 @@ done_prefixes:* Decode and fetch the source operand: register, memory * or immediate. */ -switch (d & SrcMask) { +switch (decode->d & SrcMask) {case SrcNone:break ;case SrcReg: - src.type =OP_REG ; -if (d & ByteOp) { - src.ptr =decode_register (modrm_reg, _regs, + decode->src.type =OP_REG ; +if (decode->d & ByteOp) { + decode->src.ptr = +decode_register (decode->modrm_reg, decode->regs, (rex_prefix ==0 )); - src.val = src.orig_val = *(u8 *) src.ptr; - src.bytes =1 ; + decode->src.val = decode->src.orig_val = + *(u8 *) decode->src.ptr; + decode->src.bytes =1 ; }else { - src.ptr =decode_register (modrm_reg, _regs,0 ); -switch ((src.bytes = op_bytes)) { + decode->src.ptr = +decode_register (decode->modrm_reg, decode->regs,0 ); +switch ((decode->src.bytes = decode->op_bytes)) {case 2 : - src.val = src.orig_val = *(u16 *) src.ptr; + decode->src.val = decode->src.orig_val = + *(u16 *) decode->src.ptr;break ;case 4 : - src.val = src.orig_val = *(u32 *) src.ptr; + decode->src.val = decode->src.orig_val = + *(u32 *) decode->src.ptr;break ;case 8 : - src.val = src.orig_val = *(u64 *) src.ptr; + decode->src.val = decode->src.orig_val = + *(u64 *) decode->src.ptr;break ; } }break ;case SrcMem16: - src.bytes =2 ; + decode->src.bytes =2 ; goto srcmem_common;case SrcMem32: - src.bytes =4 ; + decode->src.bytes =4 ; goto srcmem_common;case SrcMem: - src.bytes = (d & ByteOp) ?1 : op_bytes; + decode->src.bytes = (decode->d & ByteOp) ?1 : + decode->op_bytes;/* Don't fetch the address for invlpg: it could be unmapped. */ -if (twobyte && b ==0x01 && modrm_reg ==7 ) +if (decode->twobyte && decode->b ==0x01 + && decode->modrm_reg ==7 )break ; srcmem_common: - src.type =OP_MEM ; - src.ptr = (unsigned long *)cr2; - src.val =0 ; -if ((rc = ops->read_emulated ((unsigned long )src.ptr, - &src.val, src.bytes, ctxt->vcpu)) !=0 ) + decode->src.type =OP_MEM ; + decode->src.ptr = (unsigned long *)cr2; + decode->src.val =0 ; +if ((rc = ops->read_emulated ((unsigned long )decode->src.ptr, + &decode->src.val, + decode->src.bytes, ctxt->vcpu)) !=0 ) goto done; - src.orig_val = src.val; + decode->src.orig_val = decode->src.val;break ;case SrcImm: - src.type =OP_IMM ; - src.ptr = (unsigned long *)_eip; - src.bytes = (d & ByteOp) ?1 : op_bytes; -if (src.bytes ==8 ) - src.bytes =4 ; + decode->src.type =OP_IMM ; + decode->src.ptr = (unsigned long *)decode->eip; + decode->src.bytes = (decode->d & ByteOp) ?1 : decode->op_bytes; +if (decode->src.bytes ==8 ) + decode->src.bytes =4 ;/* NB. Immediates are sign-extended as necessary. */ -switch (src.bytes) { +switch (decode->src.bytes) {case 1 : - src.val =insn_fetch (s8,1 , _eip); + decode->src.val =insn_fetch (s8,1 , decode->eip);break ;case 2 : - src.val =insn_fetch (s16,2 , _eip); + decode->src.val =insn_fetch (s16,2 , decode->eip);break ;case 4 : - src.val =insn_fetch (s32,4 , _eip); + decode->src.val =insn_fetch (s32,4 , decode->eip);break ; }break ;case SrcImmByte: - src.type =OP_IMM ; - src.ptr = (unsigned long *)_eip; - src.bytes =1 ; - src.val =insn_fetch (s8,1 , _eip); + decode->src.type =OP_IMM ; + decode->src.ptr = (unsigned long *)decode->eip; + decode->src.bytes =1 ; + decode->src.val =insn_fetch (s8,1 , decode->eip);break ; }/* Decode and fetch the destination operand: register or memory. */ -switch (d & DstMask) { +switch (decode->d & DstMask) {case ImplicitOps:/* Special instructions do their own operand decoding. */ goto special_insn;case DstReg: - dst.type =OP_REG ; -if ((d & ByteOp) - && !(twobyte && (b ==0xb6 || b ==0xb7 ))) { - dst.ptr =decode_register (modrm_reg, _regs, + decode->dst.type =OP_REG ; +if ((decode->d & ByteOp) + && !(decode->twobyte && + (decode->b ==0xb6 || decode->b ==0xb7 ))) { + decode->dst.ptr = +decode_register (decode->modrm_reg, decode->regs, (rex_prefix ==0 )); - dst.val = *(u8 *) dst.ptr; - dst.bytes =1 ; + decode->dst.val = *(u8 *) decode->dst.ptr; + decode->dst.bytes =1 ; }else { - dst.ptr =decode_register (modrm_reg, _regs,0 ); -switch ((dst.bytes = op_bytes)) { + decode->dst.ptr = +decode_register (decode->modrm_reg, decode->regs,0 ); +switch ((decode->dst.bytes = decode->op_bytes)) {case 2 : - dst.val = *(u16 *)dst.ptr; + decode->dst.val = *(u16 *)decode->dst.ptr;break ;case 4 : - dst.val = *(u32 *)dst.ptr; + decode->dst.val = *(u32 *)decode->dst.ptr;break ;case 8 : - dst.val = *(u64 *)dst.ptr; + decode->dst.val = *(u64 *)decode->dst.ptr;break ; } }break ;case DstMem: - dst.type =OP_MEM ; - dst.ptr = (unsigned long *)cr2; - dst.bytes = (d & ByteOp) ?1 : op_bytes; - dst.val =0 ; -if (d & BitOp) { -unsigned long mask = ~(dst.bytes *8 -1 ); - - dst.ptr = (void *)dst.ptr + (src.val & mask) /8 ; - } -if (!(d & Mov) &&/* optimisation - avoid slow emulated read */ - ((rc = ops->read_emulated ((unsigned long )dst.ptr, - &dst.val, dst.bytes, ctxt->vcpu)) !=0 )) + decode->dst.type =OP_MEM ; + decode->dst.ptr = (unsigned long *)cr2; + decode->dst.bytes = (decode->d & ByteOp) ?1 : decode->op_bytes; + decode->dst.val =0 ; +if (decode->d & BitOp) { +unsigned long mask = ~(decode->dst.bytes *8 -1 ); + + decode->dst.ptr = (void *)decode->dst.ptr + + (decode->src.val & mask) /8 ; + } +if (!(decode->d & Mov) && +/* optimisation - avoid slow emulated read */ + ((rc = ops->read_emulated ((unsigned long )decode->dst.ptr, + &decode->dst.val, + decode->dst.bytes, ctxt->vcpu)) !=0 )) goto done;break ; } - dst.orig_val = dst.val; + decode->dst.orig_val = decode->dst.val; -if (twobyte) +if (decode->twobyte) goto twobyte_insn; -switch (b) { +switch (decode->b) { case 0x00 ... 0x05: add:/* add */ -emulate_2op_SrcV ("add" , src, dst, _eflags); +emulate_2op_SrcV ("add" , decode->src, decode->dst, _eflags);break ; case 0x08 ... 0x0d: or:/* or */ -emulate_2op_SrcV ("or" , src, dst, _eflags); +emulate_2op_SrcV ("or" , decode->src, decode->dst, _eflags);break ; case 0x10 ... 0x15: adc:/* adc */ -emulate_2op_SrcV ("adc" , src, dst, _eflags); +emulate_2op_SrcV ("adc" , decode->src, decode->dst, _eflags);break ; case 0x18 ... 0x1d: sbb:/* sbb */ -emulate_2op_SrcV ("sbb" , src, dst, _eflags); +emulate_2op_SrcV ("sbb" , decode->src, decode->dst, _eflags);break ; case 0x20 ... 0x23: and:/* and */ -emulate_2op_SrcV ("and" , src, dst, _eflags); +emulate_2op_SrcV ("and" , decode->src, decode->dst, _eflags);break ;case 0x24 :/* and al imm8 */ - dst.type =OP_REG ; - dst.ptr = &_regs[VCPU_REGS_RAX ]; - dst.val = *(u8 *)dst.ptr; - dst.bytes =1 ; - dst.orig_val = dst.val; + decode->dst.type =OP_REG ; + decode->dst.ptr = &decode->regs[VCPU_REGS_RAX ]; + decode->dst.val = *(u8 *)decode->dst.ptr; + decode->dst.bytes =1 ; + decode->dst.orig_val = decode->dst.val; goto and;case 0x25 :/* and ax imm16, or eax imm32 */ - dst.type =OP_REG ; - dst.bytes = op_bytes; - dst.ptr = &_regs[VCPU_REGS_RAX ]; -if (op_bytes ==2 ) - dst.val = *(u16 *)dst.ptr; + decode->dst.type =OP_REG ; + decode->dst.bytes = decode->op_bytes; + decode->dst.ptr = &decode->regs[VCPU_REGS_RAX ]; +if (decode->op_bytes ==2 ) + decode->dst.val = *(u16 *)decode->dst.ptr;else - dst.val = *(u32 *)dst.ptr; - dst.orig_val = dst.val; + decode->dst.val = *(u32 *)decode->dst.ptr; + decode->dst.orig_val = decode->dst.val; goto and; case 0x28 ... 0x2d: sub:/* sub */ -emulate_2op_SrcV ("sub" , src, dst, _eflags); +emulate_2op_SrcV ("sub" , decode->src, decode->dst, _eflags);break ; case 0x30 ... 0x35: xor:/* xor */ -emulate_2op_SrcV ("xor" , src, dst, _eflags); +emulate_2op_SrcV ("xor" , decode->src, decode->dst, _eflags);break ; case 0x38 ... 0x3d: cmp:/* cmp */ -emulate_2op_SrcV ("cmp" , src, dst, _eflags); +emulate_2op_SrcV ("cmp" , decode->src, decode->dst, _eflags);break ;case 0x63 :/* movsxd */ if (mode !=X86EMUL_MODE_PROT64 ) goto cannot_emulate; - dst.val = (s32 ) src.val; + decode->dst.val = (s32 ) decode->src.val;break ;case 0x6a :/* push imm8 */ - src.val =0L ; - src.val =insn_fetch (s8,1 , _eip); + decode->src.val =0L ; + decode->src.val =insn_fetch (s8,1 , decode->eip); push: - dst.type =OP_MEM ; - dst.bytes = op_bytes; - dst.val = src.val; -register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); - dst.ptr = (void *)register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]); + decode->dst.type =OP_MEM ; + decode->dst.bytes = decode->op_bytes; + decode->dst.val = decode->src.val; +register_address_increment (decode->regs[VCPU_REGS_RSP ], + -decode->op_bytes); + decode->dst.ptr = (void *)register_address ( + ctxt->ss_base, + decode->regs[VCPU_REGS_RSP ]);break ; case 0x80 ... 0x83: /* Grp1 */ -switch (modrm_reg) { +switch (decode->modrm_reg) {case 0 : goto add;case 1 :
@@ -997,180 +1024,199 @@ push:break ; case 0x84 ... 0x85: test:/* test */ -emulate_2op_SrcV ("test" , src, dst, _eflags); +emulate_2op_SrcV ("test" , decode->src, decode->dst, _eflags);break ; case 0x86 ... 0x87: /* xchg *//* Write back the register source. */ -switch (dst.bytes) { +switch (decode->dst.bytes) {case 1 : - *(u8 *) src.ptr = (u8 ) dst.val; + *(u8 *) decode->src.ptr = (u8 ) decode->dst.val;break ;case 2 : - *(u16 *) src.ptr = (u16 ) dst.val; + *(u16 *) decode->src.ptr = (u16 ) decode->dst.val;break ;case 4 : - *src.ptr = (u32 ) dst.val; + *decode->src.ptr = (u32 ) decode->dst.val;break ;/* 64b reg: zero-extend */ case 8 : - *src.ptr = dst.val; + *decode->src.ptr = decode->dst.val;break ; }/* * Write back the memory destination with implicit LOCK * prefix. */ - dst.val = src.val; - lock_prefix =1 ; + decode->dst.val = decode->src.val; + decode->lock_prefix =1 ;break ; case 0x88 ... 0x8b: /* mov */ goto mov;case 0x8d :/* lea r16/r32, m */ - dst.val = modrm_val; + decode->dst.val = decode->modrm_val;break ;case 0x8f :/* pop (sole member of Grp1a) */ /* 64-bit mode: POP always pops a 64-bit operand. */ if (mode ==X86EMUL_MODE_PROT64 ) - dst.bytes =8 ; -if ((rc = ops->read_std (register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]), - &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) + decode->dst.bytes =8 ; +if ((rc = ops->read_std (register_address ( + ctxt->ss_base, + decode->regs[VCPU_REGS_RSP ]), + &decode->dst.val, + decode->dst.bytes, + ctxt->vcpu)) !=0 ) goto done; -register_address_increment (_regs[VCPU_REGS_RSP ], dst.bytes); +register_address_increment (decode->regs[VCPU_REGS_RSP ], + decode->dst.bytes);break ; case 0xa0 ... 0xa1: /* mov */ - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; - dst.val = src.val; - _eip += ad_bytes;/* skip src displacement */ + decode->dst.ptr = (unsigned long *)&decode->regs[VCPU_REGS_RAX ]; + decode->dst.val = decode->src.val; +/* skip src displacement */ + decode->eip += decode->ad_bytes;break ; case 0xa2 ... 0xa3: /* mov */ - dst.val = (unsigned long )_regs[VCPU_REGS_RAX ]; - _eip += ad_bytes;/* skip dst displacement */ + decode->dst.val = (unsigned long )decode->regs[VCPU_REGS_RAX ]; +/* skip decode->dst displacement */ + decode->eip += decode->ad_bytes;break ; case 0xc0 ... 0xc1: grp2:/* Grp2 */ -switch (modrm_reg) { +switch (decode->modrm_reg) {case 0 :/* rol */ -emulate_2op_SrcB ("rol" , src, dst, _eflags); +emulate_2op_SrcB ("rol" , + decode->src, decode->dst, _eflags);break ;case 1 :/* ror */ -emulate_2op_SrcB ("ror" , src, dst, _eflags); +emulate_2op_SrcB ("ror" , + decode->src, decode->dst, _eflags);break ;case 2 :/* rcl */ -emulate_2op_SrcB ("rcl" , src, dst, _eflags); +emulate_2op_SrcB ("rcl" , + decode->src, decode->dst, _eflags);break ;case 3 :/* rcr */ -emulate_2op_SrcB ("rcr" , src, dst, _eflags); +emulate_2op_SrcB ("rcr" , + decode->src, decode->dst, _eflags);break ;case 4 :/* sal/shl */ case 6 :/* sal/shl */ -emulate_2op_SrcB ("sal" , src, dst, _eflags); +emulate_2op_SrcB ("sal" , + decode->src, decode->dst, _eflags);break ;case 5 :/* shr */ -emulate_2op_SrcB ("shr" , src, dst, _eflags); +emulate_2op_SrcB ("shr" , + decode->src, decode->dst, _eflags);break ;case 7 :/* sar */ -emulate_2op_SrcB ("sar" , src, dst, _eflags); +emulate_2op_SrcB ("sar" , + decode->src, decode->dst, _eflags);break ; }break ; case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ mov: - dst.val = src.val; + decode->dst.val = decode->src.val;break ; case 0xd0 ... 0xd1: /* Grp2 */ - src.val =1 ; + decode->src.val =1 ; goto grp2; case 0xd2 ... 0xd3: /* Grp2 */ - src.val = _regs[VCPU_REGS_RCX ]; + decode->src.val = decode->regs[VCPU_REGS_RCX ]; goto grp2;case 0xe8 :/* call (near) */ {long int rel; -switch (op_bytes) { +switch (decode->op_bytes) {case 2 : - rel =insn_fetch (s16,2 , _eip); + rel =insn_fetch (s16,2 , decode->eip);break ;case 4 : - rel =insn_fetch (s32,4 , _eip); + rel =insn_fetch (s32,4 , decode->eip);break ;case 8 : - rel =insn_fetch (s64,8 , _eip); + rel =insn_fetch (s64,8 , decode->eip);break ;default :DPRINTF ("Call: Invalid op_bytes\n" ); goto cannot_emulate; } - src.val = (unsigned long ) _eip; + decode->src.val = (unsigned long ) decode->eip;JMP_REL (rel); goto push; }case 0xe9 :/* jmp rel */ case 0xeb :/* jmp rel short */ -JMP_REL (src.val); +JMP_REL (decode->src.val); no_wb =1 ;/* Disable writeback. */ break ; case 0xf6 ... 0xf7: /* Grp3 */ -switch (modrm_reg) { +switch (decode->modrm_reg) { case 0 ... 1: /* test *//* * Special case in Grp3: test has an immediate * source operand. */ - src.type =OP_IMM ; - src.ptr = (unsigned long *)_eip; - src.bytes = (d & ByteOp) ?1 : op_bytes; -if (src.bytes ==8 ) - src.bytes =4 ; -switch (src.bytes) { + decode->src.type =OP_IMM ; + decode->src.ptr = (unsigned long *)decode->eip; + decode->src.bytes = (decode->d & ByteOp) ?1 : + decode->op_bytes; +if (decode->src.bytes ==8 ) + decode->src.bytes =4 ; +switch (decode->src.bytes) {case 1 : - src.val =insn_fetch (s8,1 , _eip); + decode->src.val =insn_fetch (s8,1 , + decode->eip);break ;case 2 : - src.val =insn_fetch (s16,2 , _eip); + decode->src.val =insn_fetch (s16,2 , + decode->eip);break ;case 4 : - src.val =insn_fetch (s32,4 , _eip); + decode->src.val =insn_fetch (s32,4 , + decode->eip);break ; } goto test;case 2 :/* not */ - dst.val = ~dst.val; + decode->dst.val = ~decode->dst.val;break ;case 3 :/* neg */ -emulate_1op ("neg" , dst, _eflags); +emulate_1op ("neg" , decode->dst, _eflags);break ;default : goto cannot_emulate; }break ; case 0xfe ... 0xff: /* Grp4/Grp5 */ -switch (modrm_reg) { +switch (decode->modrm_reg) {case 0 :/* inc */ -emulate_1op ("inc" , dst, _eflags); +emulate_1op ("inc" , decode->dst, _eflags);break ;case 1 :/* dec */ -emulate_1op ("dec" , dst, _eflags); +emulate_1op ("dec" , decode->dst, _eflags);break ;case 4 :/* jmp abs */ -if (b ==0xff ) - _eip = dst.val; +if (decode->b ==0xff ) + decode->eip = decode->dst.val;else goto cannot_emulate;break ;case 6 :/* push */ /* 64-bit mode: PUSH always pushes a 64-bit operand. */ if (mode ==X86EMUL_MODE_PROT64 ) { - dst.bytes =8 ; -if ((rc = ops->read_std ((unsigned long )dst.ptr, - &dst.val,8 , - ctxt->vcpu)) !=0 ) + decode->dst.bytes =8 ; +if ((rc = ops->read_std ( + (unsigned long )decode->dst.ptr, + &decode->dst.val,8 , + ctxt->vcpu)) !=0 ) goto done; } -register_address_increment (_regs[VCPU_REGS_RSP ], - -dst.bytes); +register_address_increment (decode->regs[VCPU_REGS_RSP ], + -decode->dst.bytes);if ((rc = ops->write_std (register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]), - &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) + decode->regs[VCPU_REGS_RSP ]), + &decode->dst.val, + decode->dst.bytes, ctxt->vcpu)) !=0 ) goto done; no_wb =1 ;break ;
@@ -1182,34 +1228,40 @@ push: writeback:if (!no_wb) { -switch (dst.type) { +switch (decode->dst.type) {case OP_REG : -/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ -switch (dst.bytes) { +/* The 4-byte case *is* correct: +* in 64-bit mode we zero-extend. +*/ +switch (decode->dst.bytes) {case 1 : - *(u8 *)dst.ptr = (u8 )dst.val; + *(u8 *)decode->dst.ptr = (u8 )decode->dst.val;break ;case 2 : - *(u16 *)dst.ptr = (u16 )dst.val; + *(u16 *)decode->dst.ptr = (u16 )decode->dst.val;break ;case 4 : - *dst.ptr = (u32 )dst.val; + *decode->dst.ptr = (u32 )decode->dst.val;break ;/* 64b: zero-ext */ case 8 : - *dst.ptr = dst.val; + *decode->dst.ptr = decode->dst.val;break ; }break ;case OP_MEM : -if (lock_prefix) - rc = ops->cmpxchg_emulated ((unsigned long )dst. - ptr, &dst.orig_val, - &dst.val, dst.bytes, - ctxt->vcpu); +if (decode->lock_prefix) + rc = ops->cmpxchg_emulated ( + (unsigned long )decode->dst.ptr, + &decode->dst.orig_val, + &decode->dst.val, + decode->dst.bytes, + ctxt->vcpu);else - rc = ops->write_emulated ((unsigned long )dst.ptr, - &dst.val, dst.bytes, - ctxt->vcpu); + rc = ops->write_emulated ( + (unsigned long )decode->dst.ptr, + &decode->dst.val, + decode->dst.bytes, + ctxt->vcpu);if (rc !=0 ) goto done;default :
@@ -1218,134 +1270,145 @@ writeback: }/* Commit shadow register state. */ -memcpy (ctxt->vcpu->regs, _regs,sizeof _regs); +memcpy (ctxt->vcpu->regs, decode->regs,sizeof decode->regs); ctxt->eflags = _eflags; - ctxt->vcpu->rip = _eip; + ctxt->vcpu->rip = decode->eip; done:return (rc ==X86EMUL_UNHANDLEABLE ) ?-1 :0 ; special_insn: -if (twobyte) +if (decode->twobyte) goto twobyte_special_insn; -switch (b) { +switch (decode->b) { case 0x50 ... 0x57: /* push reg */ -if (op_bytes ==2 ) - src.val = (u16 ) _regs[b &0x7 ]; +if (decode->op_bytes ==2 ) + decode->src.val = (u16 ) decode->regs[decode->b &0x7 ];else - src.val = (u32 ) _regs[b &0x7 ]; - dst.type =OP_MEM ; - dst.bytes = op_bytes; - dst.val = src.val; -register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); - dst.ptr = (void *)register_address ( - ctxt->ss_base, _regs[VCPU_REGS_RSP ]); + decode->src.val = (u32 ) decode->regs[decode->b &0x7 ]; + decode->dst.type =OP_MEM ; + decode->dst.bytes = decode->op_bytes; + decode->dst.val = decode->src.val; +register_address_increment (decode->regs[VCPU_REGS_RSP ], + -decode->op_bytes); + decode->dst.ptr = (void *)register_address ( + ctxt->ss_base, decode->regs[VCPU_REGS_RSP ]);break ; case 0x58 ... 0x5f: /* pop reg */ - dst.ptr = (unsigned long *)&_regs[b &0x7 ]; + decode->dst.ptr = + (unsigned long *)&decode->regs[decode->b &0x7 ]; pop_instruction:if ((rc = ops->read_std (register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]), dst.ptr, op_bytes, ctxt->vcpu)) - !=0 ) + decode->regs[VCPU_REGS_RSP ]), decode->dst.ptr, + decode->op_bytes, ctxt->vcpu)) !=0 ) goto done; -register_address_increment (_regs[VCPU_REGS_RSP ], op_bytes); +register_address_increment (decode->regs[VCPU_REGS_RSP ], + decode->op_bytes); no_wb =1 ;/* Disable writeback. */ break ;case 0x6c :/* insb */ case 0x6d :/* insw/insd */ if (kvm_emulate_pio_string (ctxt->vcpu,NULL , -1 ,/* in */ - (d & ByteOp) ?1 : op_bytes,/* size */ - rep_prefix ? -address_mask (_regs[VCPU_REGS_RCX ]) :1 ,/* count */ - (_eflags &EFLG_DF ),/* down */ +1 , + (decode->d & ByteOp) ?1 : decode->op_bytes, + decode->rep_prefix ? +address_mask (decode->regs[VCPU_REGS_RCX ]) :1 , + (_eflags &EFLG_DF ),register_address (ctxt->es_base, - _regs[VCPU_REGS_RDI ]),/* address */ - rep_prefix, - _regs[VCPU_REGS_RDX ]/* port */ - ) ==0 ) + decode->regs[VCPU_REGS_RDI ]), + decode->rep_prefix, + decode->regs[VCPU_REGS_RDX ]) ==0 )return -1 ;return 0 ;case 0x6e :/* outsb */ case 0x6f :/* outsw/outsd */ if (kvm_emulate_pio_string (ctxt->vcpu,NULL , -0 ,/* in */ - (d & ByteOp) ?1 : op_bytes,/* size */ - rep_prefix ? -address_mask (_regs[VCPU_REGS_RCX ]) :1 ,/* count */ - (_eflags &EFLG_DF ),/* down */ -register_address (override_base ? - *override_base : ctxt->ds_base, - _regs[VCPU_REGS_RSI ]),/* address */ - rep_prefix, - _regs[VCPU_REGS_RDX ]/* port */ - ) ==0 ) +0 , + (decode->d & ByteOp) ?1 : decode->op_bytes, + decode->rep_prefix ? +address_mask (decode->regs[VCPU_REGS_RCX ]) :1 , + (_eflags &EFLG_DF ), +register_address (decode->override_base ? + *decode->override_base : + ctxt->ds_base, + decode->regs[VCPU_REGS_RSI ]), + decode->rep_prefix, + decode->regs[VCPU_REGS_RDX ]) ==0 )return -1 ;return 0 ; case 0x70 ... 0x7f: /* jcc (short) */ { -int rel =insn_fetch (s8,1 , _eip); +int rel =insn_fetch (s8,1 , decode->eip); -if (test_cc (b, _eflags)) +if (test_cc (decode->b, _eflags))JMP_REL (rel);break ; }case 0x9c :/* pushf */ - src.val = (unsigned long ) _eflags; + decode->src.val = (unsigned long ) _eflags; goto push;case 0x9d :/* popf */ - dst.ptr = (unsigned long *) &_eflags; + decode->dst.ptr = (unsigned long *) &_eflags; goto pop_instruction;case 0xc3 :/* ret */ - dst.ptr = &_eip; + decode->dst.ptr = &decode->eip; goto pop_instruction;case 0xf4 :/* hlt */ ctxt->vcpu->halt_request =1 ; goto done; } -if (rep_prefix) { -if (_regs[VCPU_REGS_RCX ] ==0 ) { - ctxt->vcpu->rip = _eip; +if (decode->rep_prefix) { +if (decode->regs[VCPU_REGS_RCX ] ==0 ) { + ctxt->vcpu->rip = decode->eip; goto done; } - _regs[VCPU_REGS_RCX ]--; - _eip = ctxt->vcpu->rip; + decode->regs[VCPU_REGS_RCX ]--; + decode->eip = ctxt->vcpu->rip; } -switch (b) { +switch (decode->b) { case 0xa4 ... 0xa5: /* movs */ - dst.type =OP_MEM ; - dst.bytes = (d & ByteOp) ?1 : op_bytes; - dst.ptr = (unsigned long *)register_address (ctxt->es_base, - _regs[VCPU_REGS_RDI ]); + decode->dst.type =OP_MEM ; + decode->dst.bytes = (decode->d & ByteOp) ?1 : decode->op_bytes; + decode->dst.ptr = (unsigned long *)register_address ( + ctxt->es_base, + decode->regs[VCPU_REGS_RDI ]);if ((rc = ops->read_emulated (register_address ( - override_base ? *override_base : ctxt->ds_base, - _regs[VCPU_REGS_RSI ]), &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) + decode->override_base ? *decode->override_base : + ctxt->ds_base, + decode->regs[VCPU_REGS_RSI ]), + &decode->dst.val, + decode->dst.bytes, ctxt->vcpu)) !=0 ) goto done; -register_address_increment (_regs[VCPU_REGS_RSI ], - (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes); -register_address_increment (_regs[VCPU_REGS_RDI ], - (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes); +register_address_increment (decode->regs[VCPU_REGS_RSI ], + (_eflags &EFLG_DF ) ? -decode->dst.bytes + : decode->dst.bytes); +register_address_increment (decode->regs[VCPU_REGS_RDI ], + (_eflags &EFLG_DF ) ? -decode->dst.bytes + : decode->dst.bytes);break ; case 0xa6 ... 0xa7: /* cmps */DPRINTF ("Urk! I don't handle CMPS.\n" ); goto cannot_emulate; case 0xaa ... 0xab: /* stos */ - dst.type =OP_MEM ; - dst.bytes = (d & ByteOp) ?1 : op_bytes; - dst.ptr = (unsigned long *)cr2; - dst.val = _regs[VCPU_REGS_RAX ]; -register_address_increment (_regs[VCPU_REGS_RDI ], - (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes); + decode->dst.type =OP_MEM ; + decode->dst.bytes = (decode->d & ByteOp) ?1 : decode->op_bytes; + decode->dst.ptr = (unsigned long *)cr2; + decode->dst.val = decode->regs[VCPU_REGS_RAX ]; +register_address_increment (decode->regs[VCPU_REGS_RDI ], + (_eflags &EFLG_DF ) ? -decode->dst.bytes + : decode->dst.bytes);break ; case 0xac ... 0xad: /* lods */ - dst.type =OP_REG ; - dst.bytes = (d & ByteOp) ?1 : op_bytes; - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; -if ((rc = ops->read_emulated (cr2, &dst.val, dst.bytes, + decode->dst.type =OP_REG ; + decode->dst.bytes = (decode->d & ByteOp) ?1 : decode->op_bytes; + decode->dst.ptr = (unsigned long *)&decode->regs[VCPU_REGS_RAX ]; +if ((rc = ops->read_emulated (cr2, &decode->dst.val, + decode->dst.bytes, ctxt->vcpu)) !=0 ) goto done; -register_address_increment (_regs[VCPU_REGS_RSI ], - (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes); +register_address_increment (decode->regs[VCPU_REGS_RSI ], + (_eflags &EFLG_DF ) ? -decode->dst.bytes + : decode->dst.bytes);break ; case 0xae ... 0xaf: /* scas */DPRINTF ("Urk! I don't handle SCAS.\n" );
@@ -1355,38 +1418,39 @@ special_insn: goto writeback; twobyte_insn: -switch (b) { +switch (decode->b) {case 0x01 :/* lgdt, lidt, lmsw */ /* Disable writeback. */ no_wb =1 ; -switch (modrm_reg) { +switch (decode->modrm_reg) {u16 size;unsigned long address;case 2 :/* lgdt */ - rc =read_descriptor (ctxt, ops, src.ptr, - &size, &address, op_bytes); + rc =read_descriptor (ctxt, ops, decode->src.ptr, + &size, &address, decode->op_bytes);if (rc) goto done;realmode_lgdt (ctxt->vcpu, size, address);break ;case 3 :/* lidt */ - rc =read_descriptor (ctxt, ops, src.ptr, - &size, &address, op_bytes); + rc =read_descriptor (ctxt, ops, decode->src.ptr, + &size, &address, decode->op_bytes);if (rc) goto done;realmode_lidt (ctxt->vcpu, size, address);break ;case 4 :/* smsw */ -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; - *(u16 *)&_regs[modrm_rm] + *(u16 *)&decode->regs[decode->modrm_rm] =realmode_get_cr (ctxt->vcpu,0 );break ;case 6 :/* lmsw */ -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; -realmode_lmsw (ctxt->vcpu, (u16 )modrm_val, &_eflags); +realmode_lmsw (ctxt->vcpu, + (u16 )decode->modrm_val, &_eflags);break ;case 7 :/* invlpg*/ emulate_invlpg (ctxt->vcpu, cr2);
@@ -1397,24 +1461,26 @@ twobyte_insn:break ;case 0x21 :/* mov from dr to reg */ no_wb =1 ; -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; - rc =emulator_get_dr (ctxt, modrm_reg, &_regs[modrm_rm]); + rc =emulator_get_dr (ctxt, decode->modrm_reg, + &decode->regs[decode->modrm_rm]);break ;case 0x23 :/* mov from reg to dr */ no_wb =1 ; -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; - rc =emulator_set_dr (ctxt, modrm_reg, _regs[modrm_rm]); + rc =emulator_set_dr (ctxt, decode->modrm_reg, + decode->regs[decode->modrm_rm]);break ; case 0x40 ... 0x4f: /* cmov */ - dst.val = dst.orig_val = src.val; + decode->dst.val = decode->dst.orig_val = decode->src.val; no_wb =1 ;/* * First, assume we're decoding an even cmov opcode * (lsb == 0). */ -switch ((b &15 ) >>1 ) { +switch ((decode->b &15 ) >>1 ) {case 0 :/* cmovo */ no_wb = (_eflags &EFLG_OF ) ?0 :1 ;break ;
@@ -1442,46 +1508,54 @@ twobyte_insn:break ; }/* Odd cmov opcodes (lsb == 1) have inverted sense. */ - no_wb ^= b &1 ; + no_wb ^= decode->b &1 ;break ;case 0xa3 : bt:/* bt */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("bt" , src, dst, _eflags); +/* only subword offset */ + decode->src.val &= (decode->dst.bytes <<3 ) -1 ; +emulate_2op_SrcV_nobyte ("bt" , + decode->src, decode->dst, _eflags);break ;case 0xab : bts:/* bts */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("bts" , src, dst, _eflags); +/* only subword offset */ + decode->src.val &= (decode->dst.bytes <<3 ) -1 ; +emulate_2op_SrcV_nobyte ("bts" , + decode->src, decode->dst, _eflags);break ; case 0xb0 ... 0xb1: /* cmpxchg *//* * Save real source value, then compare EAX against * destination. */ - src.orig_val = src.val; - src.val = _regs[VCPU_REGS_RAX ]; -emulate_2op_SrcV ("cmp" , src, dst, _eflags); + decode->src.orig_val = decode->src.val; + decode->src.val = decode->regs[VCPU_REGS_RAX ]; +emulate_2op_SrcV ("cmp" , decode->src, decode->dst, _eflags);if (_eflags &EFLG_ZF ) {/* Success: write back to memory. */ - dst.val = src.orig_val; + decode->dst.val = decode->src.orig_val; }else {/* Failure: write the value we saw to EAX. */ - dst.type =OP_REG ; - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; + decode->dst.type =OP_REG ; + decode->dst.ptr = + (unsigned long *)&decode->regs[VCPU_REGS_RAX ]; }break ;case 0xb3 : btr:/* btr */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("btr" , src, dst, _eflags); +/* only subword offset */ + decode->src.val &= (decode->dst.bytes <<3 ) -1 ; +emulate_2op_SrcV_nobyte ("btr" , + decode->src, decode->dst, _eflags);break ; case 0xb6 ... 0xb7: /* movzx */ - dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (u8 ) src.val : (u16 ) src.val; + decode->dst.bytes = decode->op_bytes; + decode->dst.val = (decode->d & ByteOp) ? (u8 ) decode->src.val + : (u16 ) decode->src.val;break ;case 0xba :/* Grp8 */ -switch (modrm_reg &3 ) { +switch (decode->modrm_reg &3 ) {case 0 : goto bt;case 1 :
@@ -1494,12 +1568,15 @@ twobyte_insn:break ;case 0xbb : btc:/* btc */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("btc" , src, dst, _eflags); +/* only subword offset */ + decode->src.val &= (decode->dst.bytes <<3 ) -1 ; +emulate_2op_SrcV_nobyte ("btc" , + decode->src, decode->dst, _eflags);break ; case 0xbe ... 0xbf: /* movsx */ - dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (s8 ) src.val : (s16 ) src.val; + decode->dst.bytes = decode->op_bytes; + decode->dst.val = (decode->d & ByteOp) ? (s8 ) decode->src.val : + (s16 ) decode->src.val;break ; } goto writeback;
@@ -1507,7 +1584,7 @@ twobyte_insn: twobyte_special_insn:/* Disable writeback. */ no_wb =1 ; -switch (b) { +switch (decode->b) {case 0x06 :emulate_clts (ctxt->vcpu);break ;
@@ -1517,56 +1594,60 @@ twobyte_special_insn:case 0x18 :/* Grp16 (prefetch/nop) */ break ;case 0x20 :/* mov cr, reg */ -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; - _regs[modrm_rm] =realmode_get_cr (ctxt->vcpu, modrm_reg); + decode->regs[decode->modrm_rm] = +realmode_get_cr (ctxt->vcpu, decode->modrm_reg);break ;case 0x22 :/* mov reg, cr */ -if (modrm_mod !=3 ) +if (decode->modrm_mod !=3 ) goto cannot_emulate; -realmode_set_cr (ctxt->vcpu, modrm_reg, modrm_val, &_eflags); +realmode_set_cr (ctxt->vcpu, + decode->modrm_reg, decode->modrm_val, &_eflags);break ;case 0x30 :/* wrmsr */ - msr_data = (u32 )_regs[VCPU_REGS_RAX ] - | ((u64 )_regs[VCPU_REGS_RDX ] <<32 ); - rc =kvm_set_msr (ctxt->vcpu, _regs[VCPU_REGS_RCX ], msr_data); + msr_data = (u32 )decode->regs[VCPU_REGS_RAX ] + | ((u64 )decode->regs[VCPU_REGS_RDX ] <<32 ); + rc =kvm_set_msr (ctxt->vcpu, + decode->regs[VCPU_REGS_RCX ], msr_data);if (rc) { kvm_x86_ops->inject_gp (ctxt->vcpu,0 ); - _eip = ctxt->vcpu->rip; + decode->eip = ctxt->vcpu->rip; } rc =X86EMUL_CONTINUE ;break ;case 0x32 :/* rdmsr */ - rc =kvm_get_msr (ctxt->vcpu, _regs[VCPU_REGS_RCX ], &msr_data); + rc =kvm_get_msr (ctxt->vcpu, + decode->regs[VCPU_REGS_RCX ], &msr_data);if (rc) { kvm_x86_ops->inject_gp (ctxt->vcpu,0 ); - _eip = ctxt->vcpu->rip; + decode->eip = ctxt->vcpu->rip; }else { - _regs[VCPU_REGS_RAX ] = (u32 )msr_data; - _regs[VCPU_REGS_RDX ] = msr_data >>32 ; + decode->regs[VCPU_REGS_RAX ] = (u32 )msr_data; + decode->regs[VCPU_REGS_RDX ] = msr_data >>32 ; } rc =X86EMUL_CONTINUE ;break ; case 0x80 ... 0x8f: /* jnz rel, etc*/ {long int rel; -switch (op_bytes) { +switch (decode->op_bytes) {case 2 : - rel =insn_fetch (s16,2 , _eip); + rel =insn_fetch (s16,2 , decode->eip);break ;case 4 : - rel =insn_fetch (s32,4 , _eip); + rel =insn_fetch (s32,4 , decode->eip);break ;case 8 : - rel =insn_fetch (s64,8 , _eip); + rel =insn_fetch (s64,8 , decode->eip);break ;default :DPRINTF ("jnz: Invalid op_bytes\n" ); goto cannot_emulate; } -if (test_cc (b, _eflags)) +if (test_cc (decode->b, _eflags))JMP_REL (rel);break ; }
@@ -1576,14 +1657,16 @@ twobyte_special_insn:if ((rc = ops->read_emulated (cr2, &old,8 , ctxt->vcpu)) !=0 ) goto done; -if (((u32) (old >>0 ) != (u32 ) _regs[VCPU_REGS_RAX ]) || - ((u32) (old >>32 ) != (u32 ) _regs[VCPU_REGS_RDX ])) { - _regs[VCPU_REGS_RAX ] = (u32) (old >>0 ); - _regs[VCPU_REGS_RDX ] = (u32) (old >>32 ); +if (((u32) (old >>0 ) != + (u32 ) decode->regs[VCPU_REGS_RAX ]) || + ((u32) (old >>32 ) != + (u32 ) decode->regs[VCPU_REGS_RDX ])) { + decode->regs[VCPU_REGS_RAX ] = (u32) (old >>0 ); + decode->regs[VCPU_REGS_RDX ] = (u32) (old >>32 ); _eflags &= ~EFLG_ZF ; }else { - new = ((u64 )_regs[VCPU_REGS_RCX ] <<32 ) - | (u32 ) _regs[VCPU_REGS_RBX ]; + new = ((u64 )decode->regs[VCPU_REGS_RCX ] <<32 ) + | (u32 ) decode->regs[VCPU_REGS_RBX ];if ((rc = ops->cmpxchg_emulated (cr2, &old, &new,8 , ctxt->vcpu)) !=0 ) goto done;
@@ -1595,6 +1678,6 @@ twobyte_special_insn: goto writeback; cannot_emulate: -DPRINTF ("Cannot emulate %02x\n" , b); +DPRINTF ("Cannot emulate %02x\n" , decode->b);return -1 ; }
drivers/kvm/x86_emulate.h +34 -0
@@ -112,6 +112,36 @@ struct x86_emulate_ops { }; +/* Type, address-of, and value of an instruction's operand. */ +struct operand { +enum {OP_REG ,OP_MEM ,OP_IMM } type; +unsigned int bytes; +unsigned long val, orig_val, *ptr; +}; + +struct decode_cache { +u8 twobyte; +u8 b; +u8 lock_prefix; +u8 rep_prefix; +u8 op_bytes; +u8 ad_bytes; +struct operand src; +struct operand dst; +unsigned long *override_base; +unsigned int d; +unsigned long regs[NR_VCPU_REGS ]; +unsigned long eip; +/* modrm */ +u8 modrm; +u8 modrm_mod; +u8 modrm_reg; +u8 modrm_rm; +u8 use_modrm_ea; +unsigned long modrm_ea; +unsigned long modrm_val; +}; +struct x86_emulate_ctxt {/* Register state before/after emulation. */ struct kvm_vcpu *vcpu;
@@ -129,6 +159,10 @@ struct x86_emulate_ctxt {unsigned long ss_base;unsigned long gs_base;unsigned long fs_base; + +/* decode cache */ + +struct decode_cache decode; };/* Execution mode, passed to the emulator. */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel