[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge with ia64 tree
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1201030012 0 # Node ID 087c2b76d360021657dea9fb3b5573c86572d589 # Parent b79802517a75a23abb88eda900ff802810a6add6 # Parent 7eafc6e841882426d1c1830f31f8a48b5e842e4b Merge with ia64 tree --- xen/arch/x86/Rules.mk | 2 xen/arch/x86/hvm/vmx/realmode.c | 60 +++++++++++++ xen/arch/x86/x86_emulate.c | 173 ++++++++++++++++++++++++++------------ xen/include/asm-x86/x86_emulate.h | 43 +++++++++ 4 files changed, 226 insertions(+), 52 deletions(-) diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/Rules.mk --- a/xen/arch/x86/Rules.mk Tue Jan 22 09:04:41 2008 -0700 +++ b/xen/arch/x86/Rules.mk Tue Jan 22 19:26:52 2008 +0000 @@ -11,7 +11,7 @@ xenoprof := y # pae ?= n supervisor_mode_kernel ?= n -vmxassist ?= y +vmxassist ?= n ifeq ($(vmxassist),y) CFLAGS += -DVMXASSIST diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/hvm/vmx/realmode.c --- a/xen/arch/x86/hvm/vmx/realmode.c Tue Jan 22 09:04:41 2008 -0700 +++ b/xen/arch/x86/hvm/vmx/realmode.c Tue Jan 22 19:26:52 2008 +0000 @@ -221,6 +221,64 @@ realmode_emulate_cmpxchg( { /* Fix this in case the guest is really relying on r-m-w atomicity. */ return realmode_emulate_write(seg, offset, new, bytes, ctxt); +} + +static int +realmode_rep_ins( + uint16_t src_port, + enum x86_segment dst_seg, + unsigned long dst_offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct realmode_emulate_ctxt *rm_ctxt = + container_of(ctxt, struct realmode_emulate_ctxt, ctxt); + struct vcpu *curr = current; + uint32_t paddr = rm_ctxt->seg_reg[dst_seg].base + dst_offset; + + if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) + return X86EMUL_UNHANDLEABLE; + + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + { + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_pio_req(src_port, *reps, bytes_per_rep, + paddr, IOREQ_READ, + !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1); + } + + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + return X86EMUL_RETRY; + + curr->arch.hvm_vmx.real_mode_io_completed = 0; + + return X86EMUL_OKAY; +} + +static int +realmode_rep_outs( + enum x86_segment src_seg, + unsigned long src_offset, + uint16_t dst_port, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct realmode_emulate_ctxt *rm_ctxt = + container_of(ctxt, struct realmode_emulate_ctxt, ctxt); + struct vcpu *curr = current; + uint32_t paddr = rm_ctxt->seg_reg[src_seg].base + src_offset; + + if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) + return X86EMUL_UNHANDLEABLE; + + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_pio_req(dst_port, *reps, bytes_per_rep, + paddr, IOREQ_WRITE, + !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1); + + return X86EMUL_OKAY; } static int @@ -420,6 +478,8 @@ static struct x86_emulate_ops realmode_e .insn_fetch = realmode_emulate_insn_fetch, .write = realmode_emulate_write, .cmpxchg = realmode_emulate_cmpxchg, + .rep_ins = realmode_rep_ins, + .rep_outs = realmode_rep_outs, .read_segment = realmode_read_segment, .write_segment = realmode_write_segment, .read_io = realmode_read_io, diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Tue Jan 22 09:04:41 2008 -0700 +++ b/xen/arch/x86/x86_emulate.c Tue Jan 22 19:26:52 2008 +0000 @@ -552,7 +552,7 @@ do { ? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \ } while (0) -static int __handle_rep_prefix( +static unsigned long __get_rep_prefix( struct cpu_user_regs *int_regs, struct cpu_user_regs *ext_regs, int ad_bytes) @@ -561,11 +561,36 @@ static int __handle_rep_prefix( (ad_bytes == 4) ? (uint32_t)int_regs->ecx : int_regs->ecx); - if ( ecx-- == 0 ) - { + /* Skip the instruction if no repetitions are required. */ + if ( ecx == 0 ) ext_regs->eip = int_regs->eip; - return 1; - } + + return ecx; +} + +#define get_rep_prefix() ({ \ + unsigned long max_reps = 1; \ + if ( rep_prefix ) \ + max_reps = __get_rep_prefix(&_regs, ctxt->regs, ad_bytes); \ + if ( max_reps == 0 ) \ + goto done; \ + max_reps; \ +}) + +static void __put_rep_prefix( + struct cpu_user_regs *int_regs, + struct cpu_user_regs *ext_regs, + int ad_bytes, + unsigned long reps_completed) +{ + unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx : + (ad_bytes == 4) ? (uint32_t)int_regs->ecx : + int_regs->ecx); + + /* Reduce counter appropriately, and repeat instruction if non-zero. */ + ecx -= reps_completed; + if ( ecx != 0 ) + int_regs->eip = ext_regs->eip; if ( ad_bytes == 2 ) *(uint16_t *)&int_regs->ecx = ecx; @@ -573,15 +598,12 @@ static int __handle_rep_prefix( int_regs->ecx = (uint32_t)ecx; else int_regs->ecx = ecx; - int_regs->eip = ext_regs->eip; - return 0; } -#define handle_rep_prefix() \ -do { \ - if ( rep_prefix && __handle_rep_prefix(&_regs, ctxt->regs, ad_bytes) ) \ - goto done; \ -} while (0) +#define put_rep_prefix(reps_completed) ({ \ + if ( rep_prefix ) \ + __put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \ +}) /* * Unsigned multiplication with double-word result. @@ -2051,35 +2073,63 @@ x86_emulate( dst.mem.off = sp_pre_dec(dst.bytes); break; - case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ - handle_rep_prefix(); + case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ { + unsigned long nr_reps = get_rep_prefix(); generate_exception_if(!mode_iopl(), EXC_GP); - dst.type = OP_MEM; dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - fail_if(ops->read_io == NULL); - if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes, - &dst.val, ctxt)) != 0 ) - goto done; + if ( (nr_reps > 1) && (ops->rep_ins != NULL) ) + { + if ( (rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg, + dst.mem.off, dst.bytes, + &nr_reps, ctxt)) != 0 ) + goto done; + } + else + { + fail_if(ops->read_io == NULL); + if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes, + &dst.val, ctxt)) != 0 ) + goto done; + dst.type = OP_MEM; + nr_reps = 1; + } register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; - - case 0x6e ... 0x6f: /* outs %esi,%dx */ - handle_rep_prefix(); + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); + break; + } + + case 0x6e ... 0x6f: /* outs %esi,%dx */ { + unsigned long nr_reps = get_rep_prefix(); generate_exception_if(!mode_iopl(), EXC_GP); dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; - if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), - &dst.val, dst.bytes, ctxt)) != 0 ) - goto done; - fail_if(ops->write_io == NULL); - if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes, - dst.val, ctxt)) != 0 ) - goto done; + if ( (nr_reps > 1) && (ops->rep_outs != NULL) ) + { + if ( (rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi), + (uint16_t)_regs.edx, dst.bytes, + &nr_reps, ctxt)) != 0 ) + goto done; + } + else + { + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), + &dst.val, dst.bytes, ctxt)) != 0 ) + goto done; + fail_if(ops->write_io == NULL); + if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes, + dst.val, ctxt)) != 0 ) + goto done; + nr_reps = 1; + } register_address_increment( - _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; + _regs.esi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); + break; + } case 0x70 ... 0x7f: /* jcc (short) */ { int rel = insn_fetch_type(int8_t); @@ -2202,24 +2252,39 @@ x86_emulate( dst.val = (unsigned long)_regs.eax; break; - case 0xa4 ... 0xa5: /* movs */ - handle_rep_prefix(); - dst.type = OP_MEM; + case 0xa4 ... 0xa5: /* movs */ { + unsigned long nr_reps = get_rep_prefix(); dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), - &dst.val, dst.bytes, ctxt)) != 0 ) - goto done; + if ( (nr_reps > 1) && (ops->rep_movs != NULL) ) + { + if ( (rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi), + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) != 0 ) + goto done; + } + else + { + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), + &dst.val, dst.bytes, ctxt)) != 0 ) + goto done; + dst.type = OP_MEM; + nr_reps = 1; + } register_address_increment( - _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); + _regs.esi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); + break; + } case 0xa6 ... 0xa7: /* cmps */ { unsigned long next_eip = _regs.eip; - handle_rep_prefix(); + get_rep_prefix(); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt)) || @@ -2230,6 +2295,7 @@ x86_emulate( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); register_address_increment( _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes); + put_rep_prefix(1); /* cmp: dst - src ==> src=*%%edi,dst=*%%esi ==> *%%esi - *%%edi */ emulate_2op_SrcV("cmp", src, dst, _regs.eflags); if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) || @@ -2238,8 +2304,8 @@ x86_emulate( break; } - case 0xaa ... 0xab: /* stos */ - handle_rep_prefix(); + case 0xaa ... 0xab: /* stos */ { + /* unsigned long max_reps = */get_rep_prefix(); dst.type = OP_MEM; dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; @@ -2247,10 +2313,12 @@ x86_emulate( dst.val = _regs.eax; register_address_increment( _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; - - case 0xac ... 0xad: /* lods */ - handle_rep_prefix(); + put_rep_prefix(1); + break; + } + + case 0xac ... 0xad: /* lods */ { + /* unsigned long max_reps = */get_rep_prefix(); dst.type = OP_REG; dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.reg = (unsigned long *)&_regs.eax; @@ -2259,11 +2327,13 @@ x86_emulate( goto done; register_address_increment( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - break; + put_rep_prefix(1); + break; + } case 0xae ... 0xaf: /* scas */ { unsigned long next_eip = _regs.eip; - handle_rep_prefix(); + get_rep_prefix(); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.val = _regs.eax; if ( (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi), @@ -2271,6 +2341,7 @@ x86_emulate( goto done; register_address_increment( _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes); + put_rep_prefix(1); /* cmp: dst - src ==> src=*%%edi,dst=%%eax ==> %%eax - *%%edi */ emulate_2op_SrcV("cmp", src, dst, _regs.eflags); if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) || diff -r b79802517a75 -r 087c2b76d360 xen/include/asm-x86/x86_emulate.h --- a/xen/include/asm-x86/x86_emulate.h Tue Jan 22 09:04:41 2008 -0700 +++ b/xen/include/asm-x86/x86_emulate.h Tue Jan 22 19:26:52 2008 +0000 @@ -175,6 +175,49 @@ struct x86_emulate_ops struct x86_emulate_ctxt *ctxt); /* + * rep_ins: Emulate INS: <src_port> -> <dst_seg:dst_offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_ins)( + uint16_t src_port, + enum x86_segment dst_seg, + unsigned long dst_offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* + * rep_outs: Emulate OUTS: <src_seg:src_offset> -> <dst_port>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_outs)( + enum x86_segment src_seg, + unsigned long src_offset, + uint16_t dst_port, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* + * rep_movs: Emulate MOVS: <src_seg:src_offset> -> <dst_seg:dst_offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_movs)( + enum x86_segment src_seg, + unsigned long src_offset, + enum x86_segment dst_seg, + unsigned long dst_offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* * read_segment: Emulate a read of full context of a segment register. * @reg: [OUT] Contents of segment register (visible and hidden state). */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |