ia64/xen-unstable

changeset 16852:087c2b76d360

Merge with ia64 tree
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jan 22 19:26:52 2008 +0000 (2008-01-22)
parents b79802517a75 7eafc6e84188
children 470e9dc0afc2
files
line diff
     1.1 --- a/xen/arch/x86/Rules.mk	Tue Jan 22 09:04:41 2008 -0700
     1.2 +++ b/xen/arch/x86/Rules.mk	Tue Jan 22 19:26:52 2008 +0000
     1.3 @@ -11,7 +11,7 @@ xenoprof := y
     1.4  #
     1.5  pae ?= n
     1.6  supervisor_mode_kernel ?= n
     1.7 -vmxassist ?= y
     1.8 +vmxassist ?= n
     1.9  
    1.10  ifeq ($(vmxassist),y)
    1.11  CFLAGS += -DVMXASSIST
     2.1 --- a/xen/arch/x86/hvm/vmx/realmode.c	Tue Jan 22 09:04:41 2008 -0700
     2.2 +++ b/xen/arch/x86/hvm/vmx/realmode.c	Tue Jan 22 19:26:52 2008 +0000
     2.3 @@ -223,6 +223,64 @@ realmode_emulate_cmpxchg(
     2.4      return realmode_emulate_write(seg, offset, new, bytes, ctxt);
     2.5  }
     2.6  
     2.7 +static int 
     2.8 +realmode_rep_ins(
     2.9 +    uint16_t src_port,
    2.10 +    enum x86_segment dst_seg,
    2.11 +    unsigned long dst_offset,
    2.12 +    unsigned int bytes_per_rep,
    2.13 +    unsigned long *reps,
    2.14 +    struct x86_emulate_ctxt *ctxt)
    2.15 +{
    2.16 +    struct realmode_emulate_ctxt *rm_ctxt =
    2.17 +        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
    2.18 +    struct vcpu *curr = current;
    2.19 +    uint32_t paddr = rm_ctxt->seg_reg[dst_seg].base + dst_offset;
    2.20 +
    2.21 +    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.22 +        return X86EMUL_UNHANDLEABLE;
    2.23 +
    2.24 +    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
    2.25 +    {
    2.26 +        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
    2.27 +        send_pio_req(src_port, *reps, bytes_per_rep,
    2.28 +                     paddr, IOREQ_READ,
    2.29 +                     !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
    2.30 +    }
    2.31 +
    2.32 +    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
    2.33 +        return X86EMUL_RETRY;
    2.34 +
    2.35 +    curr->arch.hvm_vmx.real_mode_io_completed = 0;
    2.36 +
    2.37 +    return X86EMUL_OKAY;
    2.38 +}
    2.39 +
    2.40 +static int 
    2.41 +realmode_rep_outs(
    2.42 +    enum x86_segment src_seg,
    2.43 +    unsigned long src_offset,
    2.44 +    uint16_t dst_port,
    2.45 +    unsigned int bytes_per_rep,
    2.46 +    unsigned long *reps,
    2.47 +    struct x86_emulate_ctxt *ctxt)
    2.48 +{
    2.49 +    struct realmode_emulate_ctxt *rm_ctxt =
    2.50 +        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
    2.51 +    struct vcpu *curr = current;
    2.52 +    uint32_t paddr = rm_ctxt->seg_reg[src_seg].base + src_offset;
    2.53 +
    2.54 +    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.55 +        return X86EMUL_UNHANDLEABLE;
    2.56 +
    2.57 +    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
    2.58 +    send_pio_req(dst_port, *reps, bytes_per_rep,
    2.59 +                 paddr, IOREQ_WRITE,
    2.60 +                 !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
    2.61 +
    2.62 +    return X86EMUL_OKAY;
    2.63 +}
    2.64 +
    2.65  static int
    2.66  realmode_read_segment(
    2.67      enum x86_segment seg,
    2.68 @@ -420,6 +478,8 @@ static struct x86_emulate_ops realmode_e
    2.69      .insn_fetch    = realmode_emulate_insn_fetch,
    2.70      .write         = realmode_emulate_write,
    2.71      .cmpxchg       = realmode_emulate_cmpxchg,
    2.72 +    .rep_ins       = realmode_rep_ins,
    2.73 +    .rep_outs      = realmode_rep_outs,
    2.74      .read_segment  = realmode_read_segment,
    2.75      .write_segment = realmode_write_segment,
    2.76      .read_io       = realmode_read_io,
     3.1 --- a/xen/arch/x86/x86_emulate.c	Tue Jan 22 09:04:41 2008 -0700
     3.2 +++ b/xen/arch/x86/x86_emulate.c	Tue Jan 22 19:26:52 2008 +0000
     3.3 @@ -552,7 +552,7 @@ do {                                    
     3.4                       ? (uint16_t)_regs.eip : (uint32_t)_regs.eip);      \
     3.5  } while (0)
     3.6  
     3.7 -static int __handle_rep_prefix(
     3.8 +static unsigned long __get_rep_prefix(
     3.9      struct cpu_user_regs *int_regs,
    3.10      struct cpu_user_regs *ext_regs,
    3.11      int ad_bytes)
    3.12 @@ -561,11 +561,36 @@ static int __handle_rep_prefix(
    3.13                           (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
    3.14                           int_regs->ecx);
    3.15  
    3.16 -    if ( ecx-- == 0 )
    3.17 -    {
    3.18 +    /* Skip the instruction if no repetitions are required. */
    3.19 +    if ( ecx == 0 )
    3.20          ext_regs->eip = int_regs->eip;
    3.21 -        return 1;
    3.22 -    }
    3.23 +
    3.24 +    return ecx;
    3.25 +}
    3.26 +
    3.27 +#define get_rep_prefix() ({                                             \
    3.28 +    unsigned long max_reps = 1;                                         \
    3.29 +    if ( rep_prefix )                                                   \
    3.30 +        max_reps = __get_rep_prefix(&_regs, ctxt->regs, ad_bytes);      \
    3.31 +    if ( max_reps == 0 )                                                \
    3.32 +        goto done;                                                      \
    3.33 +   max_reps;                                                            \
    3.34 +})
    3.35 +
    3.36 +static void __put_rep_prefix(
    3.37 +    struct cpu_user_regs *int_regs,
    3.38 +    struct cpu_user_regs *ext_regs,
    3.39 +    int ad_bytes,
    3.40 +    unsigned long reps_completed)
    3.41 +{
    3.42 +    unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx :
    3.43 +                         (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
    3.44 +                         int_regs->ecx);
    3.45 +
    3.46 +    /* Reduce counter appropriately, and repeat instruction if non-zero. */
    3.47 +    ecx -= reps_completed;
    3.48 +    if ( ecx != 0 )
    3.49 +        int_regs->eip = ext_regs->eip;
    3.50  
    3.51      if ( ad_bytes == 2 )
    3.52          *(uint16_t *)&int_regs->ecx = ecx;
    3.53 @@ -573,15 +598,12 @@ static int __handle_rep_prefix(
    3.54          int_regs->ecx = (uint32_t)ecx;
    3.55      else
    3.56          int_regs->ecx = ecx;
    3.57 -    int_regs->eip = ext_regs->eip;
    3.58 -    return 0;
    3.59  }
    3.60  
    3.61 -#define handle_rep_prefix()                                                \
    3.62 -do {                                                                       \
    3.63 -    if ( rep_prefix && __handle_rep_prefix(&_regs, ctxt->regs, ad_bytes) ) \
    3.64 -        goto done;                                                         \
    3.65 -} while (0)
    3.66 +#define put_rep_prefix(reps_completed) ({                               \
    3.67 +    if ( rep_prefix )                                                   \
    3.68 +        __put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \
    3.69 +})
    3.70  
    3.71  /*
    3.72   * Unsigned multiplication with double-word result.
    3.73 @@ -2051,35 +2073,63 @@ x86_emulate(
    3.74          dst.mem.off = sp_pre_dec(dst.bytes);
    3.75          break;
    3.76  
    3.77 -    case 0x6c ... 0x6d: /* ins %dx,%es:%edi */
    3.78 -        handle_rep_prefix();
    3.79 +    case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ {
    3.80 +        unsigned long nr_reps = get_rep_prefix();
    3.81          generate_exception_if(!mode_iopl(), EXC_GP);
    3.82 -        dst.type  = OP_MEM;
    3.83          dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
    3.84          dst.mem.seg = x86_seg_es;
    3.85          dst.mem.off = truncate_ea(_regs.edi);
    3.86 -        fail_if(ops->read_io == NULL);
    3.87 -        if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes,
    3.88 -                                &dst.val, ctxt)) != 0 )
    3.89 -            goto done;
    3.90 +        if ( (nr_reps > 1) && (ops->rep_ins != NULL) )
    3.91 +        {
    3.92 +            if ( (rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg,
    3.93 +                                    dst.mem.off, dst.bytes,
    3.94 +                                    &nr_reps, ctxt)) != 0 )
    3.95 +                goto done;
    3.96 +        }
    3.97 +        else
    3.98 +        {
    3.99 +            fail_if(ops->read_io == NULL);
   3.100 +            if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes,
   3.101 +                                    &dst.val, ctxt)) != 0 )
   3.102 +                goto done;
   3.103 +            dst.type = OP_MEM;
   3.104 +            nr_reps = 1;
   3.105 +        }
   3.106          register_address_increment(
   3.107 -            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.108 +            _regs.edi,
   3.109 +            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
   3.110 +        put_rep_prefix(nr_reps);
   3.111          break;
   3.112 +    }
   3.113  
   3.114 -    case 0x6e ... 0x6f: /* outs %esi,%dx */
   3.115 -        handle_rep_prefix();
   3.116 +    case 0x6e ... 0x6f: /* outs %esi,%dx */ {
   3.117 +        unsigned long nr_reps = get_rep_prefix();
   3.118          generate_exception_if(!mode_iopl(), EXC_GP);
   3.119          dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
   3.120 -        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
   3.121 -                             &dst.val, dst.bytes, ctxt)) != 0 )
   3.122 -            goto done;
   3.123 -        fail_if(ops->write_io == NULL);
   3.124 -        if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes,
   3.125 -                                 dst.val, ctxt)) != 0 )
   3.126 -            goto done;
   3.127 +        if ( (nr_reps > 1) && (ops->rep_outs != NULL) )
   3.128 +        {
   3.129 +            if ( (rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
   3.130 +                                     (uint16_t)_regs.edx, dst.bytes,
   3.131 +                                     &nr_reps, ctxt)) != 0 )
   3.132 +                goto done;
   3.133 +        }
   3.134 +        else
   3.135 +        {
   3.136 +            if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
   3.137 +                                 &dst.val, dst.bytes, ctxt)) != 0 )
   3.138 +                goto done;
   3.139 +            fail_if(ops->write_io == NULL);
   3.140 +            if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes,
   3.141 +                                     dst.val, ctxt)) != 0 )
   3.142 +                goto done;
   3.143 +            nr_reps = 1;
   3.144 +        }
   3.145          register_address_increment(
   3.146 -            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.147 +            _regs.esi,
   3.148 +            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
   3.149 +        put_rep_prefix(nr_reps);
   3.150          break;
   3.151 +    }
   3.152  
   3.153      case 0x70 ... 0x7f: /* jcc (short) */ {
   3.154          int rel = insn_fetch_type(int8_t);
   3.155 @@ -2202,24 +2252,39 @@ x86_emulate(
   3.156          dst.val   = (unsigned long)_regs.eax;
   3.157          break;
   3.158  
   3.159 -    case 0xa4 ... 0xa5: /* movs */
   3.160 -        handle_rep_prefix();
   3.161 -        dst.type  = OP_MEM;
   3.162 +    case 0xa4 ... 0xa5: /* movs */ {
   3.163 +        unsigned long nr_reps = get_rep_prefix();
   3.164          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   3.165          dst.mem.seg = x86_seg_es;
   3.166          dst.mem.off = truncate_ea(_regs.edi);
   3.167 -        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
   3.168 -                             &dst.val, dst.bytes, ctxt)) != 0 )
   3.169 -            goto done;
   3.170 +        if ( (nr_reps > 1) && (ops->rep_movs != NULL) )
   3.171 +        {
   3.172 +            if ( (rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
   3.173 +                                     dst.mem.seg, dst.mem.off, dst.bytes,
   3.174 +                                     &nr_reps, ctxt)) != 0 )
   3.175 +                goto done;
   3.176 +        }
   3.177 +        else
   3.178 +        {
   3.179 +            if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
   3.180 +                                 &dst.val, dst.bytes, ctxt)) != 0 )
   3.181 +                goto done;
   3.182 +            dst.type = OP_MEM;
   3.183 +            nr_reps = 1;
   3.184 +        }
   3.185          register_address_increment(
   3.186 -            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.187 +            _regs.esi,
   3.188 +            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
   3.189          register_address_increment(
   3.190 -            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.191 +            _regs.edi,
   3.192 +            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
   3.193 +        put_rep_prefix(nr_reps);
   3.194          break;
   3.195 +    }
   3.196  
   3.197      case 0xa6 ... 0xa7: /* cmps */ {
   3.198          unsigned long next_eip = _regs.eip;
   3.199 -        handle_rep_prefix();
   3.200 +        get_rep_prefix();
   3.201          src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   3.202          if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
   3.203                               &dst.val, dst.bytes, ctxt)) ||
   3.204 @@ -2230,6 +2295,7 @@ x86_emulate(
   3.205              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.206          register_address_increment(
   3.207              _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
   3.208 +        put_rep_prefix(1);
   3.209          /* cmp: dst - src ==> src=*%%edi,dst=*%%esi ==> *%%esi - *%%edi */
   3.210          emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
   3.211          if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
   3.212 @@ -2238,8 +2304,8 @@ x86_emulate(
   3.213          break;
   3.214      }
   3.215  
   3.216 -    case 0xaa ... 0xab: /* stos */
   3.217 -        handle_rep_prefix();
   3.218 +    case 0xaa ... 0xab: /* stos */ {
   3.219 +        /* unsigned long max_reps = */get_rep_prefix();
   3.220          dst.type  = OP_MEM;
   3.221          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   3.222          dst.mem.seg = x86_seg_es;
   3.223 @@ -2247,10 +2313,12 @@ x86_emulate(
   3.224          dst.val   = _regs.eax;
   3.225          register_address_increment(
   3.226              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.227 +        put_rep_prefix(1);
   3.228          break;
   3.229 +    }
   3.230  
   3.231 -    case 0xac ... 0xad: /* lods */
   3.232 -        handle_rep_prefix();
   3.233 +    case 0xac ... 0xad: /* lods */ {
   3.234 +        /* unsigned long max_reps = */get_rep_prefix();
   3.235          dst.type  = OP_REG;
   3.236          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   3.237          dst.reg   = (unsigned long *)&_regs.eax;
   3.238 @@ -2259,11 +2327,13 @@ x86_emulate(
   3.239              goto done;
   3.240          register_address_increment(
   3.241              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   3.242 +        put_rep_prefix(1);
   3.243          break;
   3.244 +    }
   3.245  
   3.246      case 0xae ... 0xaf: /* scas */ {
   3.247          unsigned long next_eip = _regs.eip;
   3.248 -        handle_rep_prefix();
   3.249 +        get_rep_prefix();
   3.250          src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   3.251          dst.val = _regs.eax;
   3.252          if ( (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
   3.253 @@ -2271,6 +2341,7 @@ x86_emulate(
   3.254              goto done;
   3.255          register_address_increment(
   3.256              _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
   3.257 +        put_rep_prefix(1);
   3.258          /* cmp: dst - src ==> src=*%%edi,dst=%%eax ==> %%eax - *%%edi */
   3.259          emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
   3.260          if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
     4.1 --- a/xen/include/asm-x86/x86_emulate.h	Tue Jan 22 09:04:41 2008 -0700
     4.2 +++ b/xen/include/asm-x86/x86_emulate.h	Tue Jan 22 19:26:52 2008 +0000
     4.3 @@ -175,6 +175,49 @@ struct x86_emulate_ops
     4.4          struct x86_emulate_ctxt *ctxt);
     4.5  
     4.6      /*
     4.7 +     * rep_ins: Emulate INS: <src_port> -> <dst_seg:dst_offset>.
     4.8 +     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
     4.9 +     *  @reps:  [IN ] Maximum repetitions to be emulated.
    4.10 +     *          [OUT] Number of repetitions actually emulated.
    4.11 +     */
    4.12 +    int (*rep_ins)(
    4.13 +        uint16_t src_port,
    4.14 +        enum x86_segment dst_seg,
    4.15 +        unsigned long dst_offset,
    4.16 +        unsigned int bytes_per_rep,
    4.17 +        unsigned long *reps,
    4.18 +        struct x86_emulate_ctxt *ctxt);
    4.19 +
    4.20 +    /*
    4.21 +     * rep_outs: Emulate OUTS: <src_seg:src_offset> -> <dst_port>.
    4.22 +     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
    4.23 +     *  @reps:  [IN ] Maximum repetitions to be emulated.
    4.24 +     *          [OUT] Number of repetitions actually emulated.
    4.25 +     */
    4.26 +    int (*rep_outs)(
    4.27 +        enum x86_segment src_seg,
    4.28 +        unsigned long src_offset,
    4.29 +        uint16_t dst_port,
    4.30 +        unsigned int bytes_per_rep,
    4.31 +        unsigned long *reps,
    4.32 +        struct x86_emulate_ctxt *ctxt);
    4.33 +
    4.34 +    /*
    4.35 +     * rep_movs: Emulate MOVS: <src_seg:src_offset> -> <dst_seg:dst_offset>.
    4.36 +     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
    4.37 +     *  @reps:  [IN ] Maximum repetitions to be emulated.
    4.38 +     *          [OUT] Number of repetitions actually emulated.
    4.39 +     */
    4.40 +    int (*rep_movs)(
    4.41 +        enum x86_segment src_seg,
    4.42 +        unsigned long src_offset,
    4.43 +        enum x86_segment dst_seg,
    4.44 +        unsigned long dst_offset,
    4.45 +        unsigned int bytes_per_rep,
    4.46 +        unsigned long *reps,
    4.47 +        struct x86_emulate_ctxt *ctxt);
    4.48 +
    4.49 +    /*
    4.50       * read_segment: Emulate a read of full context of a segment register.
    4.51       *  @reg:   [OUT] Contents of segment register (visible and hidden state).
    4.52       */