ia64/xen-unstable

changeset 17090:3f1cf03826fe

x86 hvm: Replace old MMIO emulator with x86_emulate()-based harness.
Re-factor VMX real-mode emulation to use the same harness.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 20 14:36:45 2008 +0000 (2008-02-20)
parents f853c0497095
children 6757307d1adc
files tools/ioemu/target-i386-dm/helper2.c xen/arch/x86/hvm/Makefile xen/arch/x86/hvm/emulate.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/instrlen.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/io.c xen/arch/x86/hvm/platform.c xen/arch/x86/hvm/stdvga.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/realmode.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/mm/shadow/multi.c xen/include/asm-x86/hvm/emulate.h xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/io.h xen/include/asm-x86/hvm/support.h xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h xen/include/public/hvm/ioreq.h
line diff
     1.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Tue Feb 19 11:14:40 2008 -0700
     1.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Wed Feb 20 14:36:45 2008 +0000
     1.3 @@ -379,82 +379,7 @@ void cpu_ioreq_move(CPUState *env, ioreq
     1.4      }
     1.5  }
     1.6  
     1.7 -void cpu_ioreq_and(CPUState *env, ioreq_t *req)
     1.8 -{
     1.9 -    target_ulong tmp1, tmp2;
    1.10 -
    1.11 -    if (req->data_is_ptr != 0)
    1.12 -        hw_error("expected scalar value");
    1.13 -
    1.14 -    read_physical(req->addr, req->size, &tmp1);
    1.15 -    if (req->dir == IOREQ_WRITE) {
    1.16 -        tmp2 = tmp1 & (target_ulong) req->data;
    1.17 -        write_physical(req->addr, req->size, &tmp2);
    1.18 -    }
    1.19 -    req->data = tmp1;
    1.20 -}
    1.21 -
    1.22 -void cpu_ioreq_add(CPUState *env, ioreq_t *req)
    1.23 -{
    1.24 -    target_ulong tmp1, tmp2;
    1.25 -
    1.26 -    if (req->data_is_ptr != 0)
    1.27 -        hw_error("expected scalar value");
    1.28 -
    1.29 -    read_physical(req->addr, req->size, &tmp1);
    1.30 -    if (req->dir == IOREQ_WRITE) {
    1.31 -        tmp2 = tmp1 + (target_ulong) req->data;
    1.32 -        write_physical(req->addr, req->size, &tmp2);
    1.33 -    }
    1.34 -    req->data = tmp1;
    1.35 -}
    1.36 -
    1.37 -void cpu_ioreq_sub(CPUState *env, ioreq_t *req)
    1.38 -{
    1.39 -    target_ulong tmp1, tmp2;
    1.40 -
    1.41 -    if (req->data_is_ptr != 0)
    1.42 -        hw_error("expected scalar value");
    1.43 -
    1.44 -    read_physical(req->addr, req->size, &tmp1);
    1.45 -    if (req->dir == IOREQ_WRITE) {
    1.46 -        tmp2 = tmp1 - (target_ulong) req->data;
    1.47 -        write_physical(req->addr, req->size, &tmp2);
    1.48 -    }
    1.49 -    req->data = tmp1;
    1.50 -}
    1.51 -
    1.52 -void cpu_ioreq_or(CPUState *env, ioreq_t *req)
    1.53 -{
    1.54 -    target_ulong tmp1, tmp2;
    1.55 -
    1.56 -    if (req->data_is_ptr != 0)
    1.57 -        hw_error("expected scalar value");
    1.58 -
    1.59 -    read_physical(req->addr, req->size, &tmp1);
    1.60 -    if (req->dir == IOREQ_WRITE) {
    1.61 -        tmp2 = tmp1 | (target_ulong) req->data;
    1.62 -        write_physical(req->addr, req->size, &tmp2);
    1.63 -    }
    1.64 -    req->data = tmp1;
    1.65 -}
    1.66 -
    1.67 -void cpu_ioreq_xor(CPUState *env, ioreq_t *req)
    1.68 -{
    1.69 -    target_ulong tmp1, tmp2;
    1.70 -
    1.71 -    if (req->data_is_ptr != 0)
    1.72 -        hw_error("expected scalar value");
    1.73 -
    1.74 -    read_physical(req->addr, req->size, &tmp1);
    1.75 -    if (req->dir == IOREQ_WRITE) {
    1.76 -        tmp2 = tmp1 ^ (target_ulong) req->data;
    1.77 -        write_physical(req->addr, req->size, &tmp2);
    1.78 -    }
    1.79 -    req->data = tmp1;
    1.80 -}
    1.81 -
    1.82 -void timeoffset_get()
    1.83 +void timeoffset_get(void)
    1.84  {
    1.85      char *p;
    1.86  
    1.87 @@ -483,18 +408,6 @@ void cpu_ioreq_timeoffset(CPUState *env,
    1.88      xenstore_vm_write(domid, "rtc/timeoffset", b);
    1.89  }
    1.90  
    1.91 -void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
    1.92 -{
    1.93 -    unsigned long tmp1;
    1.94 -
    1.95 -    if (req->data_is_ptr != 0)
    1.96 -        hw_error("expected scalar value");
    1.97 -
    1.98 -    read_physical(req->addr, req->size, &tmp1);
    1.99 -    write_physical(req->addr, req->size, &req->data);
   1.100 -    req->data = tmp1;
   1.101 -}
   1.102 -
   1.103  void __handle_ioreq(CPUState *env, ioreq_t *req)
   1.104  {
   1.105      if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
   1.106 @@ -508,24 +421,6 @@ void __handle_ioreq(CPUState *env, ioreq
   1.107      case IOREQ_TYPE_COPY:
   1.108          cpu_ioreq_move(env, req);
   1.109          break;
   1.110 -    case IOREQ_TYPE_AND:
   1.111 -        cpu_ioreq_and(env, req);
   1.112 -        break;
   1.113 -    case IOREQ_TYPE_ADD:
   1.114 -        cpu_ioreq_add(env, req);
   1.115 -        break;
   1.116 -    case IOREQ_TYPE_SUB:
   1.117 -        cpu_ioreq_sub(env, req);
   1.118 -        break;
   1.119 -    case IOREQ_TYPE_OR:
   1.120 -        cpu_ioreq_or(env, req);
   1.121 -        break;
   1.122 -    case IOREQ_TYPE_XOR:
   1.123 -        cpu_ioreq_xor(env, req);
   1.124 -        break;
   1.125 -    case IOREQ_TYPE_XCHG:
   1.126 -        cpu_ioreq_xchg(env, req);
   1.127 -        break;
   1.128      case IOREQ_TYPE_TIMEOFFSET:
   1.129          cpu_ioreq_timeoffset(env, req);
   1.130          break;
     2.1 --- a/xen/arch/x86/hvm/Makefile	Tue Feb 19 11:14:40 2008 -0700
     2.2 +++ b/xen/arch/x86/hvm/Makefile	Wed Feb 20 14:36:45 2008 +0000
     2.3 @@ -1,9 +1,9 @@
     2.4  subdir-y += svm
     2.5  subdir-y += vmx
     2.6  
     2.7 +obj-y += emulate.o
     2.8  obj-y += hvm.o
     2.9  obj-y += i8254.o
    2.10 -obj-y += instrlen.o
    2.11  obj-y += intercept.o
    2.12  obj-y += io.o
    2.13  obj-y += iommu.o
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/x86/hvm/emulate.c	Wed Feb 20 14:36:45 2008 +0000
     3.3 @@ -0,0 +1,755 @@
     3.4 +/******************************************************************************
     3.5 + * hvm/emulate.c
     3.6 + * 
     3.7 + * HVM instruction emulation. Used for MMIO and VMX real mode.
     3.8 + * 
     3.9 + * Copyright (c) 2008 Citrix Systems, Inc.
    3.10 + * 
    3.11 + * Authors:
    3.12 + *    Keir Fraser <keir.fraser@citrix.com>
    3.13 + */
    3.14 +
    3.15 +#include <xen/config.h>
    3.16 +#include <xen/init.h>
    3.17 +#include <xen/lib.h>
    3.18 +#include <xen/sched.h>
    3.19 +#include <xen/paging.h>
    3.20 +#include <asm/event.h>
    3.21 +#include <asm/hvm/emulate.h>
    3.22 +#include <asm/hvm/hvm.h>
    3.23 +#include <asm/hvm/support.h>
    3.24 +
    3.25 +/*
    3.26 + * Convert addr from linear to physical form, valid over the range
    3.27 + * [addr, addr + *reps * bytes_per_rep]. *reps is adjusted according to
    3.28 + * the valid computed range. It is always >0 when X86EMUL_OKAY is returned.
    3.29 + */
    3.30 +static int hvmemul_linear_to_phys(
    3.31 +    unsigned long addr,
    3.32 +    paddr_t *paddr,
    3.33 +    unsigned int bytes_per_rep,
    3.34 +    unsigned long *reps,
    3.35 +    enum hvm_access_type access_type,
    3.36 +    struct hvm_emulate_ctxt *hvmemul_ctxt)
    3.37 +{
    3.38 +    struct vcpu *curr = current;
    3.39 +    unsigned long pfn, npfn, done, todo, i;
    3.40 +    struct segment_register *sreg;
    3.41 +    uint32_t pfec;
    3.42 +
    3.43 +    /* Clip repetitions to a sensible maximum. */
    3.44 +    *reps = min_t(unsigned long, *reps, 4096);
    3.45 +
    3.46 +    /* With no paging it's easy: linear == physical. */
    3.47 +    if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG) )
    3.48 +    {
    3.49 +        *paddr = addr;
    3.50 +        return X86EMUL_OKAY;
    3.51 +    }
    3.52 +
    3.53 +    *paddr = addr & ~PAGE_MASK;
    3.54 +
    3.55 +    /* Gather access-type information for the page walks. */
    3.56 +    sreg = hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt);
    3.57 +    pfec = PFEC_page_present;
    3.58 +    if ( sreg->attr.fields.dpl == 3 )
    3.59 +        pfec |= PFEC_user_mode;
    3.60 +    if ( access_type == hvm_access_write )
    3.61 +        pfec |= PFEC_write_access;
    3.62 +
    3.63 +    /* Get the first PFN in the range. */
    3.64 +    if ( (pfn = paging_gva_to_gfn(curr, addr, &pfec)) == INVALID_GFN )
    3.65 +    {
    3.66 +        hvm_inject_exception(TRAP_page_fault, pfec, addr);
    3.67 +        return X86EMUL_EXCEPTION;
    3.68 +    }
    3.69 +
    3.70 +    /* If the range does not straddle a page boundary then we're done. */
    3.71 +    done = PAGE_SIZE - (addr & ~PAGE_MASK);
    3.72 +    todo = *reps * bytes_per_rep;
    3.73 +    if ( done >= todo )
    3.74 +        goto done;
    3.75 +
    3.76 +    addr += done;
    3.77 +    for ( i = 1; done < todo; i++ )
    3.78 +    {
    3.79 +        /* Get the next PFN in the range. */
    3.80 +        if ( (npfn = paging_gva_to_gfn(curr, addr, &pfec)) == INVALID_GFN )
    3.81 +        {
    3.82 +            hvm_inject_exception(TRAP_page_fault, pfec, addr);
    3.83 +            return X86EMUL_EXCEPTION;
    3.84 +        }
    3.85 +
    3.86 +        /* Is it contiguous with the preceding PFNs? If not then we're done. */
    3.87 +        if ( npfn != (pfn + i) )
    3.88 +        {
    3.89 +            done /= bytes_per_rep;
    3.90 +            if ( done == 0 )
    3.91 +                return X86EMUL_UNHANDLEABLE;
    3.92 +            *reps = done;
    3.93 +            break;
    3.94 +        }
    3.95 +
    3.96 +        addr += PAGE_SIZE;
    3.97 +        done += PAGE_SIZE;
    3.98 +    }
    3.99 +
   3.100 + done:
   3.101 +    *paddr |= (paddr_t)pfn << PAGE_SHIFT;
   3.102 +    return X86EMUL_OKAY;
   3.103 +}
   3.104 +    
   3.105 +
   3.106 +static int hvmemul_virtual_to_linear(
   3.107 +    enum x86_segment seg,
   3.108 +    unsigned long offset,
   3.109 +    unsigned int bytes,
   3.110 +    enum hvm_access_type access_type,
   3.111 +    struct hvm_emulate_ctxt *hvmemul_ctxt,
   3.112 +    unsigned long *paddr)
   3.113 +{
   3.114 +    struct segment_register *reg;
   3.115 +    int okay;
   3.116 +
   3.117 +    if ( seg == x86_seg_none )
   3.118 +    {
   3.119 +        *paddr = offset;
   3.120 +        return X86EMUL_OKAY;
   3.121 +    }
   3.122 +
   3.123 +    reg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
   3.124 +    okay = hvm_virtual_to_linear_addr(
   3.125 +        seg, reg, offset, bytes, access_type,
   3.126 +        hvmemul_ctxt->ctxt.addr_size, paddr);
   3.127 +
   3.128 +    if ( !okay )
   3.129 +    {
   3.130 +        hvmemul_ctxt->flags.exn_pending = 1;
   3.131 +        hvmemul_ctxt->exn_vector = TRAP_gp_fault;
   3.132 +        hvmemul_ctxt->exn_insn_len = 0;
   3.133 +        return X86EMUL_EXCEPTION;
   3.134 +    }
   3.135 +
   3.136 +    return X86EMUL_OKAY;
   3.137 +}
   3.138 +
   3.139 +static int __hvmemul_read(
   3.140 +    enum x86_segment seg,
   3.141 +    unsigned long offset,
   3.142 +    unsigned long *val,
   3.143 +    unsigned int bytes,
   3.144 +    enum hvm_access_type access_type,
   3.145 +    struct hvm_emulate_ctxt *hvmemul_ctxt)
   3.146 +{
   3.147 +    unsigned long addr;
   3.148 +    int rc;
   3.149 +
   3.150 +    rc = hvmemul_virtual_to_linear(
   3.151 +        seg, offset, bytes, access_type, hvmemul_ctxt, &addr);
   3.152 +    if ( rc != X86EMUL_OKAY )
   3.153 +        return rc;
   3.154 +
   3.155 +    *val = 0;
   3.156 +
   3.157 +    rc = ((access_type == hvm_access_insn_fetch) ?
   3.158 +          hvm_fetch_from_guest_virt(val, addr, bytes) :
   3.159 +          hvm_copy_from_guest_virt(val, addr, bytes));
   3.160 +    if ( rc == HVMCOPY_bad_gva_to_gfn )
   3.161 +        return X86EMUL_EXCEPTION;
   3.162 +
   3.163 +    if ( rc == HVMCOPY_bad_gfn_to_mfn )
   3.164 +    {
   3.165 +        struct vcpu *curr = current;
   3.166 +        unsigned long reps = 1;
   3.167 +        paddr_t gpa;
   3.168 +
   3.169 +        if ( access_type == hvm_access_insn_fetch )
   3.170 +            return X86EMUL_UNHANDLEABLE;
   3.171 +
   3.172 +        rc = hvmemul_linear_to_phys(
   3.173 +            addr, &gpa, bytes, &reps, access_type, hvmemul_ctxt);
   3.174 +        if ( rc != X86EMUL_OKAY )
   3.175 +            return rc;
   3.176 +
   3.177 +        if ( curr->arch.hvm_vcpu.io_in_progress )
   3.178 +            return X86EMUL_UNHANDLEABLE;
   3.179 +
   3.180 +        if ( !curr->arch.hvm_vcpu.io_completed )
   3.181 +        {
   3.182 +            curr->arch.hvm_vcpu.io_in_progress = 1;
   3.183 +            send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, bytes,
   3.184 +                          0, IOREQ_READ, 0, 0);
   3.185 +        }
   3.186 +
   3.187 +        if ( !curr->arch.hvm_vcpu.io_completed )
   3.188 +            return X86EMUL_RETRY;
   3.189 +
   3.190 +        *val = curr->arch.hvm_vcpu.io_data;
   3.191 +        curr->arch.hvm_vcpu.io_completed = 0;
   3.192 +    }
   3.193 +
   3.194 +    return X86EMUL_OKAY;
   3.195 +}
   3.196 +
   3.197 +static int hvmemul_read(
   3.198 +    enum x86_segment seg,
   3.199 +    unsigned long offset,
   3.200 +    unsigned long *val,
   3.201 +    unsigned int bytes,
   3.202 +    struct x86_emulate_ctxt *ctxt)
   3.203 +{
   3.204 +    return __hvmemul_read(
   3.205 +        seg, offset, val, bytes, hvm_access_read,
   3.206 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt));
   3.207 +}
   3.208 +
   3.209 +static int hvmemul_insn_fetch(
   3.210 +    enum x86_segment seg,
   3.211 +    unsigned long offset,
   3.212 +    unsigned long *val,
   3.213 +    unsigned int bytes,
   3.214 +    struct x86_emulate_ctxt *ctxt)
   3.215 +{
   3.216 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.217 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.218 +    unsigned int insn_off = offset - hvmemul_ctxt->insn_buf_eip;
   3.219 +
   3.220 +    /* Fall back if requested bytes are not in the prefetch cache. */
   3.221 +    if ( unlikely((insn_off + bytes) > hvmemul_ctxt->insn_buf_bytes) )
   3.222 +        return __hvmemul_read(
   3.223 +            seg, offset, val, bytes,
   3.224 +            hvm_access_insn_fetch, hvmemul_ctxt);
   3.225 +
   3.226 +    /* Hit the cache. Simple memcpy. */
   3.227 +    *val = 0;
   3.228 +    memcpy(val, &hvmemul_ctxt->insn_buf[insn_off], bytes);
   3.229 +    return X86EMUL_OKAY;
   3.230 +}
   3.231 +
   3.232 +static int hvmemul_write(
   3.233 +    enum x86_segment seg,
   3.234 +    unsigned long offset,
   3.235 +    unsigned long val,
   3.236 +    unsigned int bytes,
   3.237 +    struct x86_emulate_ctxt *ctxt)
   3.238 +{
   3.239 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.240 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.241 +    unsigned long addr;
   3.242 +    int rc;
   3.243 +
   3.244 +    rc = hvmemul_virtual_to_linear(
   3.245 +        seg, offset, bytes, hvm_access_write, hvmemul_ctxt, &addr);
   3.246 +    if ( rc != X86EMUL_OKAY )
   3.247 +        return rc;
   3.248 +
   3.249 +    rc = hvm_copy_to_guest_virt(addr, &val, bytes);
   3.250 +    if ( rc == HVMCOPY_bad_gva_to_gfn )
   3.251 +        return X86EMUL_EXCEPTION;
   3.252 +
   3.253 +    if ( rc == HVMCOPY_bad_gfn_to_mfn )
   3.254 +    {
   3.255 +        struct vcpu *curr = current;
   3.256 +        unsigned long reps = 1;
   3.257 +        paddr_t gpa;
   3.258 +
   3.259 +        rc = hvmemul_linear_to_phys(
   3.260 +            addr, &gpa, bytes, &reps, hvm_access_write, hvmemul_ctxt);
   3.261 +        if ( rc != X86EMUL_OKAY )
   3.262 +            return rc;
   3.263 +
   3.264 +        if ( curr->arch.hvm_vcpu.io_in_progress )
   3.265 +            return X86EMUL_UNHANDLEABLE;
   3.266 +
   3.267 +        curr->arch.hvm_vcpu.io_in_progress = 1;
   3.268 +        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, bytes,
   3.269 +                      val, IOREQ_WRITE, 0, 0);
   3.270 +    }
   3.271 +
   3.272 +    return X86EMUL_OKAY;
   3.273 +}
   3.274 +
   3.275 +static int hvmemul_cmpxchg(
   3.276 +    enum x86_segment seg,
   3.277 +    unsigned long offset,
   3.278 +    unsigned long old,
   3.279 +    unsigned long new,
   3.280 +    unsigned int bytes,
   3.281 +    struct x86_emulate_ctxt *ctxt)
   3.282 +{
   3.283 +    /* Fix this in case the guest is really relying on r-m-w atomicity. */
   3.284 +    return hvmemul_write(seg, offset, new, bytes, ctxt);
   3.285 +}
   3.286 +
   3.287 +static int hvmemul_rep_ins(
   3.288 +    uint16_t src_port,
   3.289 +    enum x86_segment dst_seg,
   3.290 +    unsigned long dst_offset,
   3.291 +    unsigned int bytes_per_rep,
   3.292 +    unsigned long *reps,
   3.293 +    struct x86_emulate_ctxt *ctxt)
   3.294 +{
   3.295 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.296 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.297 +    struct vcpu *curr = current;
   3.298 +    unsigned long addr;
   3.299 +    paddr_t gpa;
   3.300 +    int rc;
   3.301 +
   3.302 +    rc = hvmemul_virtual_to_linear(
   3.303 +        dst_seg, dst_offset, *reps * bytes_per_rep, hvm_access_write,
   3.304 +        hvmemul_ctxt, &addr);
   3.305 +    if ( rc != X86EMUL_OKAY )
   3.306 +        return rc;
   3.307 +
   3.308 +    rc = hvmemul_linear_to_phys(
   3.309 +        addr, &gpa, bytes_per_rep, reps, hvm_access_write, hvmemul_ctxt);
   3.310 +    if ( rc != X86EMUL_OKAY )
   3.311 +        return rc;
   3.312 +
   3.313 +    if ( curr->arch.hvm_vcpu.io_in_progress )
   3.314 +        return X86EMUL_UNHANDLEABLE;
   3.315 +
   3.316 +    if ( !curr->arch.hvm_vcpu.io_completed )
   3.317 +    {
   3.318 +        curr->arch.hvm_vcpu.io_in_progress = 1;
   3.319 +        send_pio_req(src_port, *reps, bytes_per_rep,
   3.320 +                     gpa, IOREQ_READ,
   3.321 +                     !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
   3.322 +    }
   3.323 +
   3.324 +    if ( !curr->arch.hvm_vcpu.io_completed )
   3.325 +        return X86EMUL_RETRY;
   3.326 +
   3.327 +    curr->arch.hvm_vcpu.io_completed = 0;
   3.328 +
   3.329 +    return X86EMUL_OKAY;
   3.330 +}
   3.331 +
   3.332 +static int hvmemul_rep_outs(
   3.333 +    enum x86_segment src_seg,
   3.334 +    unsigned long src_offset,
   3.335 +    uint16_t dst_port,
   3.336 +    unsigned int bytes_per_rep,
   3.337 +    unsigned long *reps,
   3.338 +    struct x86_emulate_ctxt *ctxt)
   3.339 +{
   3.340 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.341 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.342 +    struct vcpu *curr = current;
   3.343 +    unsigned long addr;
   3.344 +    paddr_t gpa;
   3.345 +    int rc;
   3.346 +
   3.347 +    rc = hvmemul_virtual_to_linear(
   3.348 +        src_seg, src_offset, *reps * bytes_per_rep, hvm_access_read,
   3.349 +        hvmemul_ctxt, &addr);
   3.350 +    if ( rc != X86EMUL_OKAY )
   3.351 +        return rc;
   3.352 +
   3.353 +    rc = hvmemul_linear_to_phys(
   3.354 +        addr, &gpa, bytes_per_rep, reps, hvm_access_read, hvmemul_ctxt);
   3.355 +    if ( rc != X86EMUL_OKAY )
   3.356 +        return rc;
   3.357 +
   3.358 +    if ( curr->arch.hvm_vcpu.io_in_progress )
   3.359 +        return X86EMUL_UNHANDLEABLE;
   3.360 +
   3.361 +    curr->arch.hvm_vcpu.io_in_progress = 1;
   3.362 +    send_pio_req(dst_port, *reps, bytes_per_rep,
   3.363 +                 gpa, IOREQ_WRITE,
   3.364 +                 !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
   3.365 +
   3.366 +    return X86EMUL_OKAY;
   3.367 +}
   3.368 +
   3.369 +static int hvmemul_rep_movs(
   3.370 +   enum x86_segment src_seg,
   3.371 +   unsigned long src_offset,
   3.372 +   enum x86_segment dst_seg,
   3.373 +   unsigned long dst_offset,
   3.374 +   unsigned int bytes_per_rep,
   3.375 +   unsigned long *reps,
   3.376 +   struct x86_emulate_ctxt *ctxt)
   3.377 +{
   3.378 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.379 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.380 +    struct vcpu *curr = current;
   3.381 +    unsigned long saddr, daddr;
   3.382 +    paddr_t sgpa, dgpa;
   3.383 +    p2m_type_t p2mt;
   3.384 +    int rc;
   3.385 +
   3.386 +    rc = hvmemul_virtual_to_linear(
   3.387 +        src_seg, src_offset, *reps * bytes_per_rep, hvm_access_read,
   3.388 +        hvmemul_ctxt, &saddr);
   3.389 +    if ( rc != X86EMUL_OKAY )
   3.390 +        return rc;
   3.391 +
   3.392 +    rc = hvmemul_virtual_to_linear(
   3.393 +        dst_seg, dst_offset, *reps * bytes_per_rep, hvm_access_write,
   3.394 +        hvmemul_ctxt, &daddr);
   3.395 +    if ( rc != X86EMUL_OKAY )
   3.396 +        return rc;
   3.397 +
   3.398 +    rc = hvmemul_linear_to_phys(
   3.399 +        saddr, &sgpa, bytes_per_rep, reps, hvm_access_read, hvmemul_ctxt);
   3.400 +    if ( rc != X86EMUL_OKAY )
   3.401 +        return rc;
   3.402 +
   3.403 +    rc = hvmemul_linear_to_phys(
   3.404 +        daddr, &dgpa, bytes_per_rep, reps, hvm_access_write, hvmemul_ctxt);
   3.405 +    if ( rc != X86EMUL_OKAY )
   3.406 +        return rc;
   3.407 +
   3.408 +    if ( curr->arch.hvm_vcpu.io_in_progress )
   3.409 +        return X86EMUL_UNHANDLEABLE;
   3.410 +
   3.411 +    (void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
   3.412 +    if ( !p2m_is_ram(p2mt) )
   3.413 +    {
   3.414 +        if ( !curr->arch.hvm_vcpu.io_completed )
   3.415 +        {
   3.416 +            curr->arch.hvm_vcpu.io_in_progress = 1;
   3.417 +            send_mmio_req(IOREQ_TYPE_COPY, sgpa, *reps, bytes_per_rep,
   3.418 +                      dgpa, IOREQ_READ,
   3.419 +                      !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
   3.420 +        }
   3.421 +
   3.422 +        if ( !curr->arch.hvm_vcpu.io_completed )
   3.423 +            return X86EMUL_RETRY;
   3.424 +
   3.425 +        curr->arch.hvm_vcpu.io_completed = 0;
   3.426 +    }
   3.427 +    else
   3.428 +    {
   3.429 +        (void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
   3.430 +        if ( p2m_is_ram(p2mt) )
   3.431 +            return X86EMUL_UNHANDLEABLE;
   3.432 +        curr->arch.hvm_vcpu.io_in_progress = 1;
   3.433 +        send_mmio_req(IOREQ_TYPE_COPY, dgpa, *reps, bytes_per_rep,
   3.434 +                      sgpa, IOREQ_WRITE,
   3.435 +                      !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
   3.436 +    }
   3.437 +
   3.438 +    return X86EMUL_OKAY;
   3.439 +}
   3.440 +
   3.441 +static int hvmemul_read_segment(
   3.442 +    enum x86_segment seg,
   3.443 +    struct segment_register *reg,
   3.444 +    struct x86_emulate_ctxt *ctxt)
   3.445 +{
   3.446 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.447 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.448 +    struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
   3.449 +    memcpy(reg, sreg, sizeof(struct segment_register));
   3.450 +    return X86EMUL_OKAY;
   3.451 +}
   3.452 +
   3.453 +static int hvmemul_write_segment(
   3.454 +    enum x86_segment seg,
   3.455 +    struct segment_register *reg,
   3.456 +    struct x86_emulate_ctxt *ctxt)
   3.457 +{
   3.458 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.459 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.460 +    struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
   3.461 +
   3.462 +    if ( seg == x86_seg_ss )
   3.463 +        hvmemul_ctxt->flags.mov_ss = 1;
   3.464 +
   3.465 +    memcpy(sreg, reg, sizeof(struct segment_register));
   3.466 +    __set_bit(seg, &hvmemul_ctxt->seg_reg_dirty);
   3.467 +
   3.468 +    return X86EMUL_OKAY;
   3.469 +}
   3.470 +
   3.471 +static int hvmemul_read_io(
   3.472 +    unsigned int port,
   3.473 +    unsigned int bytes,
   3.474 +    unsigned long *val,
   3.475 +    struct x86_emulate_ctxt *ctxt)
   3.476 +{
   3.477 +    struct vcpu *curr = current;
   3.478 +
   3.479 +    if ( curr->arch.hvm_vcpu.io_in_progress )
   3.480 +        return X86EMUL_UNHANDLEABLE;
   3.481 +
   3.482 +    if ( !curr->arch.hvm_vcpu.io_completed )
   3.483 +    {
   3.484 +        curr->arch.hvm_vcpu.io_in_progress = 1;
   3.485 +        send_pio_req(port, 1, bytes, 0, IOREQ_READ, 0, 0);
   3.486 +    }
   3.487 +
   3.488 +    if ( !curr->arch.hvm_vcpu.io_completed )
   3.489 +        return X86EMUL_RETRY;
   3.490 +
   3.491 +    *val = curr->arch.hvm_vcpu.io_data;
   3.492 +    curr->arch.hvm_vcpu.io_completed = 0;
   3.493 +
   3.494 +    return X86EMUL_OKAY;
   3.495 +}
   3.496 +
   3.497 +static int hvmemul_write_io(
   3.498 +    unsigned int port,
   3.499 +    unsigned int bytes,
   3.500 +    unsigned long val,
   3.501 +    struct x86_emulate_ctxt *ctxt)
   3.502 +{
   3.503 +    struct vcpu *curr = current;
   3.504 +
   3.505 +    if ( port == 0xe9 )
   3.506 +    {
   3.507 +        hvm_print_line(curr, val);
   3.508 +        return X86EMUL_OKAY;
   3.509 +    }
   3.510 +
   3.511 +    if ( curr->arch.hvm_vcpu.io_in_progress )
   3.512 +        return X86EMUL_UNHANDLEABLE;
   3.513 +
   3.514 +    curr->arch.hvm_vcpu.io_in_progress = 1;
   3.515 +    send_pio_req(port, 1, bytes, val, IOREQ_WRITE, 0, 0);
   3.516 +
   3.517 +    return X86EMUL_OKAY;
   3.518 +}
   3.519 +
   3.520 +static int hvmemul_read_cr(
   3.521 +    unsigned int reg,
   3.522 +    unsigned long *val,
   3.523 +    struct x86_emulate_ctxt *ctxt)
   3.524 +{
   3.525 +    switch ( reg )
   3.526 +    {
   3.527 +    case 0:
   3.528 +    case 2:
   3.529 +    case 3:
   3.530 +    case 4:
   3.531 +        *val = current->arch.hvm_vcpu.guest_cr[reg];
   3.532 +        return X86EMUL_OKAY;
   3.533 +    default:
   3.534 +        break;
   3.535 +    }
   3.536 +
   3.537 +    return X86EMUL_UNHANDLEABLE;
   3.538 +}
   3.539 +
   3.540 +static int hvmemul_write_cr(
   3.541 +    unsigned int reg,
   3.542 +    unsigned long val,
   3.543 +    struct x86_emulate_ctxt *ctxt)
   3.544 +{
   3.545 +    switch ( reg )
   3.546 +    {
   3.547 +    case 0:
   3.548 +        return hvm_set_cr0(val);
   3.549 +    case 2:
   3.550 +        current->arch.hvm_vcpu.guest_cr[2] = val;
   3.551 +        return X86EMUL_OKAY;
   3.552 +    case 3:
   3.553 +        return hvm_set_cr3(val);
   3.554 +    case 4:
   3.555 +        return hvm_set_cr4(val);
   3.556 +    default:
   3.557 +        break;
   3.558 +    }
   3.559 +
   3.560 +    return X86EMUL_UNHANDLEABLE;
   3.561 +}
   3.562 +
   3.563 +static int hvmemul_read_msr(
   3.564 +    unsigned long reg,
   3.565 +    uint64_t *val,
   3.566 +    struct x86_emulate_ctxt *ctxt)
   3.567 +{
   3.568 +    struct cpu_user_regs _regs;
   3.569 +    int rc;
   3.570 +
   3.571 +    _regs.ecx = (uint32_t)reg;
   3.572 +
   3.573 +    if ( (rc = hvm_funcs.msr_read_intercept(&_regs)) != 0 )
   3.574 +        return rc;
   3.575 +
   3.576 +    *val = ((uint64_t)(uint32_t)_regs.edx << 32) || (uint32_t)_regs.eax;
   3.577 +    return X86EMUL_OKAY;
   3.578 +}
   3.579 +
   3.580 +static int hvmemul_write_msr(
   3.581 +    unsigned long reg,
   3.582 +    uint64_t val,
   3.583 +    struct x86_emulate_ctxt *ctxt)
   3.584 +{
   3.585 +    struct cpu_user_regs _regs;
   3.586 +
   3.587 +    _regs.edx = (uint32_t)(val >> 32);
   3.588 +    _regs.eax = (uint32_t)val;
   3.589 +    _regs.ecx = (uint32_t)reg;
   3.590 +
   3.591 +    return hvm_funcs.msr_write_intercept(&_regs);
   3.592 +}
   3.593 +
   3.594 +static int hvmemul_write_rflags(
   3.595 +    unsigned long val,
   3.596 +    struct x86_emulate_ctxt *ctxt)
   3.597 +{
   3.598 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.599 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.600 +    if ( (val & X86_EFLAGS_IF) && !(ctxt->regs->eflags & X86_EFLAGS_IF) )
   3.601 +        hvmemul_ctxt->flags.sti = 1;
   3.602 +    return X86EMUL_OKAY;
   3.603 +}
   3.604 +
   3.605 +static int hvmemul_wbinvd(
   3.606 +    struct x86_emulate_ctxt *ctxt)
   3.607 +{
   3.608 +    hvm_funcs.wbinvd_intercept();
   3.609 +    return X86EMUL_OKAY;
   3.610 +}
   3.611 +
   3.612 +static int hvmemul_cpuid(
   3.613 +    unsigned int *eax,
   3.614 +    unsigned int *ebx,
   3.615 +    unsigned int *ecx,
   3.616 +    unsigned int *edx,
   3.617 +    struct x86_emulate_ctxt *ctxt)
   3.618 +{
   3.619 +    hvm_funcs.cpuid_intercept(eax, ebx, ecx, edx);
   3.620 +    return X86EMUL_OKAY;
   3.621 +}
   3.622 +
   3.623 +static int hvmemul_hlt(
   3.624 +    struct x86_emulate_ctxt *ctxt)
   3.625 +{
   3.626 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.627 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.628 +    hvmemul_ctxt->flags.hlt = 1;
   3.629 +    return X86EMUL_OKAY;
   3.630 +}
   3.631 +
   3.632 +static int hvmemul_inject_hw_exception(
   3.633 +    uint8_t vector,
   3.634 +    uint16_t error_code,
   3.635 +    struct x86_emulate_ctxt *ctxt)
   3.636 +{
   3.637 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.638 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.639 +
   3.640 +    if ( error_code != 0 )
   3.641 +        return X86EMUL_UNHANDLEABLE;
   3.642 +
   3.643 +    hvmemul_ctxt->flags.exn_pending = 1;
   3.644 +    hvmemul_ctxt->exn_vector = vector;
   3.645 +    hvmemul_ctxt->exn_insn_len = 0;
   3.646 +
   3.647 +    return X86EMUL_OKAY;
   3.648 +}
   3.649 +
   3.650 +static int hvmemul_inject_sw_interrupt(
   3.651 +    uint8_t vector,
   3.652 +    uint8_t insn_len,
   3.653 +    struct x86_emulate_ctxt *ctxt)
   3.654 +{
   3.655 +    struct hvm_emulate_ctxt *hvmemul_ctxt =
   3.656 +        container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
   3.657 +
   3.658 +    hvmemul_ctxt->flags.exn_pending = 1;
   3.659 +    hvmemul_ctxt->exn_vector = vector;
   3.660 +    hvmemul_ctxt->exn_insn_len = insn_len;
   3.661 +
   3.662 +    return X86EMUL_OKAY;
   3.663 +}
   3.664 +
   3.665 +static void hvmemul_load_fpu_ctxt(
   3.666 +    struct x86_emulate_ctxt *ctxt)
   3.667 +{
   3.668 +    if ( !current->fpu_dirtied )
   3.669 +        hvm_funcs.fpu_dirty_intercept();
   3.670 +}
   3.671 +
   3.672 +static struct x86_emulate_ops hvm_emulate_ops = {
   3.673 +    .read          = hvmemul_read,
   3.674 +    .insn_fetch    = hvmemul_insn_fetch,
   3.675 +    .write         = hvmemul_write,
   3.676 +    .cmpxchg       = hvmemul_cmpxchg,
   3.677 +    .rep_ins       = hvmemul_rep_ins,
   3.678 +    .rep_outs      = hvmemul_rep_outs,
   3.679 +    .rep_movs      = hvmemul_rep_movs,
   3.680 +    .read_segment  = hvmemul_read_segment,
   3.681 +    .write_segment = hvmemul_write_segment,
   3.682 +    .read_io       = hvmemul_read_io,
   3.683 +    .write_io      = hvmemul_write_io,
   3.684 +    .read_cr       = hvmemul_read_cr,
   3.685 +    .write_cr      = hvmemul_write_cr,
   3.686 +    .read_msr      = hvmemul_read_msr,
   3.687 +    .write_msr     = hvmemul_write_msr,
   3.688 +    .write_rflags  = hvmemul_write_rflags,
   3.689 +    .wbinvd        = hvmemul_wbinvd,
   3.690 +    .cpuid         = hvmemul_cpuid,
   3.691 +    .hlt           = hvmemul_hlt,
   3.692 +    .inject_hw_exception = hvmemul_inject_hw_exception,
   3.693 +    .inject_sw_interrupt = hvmemul_inject_sw_interrupt,
   3.694 +    .load_fpu_ctxt = hvmemul_load_fpu_ctxt
   3.695 +};
   3.696 +
   3.697 +int hvm_emulate_one(
   3.698 +    struct hvm_emulate_ctxt *hvmemul_ctxt)
   3.699 +{
   3.700 +    struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
   3.701 +    unsigned long addr;
   3.702 +
   3.703 +    hvmemul_ctxt->ctxt.addr_size =
   3.704 +        hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
   3.705 +    hvmemul_ctxt->ctxt.sp_size =
   3.706 +        hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
   3.707 +
   3.708 +    hvmemul_ctxt->insn_buf_eip = regs->eip;
   3.709 +    hvmemul_ctxt->insn_buf_bytes =
   3.710 +        (hvm_virtual_to_linear_addr(
   3.711 +            x86_seg_cs, &hvmemul_ctxt->seg_reg[x86_seg_cs],
   3.712 +            regs->eip, sizeof(hvmemul_ctxt->insn_buf),
   3.713 +            hvm_access_insn_fetch, hvmemul_ctxt->ctxt.addr_size, &addr) &&
   3.714 +         !hvm_fetch_from_guest_virt_nofault(
   3.715 +             hvmemul_ctxt->insn_buf, addr, sizeof(hvmemul_ctxt->insn_buf)))
   3.716 +        ? sizeof(hvmemul_ctxt->insn_buf) : 0;
   3.717 +
   3.718 +    hvmemul_ctxt->flag_word = 0;
   3.719 +
   3.720 +    return x86_emulate(&hvmemul_ctxt->ctxt, &hvm_emulate_ops);
   3.721 +}
   3.722 +
   3.723 +void hvm_emulate_prepare(
   3.724 +    struct hvm_emulate_ctxt *hvmemul_ctxt,
   3.725 +    struct cpu_user_regs *regs)
   3.726 +{
   3.727 +    hvmemul_ctxt->ctxt.regs = regs;
   3.728 +    hvmemul_ctxt->seg_reg_accessed = 0;
   3.729 +    hvmemul_ctxt->seg_reg_dirty = 0;
   3.730 +    hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt);
   3.731 +    hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt);
   3.732 +}
   3.733 +
   3.734 +void hvm_emulate_writeback(
   3.735 +    struct hvm_emulate_ctxt *hvmemul_ctxt)
   3.736 +{
   3.737 +    enum x86_segment seg;
   3.738 +
   3.739 +    seg = find_first_bit(&hvmemul_ctxt->seg_reg_dirty,
   3.740 +                         ARRAY_SIZE(hvmemul_ctxt->seg_reg));
   3.741 +
   3.742 +    while ( seg < ARRAY_SIZE(hvmemul_ctxt->seg_reg) )
   3.743 +    {
   3.744 +        hvm_set_segment_register(current, seg, &hvmemul_ctxt->seg_reg[seg]);
   3.745 +        seg = find_next_bit(&hvmemul_ctxt->seg_reg_dirty,
   3.746 +                            ARRAY_SIZE(hvmemul_ctxt->seg_reg),
   3.747 +                            seg+1);
   3.748 +    }
   3.749 +}
   3.750 +
   3.751 +struct segment_register *hvmemul_get_seg_reg(
   3.752 +    enum x86_segment seg,
   3.753 +    struct hvm_emulate_ctxt *hvmemul_ctxt)
   3.754 +{
   3.755 +    if ( !__test_and_set_bit(seg, &hvmemul_ctxt->seg_reg_accessed) )
   3.756 +        hvm_get_segment_register(current, seg, &hvmemul_ctxt->seg_reg[seg]);
   3.757 +    return &hvmemul_ctxt->seg_reg[seg];
   3.758 +}
     4.1 --- a/xen/arch/x86/hvm/hvm.c	Tue Feb 19 11:14:40 2008 -0700
     4.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Feb 20 14:36:45 2008 +0000
     4.3 @@ -729,7 +729,7 @@ int hvm_set_efer(uint64_t value)
     4.4          gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
     4.5                   "EFER: %"PRIx64"\n", value);
     4.6          hvm_inject_exception(TRAP_gp_fault, 0, 0);
     4.7 -        return 0;
     4.8 +        return X86EMUL_EXCEPTION;
     4.9      }
    4.10  
    4.11      if ( ((value ^ v->arch.hvm_vcpu.guest_efer) & EFER_LME) &&
    4.12 @@ -738,14 +738,14 @@ int hvm_set_efer(uint64_t value)
    4.13          gdprintk(XENLOG_WARNING,
    4.14                   "Trying to change EFER.LME with paging enabled\n");
    4.15          hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.16 -        return 0;
    4.17 +        return X86EMUL_EXCEPTION;
    4.18      }
    4.19  
    4.20      value |= v->arch.hvm_vcpu.guest_efer & EFER_LMA;
    4.21      v->arch.hvm_vcpu.guest_efer = value;
    4.22      hvm_update_guest_efer(v);
    4.23  
    4.24 -    return 1;
    4.25 +    return X86EMUL_OKAY;
    4.26  }
    4.27  
    4.28  extern void shadow_blow_tables_per_domain(struct domain *d);
    4.29 @@ -787,8 +787,7 @@ int hvm_set_cr0(unsigned long value)
    4.30          HVM_DBG_LOG(DBG_LEVEL_1,
    4.31                      "Guest attempts to set upper 32 bits in CR0: %lx",
    4.32                      value);
    4.33 -        hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.34 -        return 0;
    4.35 +        goto gpf;
    4.36      }
    4.37  
    4.38      value &= ~HVM_CR0_GUEST_RESERVED_BITS;
    4.39 @@ -797,10 +796,7 @@ int hvm_set_cr0(unsigned long value)
    4.40      value |= X86_CR0_ET;
    4.41  
    4.42      if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PG )
    4.43 -    {
    4.44 -        hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.45 -        return 0;
    4.46 -    }
    4.47 +        goto gpf;
    4.48  
    4.49      if ( (value & X86_CR0_PG) && !(old_value & X86_CR0_PG) )
    4.50      {
    4.51 @@ -809,8 +805,7 @@ int hvm_set_cr0(unsigned long value)
    4.52              if ( !(v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PAE) )
    4.53              {
    4.54                  HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable");
    4.55 -                hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.56 -                return 0;
    4.57 +                goto gpf;
    4.58              }
    4.59              HVM_DBG_LOG(DBG_LEVEL_1, "Enabling long mode");
    4.60              v->arch.hvm_vcpu.guest_efer |= EFER_LMA;
    4.61 @@ -828,7 +823,7 @@ int hvm_set_cr0(unsigned long value)
    4.62                  gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n",
    4.63                           v->arch.hvm_vcpu.guest_cr[3], mfn);
    4.64                  domain_crash(v->domain);
    4.65 -                return 0;
    4.66 +                return X86EMUL_UNHANDLEABLE;
    4.67              }
    4.68  
    4.69              /* Now arch.guest_table points to machine physical. */
    4.70 @@ -895,7 +890,11 @@ int hvm_set_cr0(unsigned long value)
    4.71      if ( (value ^ old_value) & X86_CR0_PG )
    4.72          paging_update_paging_modes(v);
    4.73  
    4.74 -    return 1;
    4.75 +    return X86EMUL_OKAY;
    4.76 +
    4.77 + gpf:
    4.78 +    hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.79 +    return X86EMUL_EXCEPTION;
    4.80  }
    4.81  
    4.82  int hvm_set_cr3(unsigned long value)
    4.83 @@ -922,12 +921,12 @@ int hvm_set_cr3(unsigned long value)
    4.84  
    4.85      v->arch.hvm_vcpu.guest_cr[3] = value;
    4.86      paging_update_cr3(v);
    4.87 -    return 1;
    4.88 +    return X86EMUL_OKAY;
    4.89  
    4.90   bad_cr3:
    4.91      gdprintk(XENLOG_ERR, "Invalid CR3\n");
    4.92      domain_crash(v->domain);
    4.93 -    return 0;
    4.94 +    return X86EMUL_UNHANDLEABLE;
    4.95  }
    4.96  
    4.97  int hvm_set_cr4(unsigned long value)
    4.98 @@ -958,11 +957,11 @@ int hvm_set_cr4(unsigned long value)
    4.99      if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) )
   4.100          paging_update_paging_modes(v);
   4.101  
   4.102 -    return 1;
   4.103 +    return X86EMUL_OKAY;
   4.104  
   4.105   gpf:
   4.106      hvm_inject_exception(TRAP_gp_fault, 0, 0);
   4.107 -    return 0;
   4.108 +    return X86EMUL_EXCEPTION;
   4.109  }
   4.110  
   4.111  int hvm_virtual_to_linear_addr(
   4.112 @@ -977,7 +976,15 @@ int hvm_virtual_to_linear_addr(
   4.113      unsigned long addr = offset;
   4.114      uint32_t last_byte;
   4.115  
   4.116 -    if ( addr_size != 64 )
   4.117 +    if ( !(current->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) )
   4.118 +    {
   4.119 +        /*
   4.120 +         * REAL MODE: Don't bother with segment access checks.
   4.121 +         * Certain of them are not done in native real mode anyway.
   4.122 +         */
   4.123 +        addr = (uint32_t)(addr + reg->base);
   4.124 +    }
   4.125 +    else if ( addr_size != 64 )
   4.126      {
   4.127          /*
   4.128           * COMPATIBILITY MODE: Apply segment checks and add base.
   4.129 @@ -1304,7 +1311,7 @@ void hvm_task_switch(
   4.130      if ( ptss == NULL )
   4.131          goto out;
   4.132  
   4.133 -    if ( !hvm_set_cr3(ptss->cr3) )
   4.134 +    if ( hvm_set_cr3(ptss->cr3) )
   4.135      {
   4.136          hvm_unmap(ptss);
   4.137          goto out;
   4.138 @@ -1399,7 +1406,10 @@ static enum hvm_copy_result __hvm_copy(
   4.139       * VMREADs on every data access hurts emulation performance.
   4.140       * Hence we do not gather extra PFEC flags if CR0.PG == 0.
   4.141       */
   4.142 -    if ( virt && (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG) )
   4.143 +    if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG) )
   4.144 +        virt = 0;
   4.145 +
   4.146 +    if ( virt )
   4.147      {
   4.148          struct segment_register sreg;
   4.149          hvm_get_segment_register(curr, x86_seg_ss, &sreg);
     5.1 --- a/xen/arch/x86/hvm/instrlen.c	Tue Feb 19 11:14:40 2008 -0700
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,419 +0,0 @@
     5.4 -/*
     5.5 - * instrlen.c - calculates the instruction length for all operating modes
     5.6 - * 
     5.7 - * Travis Betak, travis.betak@amd.com
     5.8 - * Copyright (c) 2005,2006 AMD
     5.9 - * Copyright (c) 2005 Keir Fraser
    5.10 - *
    5.11 - * Essentially a very, very stripped version of Keir Fraser's work in
    5.12 - * x86_emulate.c.  Used for MMIO.
    5.13 - */
    5.14 -
    5.15 -#include <xen/config.h>
    5.16 -#include <xen/sched.h>
    5.17 -#include <xen/mm.h>
    5.18 -#include <asm-x86/x86_emulate.h>
    5.19 -
    5.20 -/* read from guest memory */
    5.21 -extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip,
    5.22 -        int length);
    5.23 -
    5.24 -/*
    5.25 - * Opcode effective-address decode tables.
    5.26 - * Note that we only emulate instructions that have at least one memory
    5.27 - * operand (excluding implicit stack references). We assume that stack
    5.28 - * references and instruction fetches will never occur in special memory
    5.29 - * areas that require emulation. So, for example, 'mov <imm>,<reg>' need
    5.30 - * not be handled.
    5.31 - */
    5.32 -
    5.33 -/* Operand sizes: 8-bit operands or specified/overridden size. */
    5.34 -#define ByteOp      (1<<0) /* 8-bit operands. */
    5.35 -/* Destination operand type. */
    5.36 -#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
    5.37 -#define DstReg      (2<<1) /* Register operand. */
    5.38 -#define DstMem      (3<<1) /* Memory operand. */
    5.39 -#define DstMask     (3<<1)
    5.40 -/* Source operand type. */
    5.41 -#define SrcNone     (0<<3) /* No source operand. */
    5.42 -#define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */
    5.43 -#define SrcReg      (1<<3) /* Register operand. */
    5.44 -#define SrcMem      (2<<3) /* Memory operand. */
    5.45 -#define SrcMem16    (3<<3) /* Memory operand (16-bit). */
    5.46 -#define SrcMem32    (4<<3) /* Memory operand (32-bit). */
    5.47 -#define SrcImm      (5<<3) /* Immediate operand. */
    5.48 -#define SrcImmByte  (6<<3) /* 8-bit sign-extended immediate operand. */
    5.49 -#define SrcMask     (7<<3)
    5.50 -/* Generic ModRM decode. */
    5.51 -#define ModRM       (1<<6)
    5.52 -/* Destination is only written; never read. */
    5.53 -#define Mov         (1<<7)
    5.54 -
    5.55 -static uint8_t opcode_table[256] = {
    5.56 -    /* 0x00 - 0x07 */
    5.57 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.58 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.59 -    0, 0, 0, 0,
    5.60 -    /* 0x08 - 0x0F */
    5.61 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.62 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.63 -    0, 0, 0, 0,
    5.64 -    /* 0x10 - 0x17 */
    5.65 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.66 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.67 -    0, 0, 0, 0,
    5.68 -    /* 0x18 - 0x1F */
    5.69 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.70 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.71 -    0, 0, 0, 0,
    5.72 -    /* 0x20 - 0x27 */
    5.73 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.74 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.75 -    0, 0, 0, 0,
    5.76 -    /* 0x28 - 0x2F */
    5.77 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.78 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.79 -    0, 0, 0, 0,
    5.80 -    /* 0x30 - 0x37 */
    5.81 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.82 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.83 -    0, 0, 0, 0,
    5.84 -    /* 0x38 - 0x3F */
    5.85 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.86 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    5.87 -    0, 0, 0, 0,
    5.88 -    /* 0x40 - 0x4F */
    5.89 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.90 -    /* 0x50 - 0x5F */
    5.91 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.92 -    /* 0x60 - 0x6F */
    5.93 -    0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
    5.94 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.95 -    /* 0x70 - 0x7F */
    5.96 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.97 -    /* 0x80 - 0x87 */
    5.98 -    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
    5.99 -    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
   5.100 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   5.101 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   5.102 -    /* 0x88 - 0x8F */
   5.103 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   5.104 -    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   5.105 -    0, 0, 0, DstMem|SrcNone|ModRM|Mov,
   5.106 -    /* 0x90 - 0x9F */
   5.107 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.108 -    /* 0xA0 - 0xA7 */
   5.109 -    ByteOp|DstReg|SrcMem|Mov, DstReg|SrcMem|Mov,
   5.110 -    ByteOp|DstMem|SrcReg|Mov, DstMem|SrcReg|Mov,
   5.111 -    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   5.112 -    ByteOp|ImplicitOps, ImplicitOps,
   5.113 -    /* 0xA8 - 0xAF */
   5.114 -    0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   5.115 -    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   5.116 -    ByteOp|ImplicitOps, ImplicitOps,
   5.117 -    /* 0xB0 - 0xBF */
   5.118 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.119 -    /* 0xC0 - 0xC7 */
   5.120 -    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0,
   5.121 -    0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
   5.122 -    /* 0xC8 - 0xCF */
   5.123 -    0, 0, 0, 0, 0, 0, 0, 0,
   5.124 -    /* 0xD0 - 0xD7 */
   5.125 -    ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
   5.126 -    ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
   5.127 -    0, 0, 0, 0,
   5.128 -    /* 0xD8 - 0xDF */
   5.129 -    0, 0, 0, 0, 0, 0, 0, 0,
   5.130 -    /* 0xE0 - 0xEF */
   5.131 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.132 -    /* 0xF0 - 0xF7 */
   5.133 -    0, 0, 0, 0,
   5.134 -    0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
   5.135 -    /* 0xF8 - 0xFF */
   5.136 -    0, 0, 0, 0,
   5.137 -    0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
   5.138 -};
   5.139 -
   5.140 -static uint8_t twobyte_table[256] = {
   5.141 -    /* 0x00 - 0x0F */
   5.142 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
   5.143 -    /* 0x10 - 0x1F */
   5.144 -    0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0,
   5.145 -    /* 0x20 - 0x2F */
   5.146 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.147 -    /* 0x30 - 0x3F */
   5.148 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.149 -    /* 0x40 - 0x47 */
   5.150 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.151 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.152 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.153 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.154 -    /* 0x48 - 0x4F */
   5.155 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.156 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.157 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.158 -    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   5.159 -    /* 0x50 - 0x5F */
   5.160 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.161 -    /* 0x60 - 0x6F */
   5.162 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.163 -    /* 0x70 - 0x7F */
   5.164 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.165 -    /* 0x80 - 0x8F */
   5.166 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.167 -    /* 0x90 - 0x9F */
   5.168 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.169 -    /* 0xA0 - 0xA7 */
   5.170 -    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, 
   5.171 -    /* 0xA8 - 0xAF */
   5.172 -    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
   5.173 -    /* 0xB0 - 0xB7 */
   5.174 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM,
   5.175 -    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
   5.176 -    /* 0xB8 - 0xBF */
   5.177 -    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM,
   5.178 -    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
   5.179 -    /* 0xC0 - 0xCF */
   5.180 -    0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
   5.181 -    /* 0xD0 - 0xDF */
   5.182 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.183 -    /* 0xE0 - 0xEF */
   5.184 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   5.185 -    /* 0xF0 - 0xFF */
   5.186 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   5.187 -};
   5.188 -
   5.189 -/* 
   5.190 - * insn_fetch - fetch the next byte from instruction stream
   5.191 - */
   5.192 -#define insn_fetch()                                                      \
   5.193 -({ uint8_t _x;                                                            \
   5.194 -   if ( length >= 15 )                                                    \
   5.195 -       return -1;                                                         \
   5.196 -   if ( inst_copy_from_guest(&_x, pc, 1) != 1 ) {                         \
   5.197 -       unsigned long err;                                                 \
   5.198 -       struct segment_register ss;                                        \
   5.199 -       gdprintk(XENLOG_WARNING,                                           \
   5.200 -                "Cannot read from address %lx (eip %lx, mode %d)\n",      \
   5.201 -                pc, org_pc, address_bytes);                               \
   5.202 -       err = 0; /* Must be not-present: we don't enforce reserved bits */ \
   5.203 -       if ( hvm_nx_enabled(current) )                                     \
   5.204 -           err |= PFEC_insn_fetch;                                        \
   5.205 -       hvm_get_segment_register(current, x86_seg_ss, &ss);                \
   5.206 -       if ( ss.attr.fields.dpl == 3 )                                     \
   5.207 -           err |= PFEC_user_mode;                                         \
   5.208 -       hvm_inject_exception(TRAP_page_fault, err, pc);                    \
   5.209 -       return -1;                                                         \
   5.210 -   }                                                                      \
   5.211 -   if ( buf )                                                             \
   5.212 -       buf[length] = _x;                                                  \
   5.213 -   length += 1;                                                           \
   5.214 -   pc += 1;                                                               \
   5.215 -   _x;                                                                    \
   5.216 -})
   5.217 -
   5.218 -#define insn_skip(_n) do {                      \
   5.219 -    int _i;                                     \
   5.220 -    for ( _i = 0; _i < (_n); _i++) {            \
   5.221 -        (void) insn_fetch();                    \
   5.222 -    }                                           \
   5.223 -} while (0)
   5.224 -
   5.225 -/**
   5.226 - * hvm_instruction_fetch - read the current instruction and return its length
   5.227 - *
   5.228 - * @org_pc: guest instruction pointer
   5.229 - * @address_bytes: guest address width
   5.230 - * @buf: (optional) buffer to load actual instruction bytes into
   5.231 - *
   5.232 - * Doesn't increment the guest's instruction pointer, but may
   5.233 - * issue faults to the guest.  Returns -1 on failure.
   5.234 - */
   5.235 -int hvm_instruction_fetch(unsigned long org_pc, int address_bytes,
   5.236 -                          unsigned char *buf)
   5.237 -{
   5.238 -    uint8_t b, d, twobyte = 0, rex_prefix = 0, modrm_reg = 0;
   5.239 -    unsigned int op_default, op_bytes, ad_default, ad_bytes, tmp;
   5.240 -    int length = 0;
   5.241 -    unsigned long pc = org_pc;
   5.242 -
   5.243 -    op_bytes = op_default = ad_bytes = ad_default = address_bytes;
   5.244 -    if ( op_bytes == 8 )
   5.245 -    {
   5.246 -        op_bytes = op_default = 4;
   5.247 -#ifndef __x86_64__
   5.248 -        return -1;
   5.249 -#endif
   5.250 -    }
   5.251 -
   5.252 -    /* Legacy prefixes. */
   5.253 -    for ( ; ; )
   5.254 -    {
   5.255 -        switch ( b = insn_fetch() )
   5.256 -        {
   5.257 -        case 0x66: /* operand-size override */
   5.258 -            op_bytes = op_default ^ 6;      /* switch between 2/4 bytes */
   5.259 -            break;
   5.260 -        case 0x67: /* address-size override */
   5.261 -            if ( ad_default == 8 )
   5.262 -                ad_bytes = ad_default ^ 12; /* switch between 4/8 bytes */
   5.263 -            else
   5.264 -                ad_bytes = ad_default ^ 6;  /* switch between 2/4 bytes */
   5.265 -            break;
   5.266 -        case 0x2e: /* CS override */
   5.267 -        case 0x3e: /* DS override */
   5.268 -        case 0x26: /* ES override */
   5.269 -        case 0x64: /* FS override */
   5.270 -        case 0x65: /* GS override */
   5.271 -        case 0x36: /* SS override */
   5.272 -        case 0xf0: /* LOCK */
   5.273 -        case 0xf3: /* REP/REPE/REPZ */
   5.274 -        case 0xf2: /* REPNE/REPNZ */
   5.275 -            break;
   5.276 -#ifdef __x86_64__
   5.277 -        case 0x40 ... 0x4f:
   5.278 -            if ( ad_default == 8 )
   5.279 -            {
   5.280 -                rex_prefix = b;
   5.281 -                continue;
   5.282 -            }
   5.283 -            /* FALLTHRU */
   5.284 -#endif
   5.285 -        default:
   5.286 -            goto done_prefixes;
   5.287 -        }
   5.288 -        rex_prefix = 0;
   5.289 -    }
   5.290 -done_prefixes:
   5.291 -
   5.292 -    /* REX prefix. */
   5.293 -    if ( rex_prefix & 8 )
   5.294 -        op_bytes = 8;                   /* REX.W */
   5.295 -    /* REX.B, REX.R, and REX.X do not need to be decoded. */
   5.296 -
   5.297 -    /* Opcode byte(s). */
   5.298 -    d = opcode_table[b];
   5.299 -    if ( d == 0 )
   5.300 -    {
   5.301 -        /* Two-byte opcode? */
   5.302 -        if ( b == 0x0f )
   5.303 -        {
   5.304 -            twobyte = 1;
   5.305 -            b = insn_fetch();
   5.306 -            d = twobyte_table[b];
   5.307 -        }
   5.308 -
   5.309 -        /* Unrecognised? */
   5.310 -        if ( d == 0 )
   5.311 -            goto cannot_emulate;
   5.312 -    }
   5.313 -
   5.314 -    /* ModRM and SIB bytes. */
   5.315 -    if ( d & ModRM )
   5.316 -    {
   5.317 -        uint8_t modrm = insn_fetch();
   5.318 -        uint8_t modrm_mod = (modrm & 0xc0) >> 6;
   5.319 -        uint8_t modrm_rm  = (modrm & 0x07);
   5.320 -
   5.321 -        modrm_reg = (modrm & 0x38) >> 3;
   5.322 -        if ( modrm_mod == 3 )
   5.323 -        {
   5.324 -            gdprintk(XENLOG_WARNING, "Cannot parse ModRM.mod == 3.\n");
   5.325 -            goto cannot_emulate;
   5.326 -        }
   5.327 -
   5.328 -        if ( ad_bytes == 2 )
   5.329 -        {
   5.330 -            /* 16-bit ModR/M decode. */
   5.331 -            switch ( modrm_mod )
   5.332 -            {
   5.333 -            case 0:
   5.334 -                if ( modrm_rm == 6 ) 
   5.335 -                    insn_skip(2); /* skip disp16 */
   5.336 -                break;
   5.337 -            case 1:
   5.338 -                insn_skip(1); /* skip disp8 */
   5.339 -                break;
   5.340 -            case 2:
   5.341 -                insn_skip(2); /* skip disp16 */
   5.342 -                break;
   5.343 -            }
   5.344 -        }
   5.345 -        else
   5.346 -        {
   5.347 -            /* 32/64-bit ModR/M decode. */
   5.348 -            switch ( modrm_mod )
   5.349 -            {
   5.350 -            case 0:
   5.351 -                if ( (modrm_rm == 4) && 
   5.352 -                     ((insn_fetch() & 7) == 5) )
   5.353 -                    insn_skip(4); /* skip disp32 specified by SIB.base */
   5.354 -                else if ( modrm_rm == 5 )
   5.355 -                    insn_skip(4); /* skip disp32 */
   5.356 -                break;
   5.357 -            case 1:
   5.358 -                if ( modrm_rm == 4 )
   5.359 -                    insn_skip(1);
   5.360 -                insn_skip(1); /* skip disp8 */
   5.361 -                break;
   5.362 -            case 2:
   5.363 -                if ( modrm_rm == 4 )
   5.364 -                    insn_skip(1);
   5.365 -                insn_skip(4); /* skip disp32 */
   5.366 -                break;
   5.367 -            }
   5.368 -        }
   5.369 -    }
   5.370 -
   5.371 -    /* Decode and fetch the destination operand: register or memory. */
   5.372 -    switch ( d & DstMask )
   5.373 -    {
   5.374 -    case ImplicitOps:
   5.375 -        /* Special instructions do their own operand decoding. */
   5.376 -        goto done;
   5.377 -    }
   5.378 -
   5.379 -    /* Decode and fetch the source operand: register, memory or immediate. */
   5.380 -    switch ( d & SrcMask )
   5.381 -    {
   5.382 -    case SrcImm:
   5.383 -        tmp = (d & ByteOp) ? 1 : op_bytes;
   5.384 -        if ( tmp == 8 ) tmp = 4;
   5.385 -        /* NB. Immediates are sign-extended as necessary. */
   5.386 -        insn_skip(tmp);
   5.387 -        break;
   5.388 -    case SrcImmByte:
   5.389 -        insn_skip(1);
   5.390 -        break;
   5.391 -    }
   5.392 -
   5.393 -    if ( twobyte )
   5.394 -        goto done;
   5.395 -
   5.396 -    switch ( b )
   5.397 -    {
   5.398 -    case 0xa0 ... 0xa3: /* mov */
   5.399 -        insn_skip(ad_bytes); /* skip src/dst displacement */
   5.400 -        break;
   5.401 -    case 0xf6 ... 0xf7: /* Grp3 */
   5.402 -        switch ( modrm_reg )
   5.403 -        {
   5.404 -        case 0 ... 1: /* test */
   5.405 -            /* Special case in Grp3: test has an immediate source operand. */
   5.406 -            tmp = (d & ByteOp) ? 1 : op_bytes;
   5.407 -            if ( tmp == 8 ) tmp = 4;
   5.408 -            insn_skip(tmp);
   5.409 -            break;
   5.410 -        }
   5.411 -        break;
   5.412 -    }
   5.413 -
   5.414 -done:
   5.415 -    return length < 16 ? length : -1;
   5.416 -
   5.417 -cannot_emulate:
   5.418 -    gdprintk(XENLOG_WARNING,
   5.419 -            "Cannot emulate %02x at address %lx (%lx, addr_bytes %d)\n",
   5.420 -            b, pc - 1, org_pc, address_bytes);
   5.421 -    return -1;
   5.422 -}
     6.1 --- a/xen/arch/x86/hvm/intercept.c	Tue Feb 19 11:14:40 2008 -0700
     6.2 +++ b/xen/arch/x86/hvm/intercept.c	Wed Feb 20 14:36:45 2008 +0000
     6.3 @@ -31,7 +31,6 @@
     6.4  #include <xen/event.h>
     6.5  #include <asm/iommu.h>
     6.6  
     6.7 -
     6.8  extern struct hvm_mmio_handler hpet_mmio_handler;
     6.9  extern struct hvm_mmio_handler vlapic_mmio_handler;
    6.10  extern struct hvm_mmio_handler vioapic_mmio_handler;
    6.11 @@ -50,12 +49,11 @@ static inline void hvm_mmio_access(struc
    6.12                                     hvm_mmio_read_t read_handler,
    6.13                                     hvm_mmio_write_t write_handler)
    6.14  {
    6.15 -    unsigned int tmp1, tmp2;
    6.16      unsigned long data;
    6.17  
    6.18 -    switch ( p->type ) {
    6.19 +    switch ( p->type )
    6.20 +    {
    6.21      case IOREQ_TYPE_COPY:
    6.22 -    {
    6.23          if ( !p->data_is_ptr ) {
    6.24              if ( p->dir == IOREQ_READ )
    6.25                  p->data = read_handler(v, p->addr, p->size);
    6.26 @@ -87,62 +85,6 @@ static inline void hvm_mmio_access(struc
    6.27              }
    6.28          }
    6.29          break;
    6.30 -    }
    6.31 -
    6.32 -    case IOREQ_TYPE_AND:
    6.33 -        tmp1 = read_handler(v, p->addr, p->size);
    6.34 -        if ( p->dir == IOREQ_WRITE ) {
    6.35 -            tmp2 = tmp1 & (unsigned long) p->data;
    6.36 -            write_handler(v, p->addr, p->size, tmp2);
    6.37 -        }
    6.38 -        p->data = tmp1;
    6.39 -        break;
    6.40 -
    6.41 -    case IOREQ_TYPE_ADD:
    6.42 -        tmp1 = read_handler(v, p->addr, p->size);
    6.43 -        if (p->dir == IOREQ_WRITE) {
    6.44 -            tmp2 = tmp1 + (unsigned long) p->data;
    6.45 -            write_handler(v, p->addr, p->size, tmp2);
    6.46 -        }
    6.47 -        p->data = tmp1;
    6.48 -        break;
    6.49 -
    6.50 -    case IOREQ_TYPE_OR:
    6.51 -        tmp1 = read_handler(v, p->addr, p->size);
    6.52 -        if ( p->dir == IOREQ_WRITE ) {
    6.53 -            tmp2 = tmp1 | (unsigned long) p->data;
    6.54 -            write_handler(v, p->addr, p->size, tmp2);
    6.55 -        }
    6.56 -        p->data = tmp1;
    6.57 -        break;
    6.58 -
    6.59 -    case IOREQ_TYPE_XOR:
    6.60 -        tmp1 = read_handler(v, p->addr, p->size);
    6.61 -        if ( p->dir == IOREQ_WRITE ) {
    6.62 -            tmp2 = tmp1 ^ (unsigned long) p->data;
    6.63 -            write_handler(v, p->addr, p->size, tmp2);
    6.64 -        }
    6.65 -        p->data = tmp1;
    6.66 -        break;
    6.67 -
    6.68 -    case IOREQ_TYPE_XCHG:
    6.69 -        /*
    6.70 -         * Note that we don't need to be atomic here since VCPU is accessing
    6.71 -         * its own local APIC.
    6.72 -         */
    6.73 -        tmp1 = read_handler(v, p->addr, p->size);
    6.74 -        write_handler(v, p->addr, p->size, (unsigned long) p->data);
    6.75 -        p->data = tmp1;
    6.76 -        break;
    6.77 -
    6.78 -    case IOREQ_TYPE_SUB:
    6.79 -        tmp1 = read_handler(v, p->addr, p->size);
    6.80 -        if ( p->dir == IOREQ_WRITE ) {
    6.81 -            tmp2 = tmp1 - (unsigned long) p->data;
    6.82 -            write_handler(v, p->addr, p->size, tmp2);
    6.83 -        }
    6.84 -        p->data = tmp1;
    6.85 -        break;
    6.86  
    6.87      default:
    6.88          printk("hvm_mmio_access: error ioreq type %x\n", p->type);
     7.1 --- a/xen/arch/x86/hvm/io.c	Tue Feb 19 11:14:40 2008 -0700
     7.2 +++ b/xen/arch/x86/hvm/io.c	Wed Feb 20 14:36:45 2008 +0000
     7.3 @@ -46,379 +46,8 @@
     7.4  #include <xen/iocap.h>
     7.5  #include <public/hvm/ioreq.h>
     7.6  
     7.7 -#if defined (__i386__)
     7.8 -static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
     7.9 -{
    7.10 -    switch (size) {
    7.11 -    case BYTE:
    7.12 -        switch (index) {
    7.13 -        case 0:
    7.14 -            regs->eax &= 0xFFFFFF00;
    7.15 -            regs->eax |= (value & 0xFF);
    7.16 -            break;
    7.17 -        case 1:
    7.18 -            regs->ecx &= 0xFFFFFF00;
    7.19 -            regs->ecx |= (value & 0xFF);
    7.20 -            break;
    7.21 -        case 2:
    7.22 -            regs->edx &= 0xFFFFFF00;
    7.23 -            regs->edx |= (value & 0xFF);
    7.24 -            break;
    7.25 -        case 3:
    7.26 -            regs->ebx &= 0xFFFFFF00;
    7.27 -            regs->ebx |= (value & 0xFF);
    7.28 -            break;
    7.29 -        case 4:
    7.30 -            regs->eax &= 0xFFFF00FF;
    7.31 -            regs->eax |= ((value & 0xFF) << 8);
    7.32 -            break;
    7.33 -        case 5:
    7.34 -            regs->ecx &= 0xFFFF00FF;
    7.35 -            regs->ecx |= ((value & 0xFF) << 8);
    7.36 -            break;
    7.37 -        case 6:
    7.38 -            regs->edx &= 0xFFFF00FF;
    7.39 -            regs->edx |= ((value & 0xFF) << 8);
    7.40 -            break;
    7.41 -        case 7:
    7.42 -            regs->ebx &= 0xFFFF00FF;
    7.43 -            regs->ebx |= ((value & 0xFF) << 8);
    7.44 -            break;
    7.45 -        default:
    7.46 -            goto crash;
    7.47 -        }
    7.48 -        break;
    7.49 -    case WORD:
    7.50 -        switch (index) {
    7.51 -        case 0:
    7.52 -            regs->eax &= 0xFFFF0000;
    7.53 -            regs->eax |= (value & 0xFFFF);
    7.54 -            break;
    7.55 -        case 1:
    7.56 -            regs->ecx &= 0xFFFF0000;
    7.57 -            regs->ecx |= (value & 0xFFFF);
    7.58 -            break;
    7.59 -        case 2:
    7.60 -            regs->edx &= 0xFFFF0000;
    7.61 -            regs->edx |= (value & 0xFFFF);
    7.62 -            break;
    7.63 -        case 3:
    7.64 -            regs->ebx &= 0xFFFF0000;
    7.65 -            regs->ebx |= (value & 0xFFFF);
    7.66 -            break;
    7.67 -        case 4:
    7.68 -            regs->esp &= 0xFFFF0000;
    7.69 -            regs->esp |= (value & 0xFFFF);
    7.70 -            break;
    7.71 -        case 5:
    7.72 -            regs->ebp &= 0xFFFF0000;
    7.73 -            regs->ebp |= (value & 0xFFFF);
    7.74 -            break;
    7.75 -        case 6:
    7.76 -            regs->esi &= 0xFFFF0000;
    7.77 -            regs->esi |= (value & 0xFFFF);
    7.78 -            break;
    7.79 -        case 7:
    7.80 -            regs->edi &= 0xFFFF0000;
    7.81 -            regs->edi |= (value & 0xFFFF);
    7.82 -            break;
    7.83 -        default:
    7.84 -            goto crash;
    7.85 -        }
    7.86 -        break;
    7.87 -    case LONG:
    7.88 -        switch (index) {
    7.89 -        case 0:
    7.90 -            regs->eax = value;
    7.91 -            break;
    7.92 -        case 1:
    7.93 -            regs->ecx = value;
    7.94 -            break;
    7.95 -        case 2:
    7.96 -            regs->edx = value;
    7.97 -            break;
    7.98 -        case 3:
    7.99 -            regs->ebx = value;
   7.100 -            break;
   7.101 -        case 4:
   7.102 -            regs->esp = value;
   7.103 -            break;
   7.104 -        case 5:
   7.105 -            regs->ebp = value;
   7.106 -            break;
   7.107 -        case 6:
   7.108 -            regs->esi = value;
   7.109 -            break;
   7.110 -        case 7:
   7.111 -            regs->edi = value;
   7.112 -            break;
   7.113 -        default:
   7.114 -            goto crash;
   7.115 -        }
   7.116 -        break;
   7.117 -    default:
   7.118 -    crash:
   7.119 -        gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", size, index);
   7.120 -        domain_crash_synchronous();
   7.121 -    }
   7.122 -}
   7.123 -#else
   7.124 -static inline void __set_reg_value(unsigned long *reg, int size, long value)
   7.125 -{
   7.126 -    switch (size) {
   7.127 -    case BYTE_64:
   7.128 -        *reg &= ~0xFF;
   7.129 -        *reg |= (value & 0xFF);
   7.130 -        break;
   7.131 -    case WORD:
   7.132 -        *reg &= ~0xFFFF;
   7.133 -        *reg |= (value & 0xFFFF);
   7.134 -        break;
   7.135 -    case LONG:
   7.136 -        *reg &= ~0xFFFFFFFF;
   7.137 -        *reg |= (value & 0xFFFFFFFF);
   7.138 -        break;
   7.139 -    case QUAD:
   7.140 -        *reg = value;
   7.141 -        break;
   7.142 -    default:
   7.143 -        gdprintk(XENLOG_ERR, "size:%x is invalid\n", size);
   7.144 -        domain_crash_synchronous();
   7.145 -    }
   7.146 -}
   7.147 -
   7.148 -static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
   7.149 -{
   7.150 -    if (size == BYTE) {
   7.151 -        switch (index) {
   7.152 -        case 0:
   7.153 -            regs->rax &= ~0xFF;
   7.154 -            regs->rax |= (value & 0xFF);
   7.155 -            break;
   7.156 -        case 1:
   7.157 -            regs->rcx &= ~0xFF;
   7.158 -            regs->rcx |= (value & 0xFF);
   7.159 -            break;
   7.160 -        case 2:
   7.161 -            regs->rdx &= ~0xFF;
   7.162 -            regs->rdx |= (value & 0xFF);
   7.163 -            break;
   7.164 -        case 3:
   7.165 -            regs->rbx &= ~0xFF;
   7.166 -            regs->rbx |= (value & 0xFF);
   7.167 -            break;
   7.168 -        case 4:
   7.169 -            regs->rax &= 0xFFFFFFFFFFFF00FF;
   7.170 -            regs->rax |= ((value & 0xFF) << 8);
   7.171 -            break;
   7.172 -        case 5:
   7.173 -            regs->rcx &= 0xFFFFFFFFFFFF00FF;
   7.174 -            regs->rcx |= ((value & 0xFF) << 8);
   7.175 -            break;
   7.176 -        case 6:
   7.177 -            regs->rdx &= 0xFFFFFFFFFFFF00FF;
   7.178 -            regs->rdx |= ((value & 0xFF) << 8);
   7.179 -            break;
   7.180 -        case 7:
   7.181 -            regs->rbx &= 0xFFFFFFFFFFFF00FF;
   7.182 -            regs->rbx |= ((value & 0xFF) << 8);
   7.183 -            break;
   7.184 -        default:
   7.185 -            gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n",
   7.186 -                     size, index);
   7.187 -            domain_crash_synchronous();
   7.188 -            break;
   7.189 -        }
   7.190 -        return;
   7.191 -    }
   7.192 -
   7.193 -    switch (index) {
   7.194 -    case 0:
   7.195 -        __set_reg_value(&regs->rax, size, value);
   7.196 -        break;
   7.197 -    case 1:
   7.198 -        __set_reg_value(&regs->rcx, size, value);
   7.199 -        break;
   7.200 -    case 2:
   7.201 -        __set_reg_value(&regs->rdx, size, value);
   7.202 -        break;
   7.203 -    case 3:
   7.204 -        __set_reg_value(&regs->rbx, size, value);
   7.205 -        break;
   7.206 -    case 4:
   7.207 -        __set_reg_value(&regs->rsp, size, value);
   7.208 -        break;
   7.209 -    case 5:
   7.210 -        __set_reg_value(&regs->rbp, size, value);
   7.211 -        break;
   7.212 -    case 6:
   7.213 -        __set_reg_value(&regs->rsi, size, value);
   7.214 -        break;
   7.215 -    case 7:
   7.216 -        __set_reg_value(&regs->rdi, size, value);
   7.217 -        break;
   7.218 -    case 8:
   7.219 -        __set_reg_value(&regs->r8, size, value);
   7.220 -        break;
   7.221 -    case 9:
   7.222 -        __set_reg_value(&regs->r9, size, value);
   7.223 -        break;
   7.224 -    case 10:
   7.225 -        __set_reg_value(&regs->r10, size, value);
   7.226 -        break;
   7.227 -    case 11:
   7.228 -        __set_reg_value(&regs->r11, size, value);
   7.229 -        break;
   7.230 -    case 12:
   7.231 -        __set_reg_value(&regs->r12, size, value);
   7.232 -        break;
   7.233 -    case 13:
   7.234 -        __set_reg_value(&regs->r13, size, value);
   7.235 -        break;
   7.236 -    case 14:
   7.237 -        __set_reg_value(&regs->r14, size, value);
   7.238 -        break;
   7.239 -    case 15:
   7.240 -        __set_reg_value(&regs->r15, size, value);
   7.241 -        break;
   7.242 -    default:
   7.243 -        gdprintk(XENLOG_ERR, "Invalid index\n");
   7.244 -        domain_crash_synchronous();
   7.245 -    }
   7.246 -    return;
   7.247 -}
   7.248 -#endif
   7.249 -
   7.250 -long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
   7.251 -
   7.252 -static inline void set_eflags_CF(int size,
   7.253 -                                 unsigned int instr,
   7.254 -                                 unsigned long result,
   7.255 -                                 unsigned long src,
   7.256 -                                 unsigned long dst,
   7.257 -                                 struct cpu_user_regs *regs)
   7.258 -{
   7.259 -    unsigned long mask;
   7.260 -
   7.261 -    if ( size == BYTE_64 )
   7.262 -        size = BYTE;
   7.263 -    ASSERT((size <= sizeof(mask)) && (size > 0));
   7.264 -
   7.265 -    mask = ~0UL >> (8 * (sizeof(mask) - size));
   7.266 -
   7.267 -    if ( instr == INSTR_ADD )
   7.268 -    {
   7.269 -        /* CF=1 <==> result is less than the augend and addend) */
   7.270 -        if ( (result & mask) < (dst & mask) )
   7.271 -        {
   7.272 -            ASSERT((result & mask) < (src & mask));
   7.273 -            regs->eflags |= X86_EFLAGS_CF;
   7.274 -        }
   7.275 -    }
   7.276 -    else
   7.277 -    {
   7.278 -        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );
   7.279 -        if ( (src & mask) > (dst & mask) )
   7.280 -            regs->eflags |= X86_EFLAGS_CF;
   7.281 -    }
   7.282 -}
   7.283 -
   7.284 -static inline void set_eflags_OF(int size,
   7.285 -                                 unsigned int instr,
   7.286 -                                 unsigned long result,
   7.287 -                                 unsigned long src,
   7.288 -                                 unsigned long dst,
   7.289 -                                 struct cpu_user_regs *regs)
   7.290 -{
   7.291 -    unsigned long mask;
   7.292 -
   7.293 -    if ( size == BYTE_64 )
   7.294 -        size = BYTE;
   7.295 -    ASSERT((size <= sizeof(mask)) && (size > 0));
   7.296 -
   7.297 -    mask =  1UL << ((8*size) - 1);
   7.298 -
   7.299 -    if ( instr == INSTR_ADD )
   7.300 -    {
   7.301 -        if ((src ^ result) & (dst ^ result) & mask);
   7.302 -            regs->eflags |= X86_EFLAGS_OF;
   7.303 -    }
   7.304 -    else
   7.305 -    {
   7.306 -        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);
   7.307 -        if ((dst ^ src) & (dst ^ result) & mask)
   7.308 -            regs->eflags |= X86_EFLAGS_OF;
   7.309 -    }
   7.310 -}
   7.311 -
   7.312 -static inline void set_eflags_AF(int size,
   7.313 -                                 unsigned long result,
   7.314 -                                 unsigned long src,
   7.315 -                                 unsigned long dst,
   7.316 -                                 struct cpu_user_regs *regs)
   7.317 -{
   7.318 -    if ((result ^ src ^ dst) & 0x10)
   7.319 -        regs->eflags |= X86_EFLAGS_AF;
   7.320 -}
   7.321 -
   7.322 -static inline void set_eflags_ZF(int size, unsigned long result,
   7.323 -                                 struct cpu_user_regs *regs)
   7.324 -{
   7.325 -    unsigned long mask;
   7.326 -
   7.327 -    if ( size == BYTE_64 )
   7.328 -        size = BYTE;
   7.329 -    ASSERT((size <= sizeof(mask)) && (size > 0));
   7.330 -
   7.331 -    mask = ~0UL >> (8 * (sizeof(mask) - size));
   7.332 -
   7.333 -    if ((result & mask) == 0)
   7.334 -        regs->eflags |= X86_EFLAGS_ZF;
   7.335 -}
   7.336 -
   7.337 -static inline void set_eflags_SF(int size, unsigned long result,
   7.338 -                                 struct cpu_user_regs *regs)
   7.339 -{
   7.340 -    unsigned long mask;
   7.341 -
   7.342 -    if ( size == BYTE_64 )
   7.343 -        size = BYTE;
   7.344 -    ASSERT((size <= sizeof(mask)) && (size > 0));
   7.345 -
   7.346 -    mask = 1UL << ((8*size) - 1);
   7.347 -
   7.348 -    if (result & mask)
   7.349 -        regs->eflags |= X86_EFLAGS_SF;
   7.350 -}
   7.351 -
   7.352 -static char parity_table[256] = {
   7.353 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.354 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.355 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.356 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.357 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.358 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.359 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.360 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.361 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.362 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.363 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.364 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.365 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   7.366 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.367 -    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   7.368 -    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
   7.369 -};
   7.370 -
   7.371 -static inline void set_eflags_PF(int size, unsigned long result,
   7.372 -                                 struct cpu_user_regs *regs)
   7.373 -{
   7.374 -    if (parity_table[result & 0xFF])
   7.375 -        regs->eflags |= X86_EFLAGS_PF;
   7.376 -}
   7.377 -
   7.378 -static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
   7.379 -                           struct hvm_io_op *pio_opp)
   7.380 +static void hvm_pio_assist(
   7.381 +    struct cpu_user_regs *regs, ioreq_t *p, struct hvm_io_op *pio_opp)
   7.382  {
   7.383      if ( p->data_is_ptr || (pio_opp->flags & OVERLAP) )
   7.384      {
   7.385 @@ -472,335 +101,6 @@ static void hvm_pio_assist(struct cpu_us
   7.386      }
   7.387  }
   7.388  
   7.389 -static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
   7.390 -                            struct hvm_io_op *mmio_opp)
   7.391 -{
   7.392 -    int sign = p->df ? -1 : 1;
   7.393 -    int size = -1, index = -1;
   7.394 -    unsigned long value = 0, result = 0;
   7.395 -    unsigned long src, dst;
   7.396 -
   7.397 -    src = mmio_opp->operand[0];
   7.398 -    dst = mmio_opp->operand[1];
   7.399 -    size = operand_size(src);
   7.400 -
   7.401 -    HVMTRACE_1D(MMIO_ASSIST, current, p->data);
   7.402 -        
   7.403 -    switch (mmio_opp->instr) {
   7.404 -    case INSTR_MOV:
   7.405 -        if (dst & REGISTER) {
   7.406 -            index = operand_index(dst);
   7.407 -            set_reg_value(size, index, 0, regs, p->data);
   7.408 -        }
   7.409 -        break;
   7.410 -
   7.411 -    case INSTR_MOVZX:
   7.412 -        if (dst & REGISTER) {
   7.413 -            switch (size) {
   7.414 -            case BYTE:
   7.415 -                p->data &= 0xFFULL;
   7.416 -                break;
   7.417 -
   7.418 -            case WORD:
   7.419 -                p->data &= 0xFFFFULL;
   7.420 -                break;
   7.421 -
   7.422 -            case LONG:
   7.423 -                p->data &= 0xFFFFFFFFULL;
   7.424 -                break;
   7.425 -
   7.426 -            default:
   7.427 -                printk("Impossible source operand size of movzx instr: %d\n", size);
   7.428 -                domain_crash_synchronous();
   7.429 -            }
   7.430 -            index = operand_index(dst);
   7.431 -            set_reg_value(operand_size(dst), index, 0, regs, p->data);
   7.432 -        }
   7.433 -        break;
   7.434 -
   7.435 -    case INSTR_MOVSX:
   7.436 -        if (dst & REGISTER) {
   7.437 -            switch (size) {
   7.438 -            case BYTE:
   7.439 -                p->data &= 0xFFULL;
   7.440 -                if ( p->data & 0x80ULL )
   7.441 -                    p->data |= 0xFFFFFFFFFFFFFF00ULL;
   7.442 -                break;
   7.443 -
   7.444 -            case WORD:
   7.445 -                p->data &= 0xFFFFULL;
   7.446 -                if ( p->data & 0x8000ULL )
   7.447 -                    p->data |= 0xFFFFFFFFFFFF0000ULL;
   7.448 -                break;
   7.449 -
   7.450 -            case LONG:
   7.451 -                p->data &= 0xFFFFFFFFULL;
   7.452 -                if ( p->data & 0x80000000ULL )
   7.453 -                    p->data |= 0xFFFFFFFF00000000ULL;
   7.454 -                break;
   7.455 -
   7.456 -            default:
   7.457 -                printk("Impossible source operand size of movsx instr: %d\n", size);
   7.458 -                domain_crash_synchronous();
   7.459 -            }
   7.460 -            index = operand_index(dst);
   7.461 -            set_reg_value(operand_size(dst), index, 0, regs, p->data);
   7.462 -        }
   7.463 -        break;
   7.464 -
   7.465 -    case INSTR_MOVS:
   7.466 -        sign = p->df ? -1 : 1;
   7.467 -
   7.468 -        if (mmio_opp->flags & REPZ)
   7.469 -            regs->ecx -= p->count;
   7.470 -
   7.471 -        if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {
   7.472 -            unsigned long addr = mmio_opp->addr;
   7.473 -
   7.474 -            if (hvm_paging_enabled(current))
   7.475 -            {
   7.476 -                int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
   7.477 -                if ( rv == HVMCOPY_bad_gva_to_gfn )
   7.478 -                    return; /* exception already injected */
   7.479 -            }
   7.480 -            else
   7.481 -                (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
   7.482 -        }
   7.483 -
   7.484 -        regs->esi += sign * p->count * p->size;
   7.485 -        regs->edi += sign * p->count * p->size;
   7.486 -
   7.487 -        break;
   7.488 -
   7.489 -    case INSTR_STOS:
   7.490 -        sign = p->df ? -1 : 1;
   7.491 -        regs->edi += sign * p->count * p->size;
   7.492 -        if (mmio_opp->flags & REPZ)
   7.493 -            regs->ecx -= p->count;
   7.494 -        break;
   7.495 -
   7.496 -    case INSTR_LODS:
   7.497 -        set_reg_value(size, 0, 0, regs, p->data);
   7.498 -        sign = p->df ? -1 : 1;
   7.499 -        regs->esi += sign * p->count * p->size;
   7.500 -        if (mmio_opp->flags & REPZ)
   7.501 -            regs->ecx -= p->count;
   7.502 -        break;
   7.503 -
   7.504 -    case INSTR_AND:
   7.505 -        if (src & REGISTER) {
   7.506 -            index = operand_index(src);
   7.507 -            value = get_reg_value(size, index, 0, regs);
   7.508 -            result = (unsigned long) p->data & value;
   7.509 -        } else if (src & IMMEDIATE) {
   7.510 -            value = mmio_opp->immediate;
   7.511 -            result = (unsigned long) p->data & value;
   7.512 -        } else if (src & MEMORY) {
   7.513 -            index = operand_index(dst);
   7.514 -            value = get_reg_value(size, index, 0, regs);
   7.515 -            result = (unsigned long) p->data & value;
   7.516 -            set_reg_value(size, index, 0, regs, result);
   7.517 -        }
   7.518 -
   7.519 -        /*
   7.520 -         * The OF and CF flags are cleared; the SF, ZF, and PF
   7.521 -         * flags are set according to the result. The state of
   7.522 -         * the AF flag is undefined.
   7.523 -         */
   7.524 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
   7.525 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.526 -        set_eflags_ZF(size, result, regs);
   7.527 -        set_eflags_SF(size, result, regs);
   7.528 -        set_eflags_PF(size, result, regs);
   7.529 -        break;
   7.530 -
   7.531 -    case INSTR_ADD:
   7.532 -        if (src & REGISTER) {
   7.533 -            index = operand_index(src);
   7.534 -            value = get_reg_value(size, index, 0, regs);
   7.535 -            result = (unsigned long) p->data + value;
   7.536 -        } else if (src & IMMEDIATE) {
   7.537 -            value = mmio_opp->immediate;
   7.538 -            result = (unsigned long) p->data + value;
   7.539 -        } else if (src & MEMORY) {
   7.540 -            index = operand_index(dst);
   7.541 -            value = get_reg_value(size, index, 0, regs);
   7.542 -            result = (unsigned long) p->data + value;
   7.543 -            set_reg_value(size, index, 0, regs, result);
   7.544 -        }
   7.545 -
   7.546 -        /*
   7.547 -         * The CF, OF, SF, ZF, AF, and PF flags are set according
   7.548 -         * to the result
   7.549 -         */
   7.550 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
   7.551 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.552 -        set_eflags_CF(size, mmio_opp->instr, result, value,
   7.553 -                      (unsigned long) p->data, regs);
   7.554 -        set_eflags_OF(size, mmio_opp->instr, result, value,
   7.555 -                      (unsigned long) p->data, regs);
   7.556 -        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
   7.557 -        set_eflags_ZF(size, result, regs);
   7.558 -        set_eflags_SF(size, result, regs);
   7.559 -        set_eflags_PF(size, result, regs);
   7.560 -        break;
   7.561 -
   7.562 -    case INSTR_OR:
   7.563 -        if (src & REGISTER) {
   7.564 -            index = operand_index(src);
   7.565 -            value = get_reg_value(size, index, 0, regs);
   7.566 -            result = (unsigned long) p->data | value;
   7.567 -        } else if (src & IMMEDIATE) {
   7.568 -            value = mmio_opp->immediate;
   7.569 -            result = (unsigned long) p->data | value;
   7.570 -        } else if (src & MEMORY) {
   7.571 -            index = operand_index(dst);
   7.572 -            value = get_reg_value(size, index, 0, regs);
   7.573 -            result = (unsigned long) p->data | value;
   7.574 -            set_reg_value(size, index, 0, regs, result);
   7.575 -        }
   7.576 -
   7.577 -        /*
   7.578 -         * The OF and CF flags are cleared; the SF, ZF, and PF
   7.579 -         * flags are set according to the result. The state of
   7.580 -         * the AF flag is undefined.
   7.581 -         */
   7.582 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
   7.583 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.584 -        set_eflags_ZF(size, result, regs);
   7.585 -        set_eflags_SF(size, result, regs);
   7.586 -        set_eflags_PF(size, result, regs);
   7.587 -        break;
   7.588 -
   7.589 -    case INSTR_XOR:
   7.590 -        if (src & REGISTER) {
   7.591 -            index = operand_index(src);
   7.592 -            value = get_reg_value(size, index, 0, regs);
   7.593 -            result = (unsigned long) p->data ^ value;
   7.594 -        } else if (src & IMMEDIATE) {
   7.595 -            value = mmio_opp->immediate;
   7.596 -            result = (unsigned long) p->data ^ value;
   7.597 -        } else if (src & MEMORY) {
   7.598 -            index = operand_index(dst);
   7.599 -            value = get_reg_value(size, index, 0, regs);
   7.600 -            result = (unsigned long) p->data ^ value;
   7.601 -            set_reg_value(size, index, 0, regs, result);
   7.602 -        }
   7.603 -
   7.604 -        /*
   7.605 -         * The OF and CF flags are cleared; the SF, ZF, and PF
   7.606 -         * flags are set according to the result. The state of
   7.607 -         * the AF flag is undefined.
   7.608 -         */
   7.609 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
   7.610 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.611 -        set_eflags_ZF(size, result, regs);
   7.612 -        set_eflags_SF(size, result, regs);
   7.613 -        set_eflags_PF(size, result, regs);
   7.614 -        break;
   7.615 -
   7.616 -    case INSTR_CMP:
   7.617 -    case INSTR_SUB:
   7.618 -        if (src & REGISTER) {
   7.619 -            index = operand_index(src);
   7.620 -            value = get_reg_value(size, index, 0, regs);
   7.621 -            result = (unsigned long) p->data - value;
   7.622 -        } else if (src & IMMEDIATE) {
   7.623 -            value = mmio_opp->immediate;
   7.624 -            result = (unsigned long) p->data - value;
   7.625 -        } else if (src & MEMORY) {
   7.626 -            index = operand_index(dst);
   7.627 -            value = get_reg_value(size, index, 0, regs);
   7.628 -            result = value - (unsigned long) p->data;
   7.629 -            if ( mmio_opp->instr == INSTR_SUB )
   7.630 -                set_reg_value(size, index, 0, regs, result);
   7.631 -        }
   7.632 -
   7.633 -        /*
   7.634 -         * The CF, OF, SF, ZF, AF, and PF flags are set according
   7.635 -         * to the result
   7.636 -         */
   7.637 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
   7.638 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.639 -        if ( src & (REGISTER | IMMEDIATE) )
   7.640 -        {
   7.641 -            set_eflags_CF(size, mmio_opp->instr, result, value,
   7.642 -                          (unsigned long) p->data, regs);
   7.643 -            set_eflags_OF(size, mmio_opp->instr, result, value,
   7.644 -                          (unsigned long) p->data, regs);
   7.645 -        }
   7.646 -        else
   7.647 -        {
   7.648 -            set_eflags_CF(size, mmio_opp->instr, result,
   7.649 -                          (unsigned long) p->data, value, regs);
   7.650 -            set_eflags_OF(size, mmio_opp->instr, result,
   7.651 -                          (unsigned long) p->data, value, regs);
   7.652 -        }
   7.653 -        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
   7.654 -        set_eflags_ZF(size, result, regs);
   7.655 -        set_eflags_SF(size, result, regs);
   7.656 -        set_eflags_PF(size, result, regs);
   7.657 -        break;
   7.658 -
   7.659 -    case INSTR_TEST:
   7.660 -        if (src & REGISTER) {
   7.661 -            index = operand_index(src);
   7.662 -            value = get_reg_value(size, index, 0, regs);
   7.663 -        } else if (src & IMMEDIATE) {
   7.664 -            value = mmio_opp->immediate;
   7.665 -        } else if (src & MEMORY) {
   7.666 -            index = operand_index(dst);
   7.667 -            value = get_reg_value(size, index, 0, regs);
   7.668 -        }
   7.669 -        result = (unsigned long) p->data & value;
   7.670 -
   7.671 -        /*
   7.672 -         * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
   7.673 -         */
   7.674 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
   7.675 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
   7.676 -        set_eflags_ZF(size, result, regs);
   7.677 -        set_eflags_SF(size, result, regs);
   7.678 -        set_eflags_PF(size, result, regs);
   7.679 -        break;
   7.680 -
   7.681 -    case INSTR_BT:
   7.682 -        if ( src & REGISTER )
   7.683 -        {
   7.684 -            index = operand_index(src);
   7.685 -            value = get_reg_value(size, index, 0, regs);
   7.686 -        }
   7.687 -        else if ( src & IMMEDIATE )
   7.688 -            value = mmio_opp->immediate;
   7.689 -        if (p->data & (1 << (value & ((1 << 5) - 1))))
   7.690 -            regs->eflags |= X86_EFLAGS_CF;
   7.691 -        else
   7.692 -            regs->eflags &= ~X86_EFLAGS_CF;
   7.693 -
   7.694 -        break;
   7.695 -
   7.696 -    case INSTR_XCHG:
   7.697 -        if (src & REGISTER) {
   7.698 -            index = operand_index(src);
   7.699 -            set_reg_value(size, index, 0, regs, p->data);
   7.700 -        } else {
   7.701 -            index = operand_index(dst);
   7.702 -            set_reg_value(size, index, 0, regs, p->data);
   7.703 -        }
   7.704 -        break;
   7.705 -
   7.706 -    case INSTR_PUSH:
   7.707 -        mmio_opp->addr += hvm_get_segment_base(current, x86_seg_ss);
   7.708 -        {
   7.709 -            unsigned long addr = mmio_opp->addr;
   7.710 -            int rv = hvm_copy_to_guest_virt(addr, &p->data, size);
   7.711 -            if ( rv == HVMCOPY_bad_gva_to_gfn )
   7.712 -                return; /* exception already injected */
   7.713 -        }
   7.714 -        break;
   7.715 -    }
   7.716 -}
   7.717 -
   7.718  void hvm_io_assist(void)
   7.719  {
   7.720      vcpu_iodata_t *vio;
   7.721 @@ -825,8 +125,18 @@ void hvm_io_assist(void)
   7.722  
   7.723      p->state = STATE_IOREQ_NONE;
   7.724  
   7.725 -    if ( v->arch.hvm_vcpu.io_complete && v->arch.hvm_vcpu.io_complete() )
   7.726 +    if ( v->arch.hvm_vcpu.io_in_progress )
   7.727 +    {
   7.728 +        v->arch.hvm_vcpu.io_in_progress = 0;
   7.729 +        if ( p->dir == IOREQ_READ )
   7.730 +        {
   7.731 +            v->arch.hvm_vcpu.io_completed = 1;
   7.732 +            v->arch.hvm_vcpu.io_data = p->data;
   7.733 +        }
   7.734 +        if ( v->arch.hvm_vcpu.mmio_in_progress )
   7.735 +            (void)handle_mmio();
   7.736          goto out;
   7.737 +    }
   7.738  
   7.739      switch ( p->type )
   7.740      {
   7.741 @@ -836,8 +146,9 @@ void hvm_io_assist(void)
   7.742          hvm_pio_assist(regs, p, io_opp);
   7.743          break;
   7.744      default:
   7.745 -        hvm_mmio_assist(regs, p, io_opp);
   7.746 -        break;
   7.747 +        gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
   7.748 +        domain_crash(v->domain);
   7.749 +        goto out;
   7.750      }
   7.751  
   7.752      /* Copy register changes back into current guest state. */
     8.1 --- a/xen/arch/x86/hvm/platform.c	Tue Feb 19 11:14:40 2008 -0700
     8.2 +++ b/xen/arch/x86/hvm/platform.c	Wed Feb 20 14:36:45 2008 +0000
     8.3 @@ -33,801 +33,9 @@
     8.4  #include <asm/hvm/support.h>
     8.5  #include <asm/hvm/io.h>
     8.6  #include <public/hvm/ioreq.h>
     8.7 -
     8.8  #include <xen/lib.h>
     8.9  #include <xen/sched.h>
    8.10 -#include <asm/current.h>
    8.11 -
    8.12 -#define DECODE_success  1
    8.13 -#define DECODE_failure  0
    8.14 -
    8.15 -#define mk_operand(size_reg, index, seg, flag) \
    8.16 -    (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
    8.17 -
    8.18 -#if defined (__x86_64__)
    8.19 -static inline long __get_reg_value(unsigned long reg, int size)
    8.20 -{
    8.21 -    switch ( size ) {
    8.22 -    case BYTE_64:
    8.23 -        return (char)(reg & 0xFF);
    8.24 -    case WORD:
    8.25 -        return (short)(reg & 0xFFFF);
    8.26 -    case LONG:
    8.27 -        return (int)(reg & 0xFFFFFFFF);
    8.28 -    case QUAD:
    8.29 -        return (long)(reg);
    8.30 -    default:
    8.31 -        printk("Error: (__get_reg_value) Invalid reg size\n");
    8.32 -        domain_crash_synchronous();
    8.33 -    }
    8.34 -}
    8.35 -
    8.36 -long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
    8.37 -{
    8.38 -    if ( size == BYTE ) {
    8.39 -        switch ( index ) {
    8.40 -        case 0: /* %al */
    8.41 -            return (char)(regs->rax & 0xFF);
    8.42 -        case 1: /* %cl */
    8.43 -            return (char)(regs->rcx & 0xFF);
    8.44 -        case 2: /* %dl */
    8.45 -            return (char)(regs->rdx & 0xFF);
    8.46 -        case 3: /* %bl */
    8.47 -            return (char)(regs->rbx & 0xFF);
    8.48 -        case 4: /* %ah */
    8.49 -            return (char)((regs->rax & 0xFF00) >> 8);
    8.50 -        case 5: /* %ch */
    8.51 -            return (char)((regs->rcx & 0xFF00) >> 8);
    8.52 -        case 6: /* %dh */
    8.53 -            return (char)((regs->rdx & 0xFF00) >> 8);
    8.54 -        case 7: /* %bh */
    8.55 -            return (char)((regs->rbx & 0xFF00) >> 8);
    8.56 -        default:
    8.57 -            printk("Error: (get_reg_value) Invalid index value\n");
    8.58 -            domain_crash_synchronous();
    8.59 -        }
    8.60 -        /* NOTREACHED */
    8.61 -    }
    8.62 -
    8.63 -    switch ( index ) {
    8.64 -    case 0: return __get_reg_value(regs->rax, size);
    8.65 -    case 1: return __get_reg_value(regs->rcx, size);
    8.66 -    case 2: return __get_reg_value(regs->rdx, size);
    8.67 -    case 3: return __get_reg_value(regs->rbx, size);
    8.68 -    case 4: return __get_reg_value(regs->rsp, size);
    8.69 -    case 5: return __get_reg_value(regs->rbp, size);
    8.70 -    case 6: return __get_reg_value(regs->rsi, size);
    8.71 -    case 7: return __get_reg_value(regs->rdi, size);
    8.72 -    case 8: return __get_reg_value(regs->r8, size);
    8.73 -    case 9: return __get_reg_value(regs->r9, size);
    8.74 -    case 10: return __get_reg_value(regs->r10, size);
    8.75 -    case 11: return __get_reg_value(regs->r11, size);
    8.76 -    case 12: return __get_reg_value(regs->r12, size);
    8.77 -    case 13: return __get_reg_value(regs->r13, size);
    8.78 -    case 14: return __get_reg_value(regs->r14, size);
    8.79 -    case 15: return __get_reg_value(regs->r15, size);
    8.80 -    default:
    8.81 -        printk("Error: (get_reg_value) Invalid index value\n");
    8.82 -        domain_crash_synchronous();
    8.83 -    }
    8.84 -}
    8.85 -#elif defined (__i386__)
    8.86 -static inline long __get_reg_value(unsigned long reg, int size)
    8.87 -{
    8.88 -    switch ( size ) {
    8.89 -    case WORD:
    8.90 -        return (short)(reg & 0xFFFF);
    8.91 -    case LONG:
    8.92 -        return (int)(reg & 0xFFFFFFFF);
    8.93 -    default:
    8.94 -        printk("Error: (__get_reg_value) Invalid reg size\n");
    8.95 -        domain_crash_synchronous();
    8.96 -    }
    8.97 -}
    8.98 -
    8.99 -long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
   8.100 -{
   8.101 -    if ( size == BYTE ) {
   8.102 -        switch ( index ) {
   8.103 -        case 0: /* %al */
   8.104 -            return (char)(regs->eax & 0xFF);
   8.105 -        case 1: /* %cl */
   8.106 -            return (char)(regs->ecx & 0xFF);
   8.107 -        case 2: /* %dl */
   8.108 -            return (char)(regs->edx & 0xFF);
   8.109 -        case 3: /* %bl */
   8.110 -            return (char)(regs->ebx & 0xFF);
   8.111 -        case 4: /* %ah */
   8.112 -            return (char)((regs->eax & 0xFF00) >> 8);
   8.113 -        case 5: /* %ch */
   8.114 -            return (char)((regs->ecx & 0xFF00) >> 8);
   8.115 -        case 6: /* %dh */
   8.116 -            return (char)((regs->edx & 0xFF00) >> 8);
   8.117 -        case 7: /* %bh */
   8.118 -            return (char)((regs->ebx & 0xFF00) >> 8);
   8.119 -        default:
   8.120 -            printk("Error: (get_reg_value) Invalid index value\n");
   8.121 -            domain_crash_synchronous();
   8.122 -        }
   8.123 -    }
   8.124 -
   8.125 -    switch ( index ) {
   8.126 -    case 0: return __get_reg_value(regs->eax, size);
   8.127 -    case 1: return __get_reg_value(regs->ecx, size);
   8.128 -    case 2: return __get_reg_value(regs->edx, size);
   8.129 -    case 3: return __get_reg_value(regs->ebx, size);
   8.130 -    case 4: return __get_reg_value(regs->esp, size);
   8.131 -    case 5: return __get_reg_value(regs->ebp, size);
   8.132 -    case 6: return __get_reg_value(regs->esi, size);
   8.133 -    case 7: return __get_reg_value(regs->edi, size);
   8.134 -    default:
   8.135 -        printk("Error: (get_reg_value) Invalid index value\n");
   8.136 -        domain_crash_synchronous();
   8.137 -    }
   8.138 -}
   8.139 -#endif
   8.140 -
   8.141 -static inline unsigned char *check_prefix(unsigned char *inst,
   8.142 -                                          struct hvm_io_op *mmio_op,
   8.143 -                                          unsigned char *ad_size,
   8.144 -                                          unsigned char *op_size,
   8.145 -                                          unsigned char *seg_sel,
   8.146 -                                          unsigned char *rex_p)
   8.147 -{
   8.148 -    while ( 1 ) {
   8.149 -        switch ( *inst ) {
   8.150 -            /* rex prefix for em64t instructions */
   8.151 -        case 0x40 ... 0x4f:
   8.152 -            *rex_p = *inst;
   8.153 -            break;
   8.154 -        case 0xf3: /* REPZ */
   8.155 -            mmio_op->flags = REPZ;
   8.156 -            break;
   8.157 -        case 0xf2: /* REPNZ */
   8.158 -            mmio_op->flags = REPNZ;
   8.159 -            break;
   8.160 -        case 0xf0: /* LOCK */
   8.161 -            break;
   8.162 -        case 0x2e: /* CS */
   8.163 -        case 0x36: /* SS */
   8.164 -        case 0x3e: /* DS */
   8.165 -        case 0x26: /* ES */
   8.166 -        case 0x64: /* FS */
   8.167 -        case 0x65: /* GS */
   8.168 -            *seg_sel = *inst;
   8.169 -            break;
   8.170 -        case 0x66: /* 32bit->16bit */
   8.171 -            *op_size = WORD;
   8.172 -            break;
   8.173 -        case 0x67:
   8.174 -            *ad_size = WORD;
   8.175 -            break;
   8.176 -        default:
   8.177 -            return inst;
   8.178 -        }
   8.179 -        inst++;
   8.180 -    }
   8.181 -}
   8.182 -
   8.183 -static inline unsigned long get_immediate(int ad_size, const unsigned char *inst, int op_size)
   8.184 -{
   8.185 -    int mod, reg, rm;
   8.186 -    unsigned long val = 0;
   8.187 -    int i;
   8.188 -
   8.189 -    mod = (*inst >> 6) & 3;
   8.190 -    reg = (*inst >> 3) & 7;
   8.191 -    rm = *inst & 7;
   8.192 -
   8.193 -    inst++; //skip ModR/M byte
   8.194 -    if ( ad_size != WORD && mod != 3 && rm == 4 ) {
   8.195 -        rm = *inst & 7;
   8.196 -        inst++; //skip SIB byte
   8.197 -    }
   8.198 -
   8.199 -    switch ( mod ) {
   8.200 -    case 0:
   8.201 -        if ( ad_size == WORD ) {
   8.202 -            if ( rm == 6 )
   8.203 -                inst = inst + 2; //disp16, skip 2 bytes
   8.204 -        }
   8.205 -        else {
   8.206 -            if ( rm == 5 )
   8.207 -                inst = inst + 4; //disp32, skip 4 bytes
   8.208 -        }
   8.209 -        break;
   8.210 -    case 1:
   8.211 -        inst++; //disp8, skip 1 byte
   8.212 -        break;
   8.213 -    case 2:
   8.214 -        if ( ad_size == WORD )
   8.215 -            inst = inst + 2; //disp16, skip 2 bytes
   8.216 -        else
   8.217 -            inst = inst + 4; //disp32, skip 4 bytes
   8.218 -        break;
   8.219 -    }
   8.220 -
   8.221 -    if ( op_size == QUAD )
   8.222 -        op_size = LONG;
   8.223 -
   8.224 -    for ( i = 0; i < op_size; i++ ) {
   8.225 -        val |= (*inst++ & 0xff) << (8 * i);
   8.226 -    }
   8.227 -
   8.228 -    return val;
   8.229 -}
   8.230 -
   8.231 -static inline unsigned long get_immediate_sign_ext(
   8.232 -    int ad_size, const unsigned char *inst, int op_size)
   8.233 -{
   8.234 -    unsigned long result = get_immediate(ad_size, inst, op_size);
   8.235 -    if ( op_size == BYTE )
   8.236 -        return (int8_t)result;
   8.237 -    if ( op_size == WORD )
   8.238 -        return (int16_t)result;
   8.239 -    return (int32_t)result;
   8.240 -}
   8.241 -
   8.242 -static inline int get_index(const unsigned char *inst, unsigned char rex)
   8.243 -{
   8.244 -    int mod, reg, rm;
   8.245 -    int rex_r, rex_b;
   8.246 -
   8.247 -    mod = (*inst >> 6) & 3;
   8.248 -    reg = (*inst >> 3) & 7;
   8.249 -    rm = *inst & 7;
   8.250 -
   8.251 -    rex_r = (rex >> 2) & 1;
   8.252 -    rex_b = rex & 1;
   8.253 -
   8.254 -    //Only one operand in the instruction is register
   8.255 -    if ( mod == 3 ) {
   8.256 -        return (rm + (rex_b << 3));
   8.257 -    } else {
   8.258 -        return (reg + (rex_r << 3));
   8.259 -    }
   8.260 -    return 0;
   8.261 -}
   8.262 -
   8.263 -static void init_instruction(struct hvm_io_op *mmio_op)
   8.264 -{
   8.265 -    mmio_op->instr = 0;
   8.266 -
   8.267 -    mmio_op->flags = 0;
   8.268 -
   8.269 -    mmio_op->operand[0] = 0;
   8.270 -    mmio_op->operand[1] = 0;
   8.271 -    mmio_op->immediate = 0;
   8.272 -}
   8.273 -
   8.274 -#define GET_OP_SIZE_FOR_BYTE(size_reg)      \
   8.275 -    do {                                    \
   8.276 -        if ( rex )                          \
   8.277 -            (size_reg) = BYTE_64;           \
   8.278 -        else                                \
   8.279 -            (size_reg) = BYTE;              \
   8.280 -    } while( 0 )
   8.281 -
   8.282 -#define GET_OP_SIZE_FOR_NONEBYTE(op_size)   \
   8.283 -    do {                                    \
   8.284 -        if ( rex & 0x8 )                    \
   8.285 -            (op_size) = QUAD;               \
   8.286 -        else if ( (op_size) != WORD )       \
   8.287 -            (op_size) = LONG;               \
   8.288 -    } while( 0 )
   8.289 -
   8.290 -
   8.291 -/*
   8.292 - * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
   8.293 - */
   8.294 -static inline int mem_acc(unsigned char size, struct hvm_io_op *mmio)
   8.295 -{
   8.296 -    mmio->operand[0] = mk_operand(size, 0, 0, MEMORY);
   8.297 -    mmio->operand[1] = mk_operand(size, 0, 0, REGISTER);
   8.298 -    return DECODE_success;
   8.299 -}
   8.300 -
   8.301 -/*
   8.302 - * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
   8.303 - */
   8.304 -static inline int acc_mem(unsigned char size, struct hvm_io_op *mmio)
   8.305 -{
   8.306 -    mmio->operand[0] = mk_operand(size, 0, 0, REGISTER);
   8.307 -    mmio->operand[1] = mk_operand(size, 0, 0, MEMORY);
   8.308 -    return DECODE_success;
   8.309 -}
   8.310 -
   8.311 -/*
   8.312 - * Decode mem,reg operands (as in <opcode> r32/16, m32/16)
   8.313 - */
   8.314 -static int mem_reg(unsigned char size, unsigned char *opcode,
   8.315 -                   struct hvm_io_op *mmio_op, unsigned char rex)
   8.316 -{
   8.317 -    int index = get_index(opcode + 1, rex);
   8.318 -
   8.319 -    mmio_op->operand[0] = mk_operand(size, 0, 0, MEMORY);
   8.320 -    mmio_op->operand[1] = mk_operand(size, index, 0, REGISTER);
   8.321 -    return DECODE_success;
   8.322 -}
   8.323 -
   8.324 -/*
   8.325 - * Decode reg,mem operands (as in <opcode> m32/16, r32/16)
   8.326 - */
   8.327 -static int reg_mem(unsigned char size, unsigned char *opcode,
   8.328 -                   struct hvm_io_op *mmio_op, unsigned char rex)
   8.329 -{
   8.330 -    int index = get_index(opcode + 1, rex);
   8.331 -
   8.332 -    mmio_op->operand[0] = mk_operand(size, index, 0, REGISTER);
   8.333 -    mmio_op->operand[1] = mk_operand(size, 0, 0, MEMORY);
   8.334 -    return DECODE_success;
   8.335 -}
   8.336 -
   8.337 -static int mmio_decode(int address_bytes, unsigned char *opcode,
   8.338 -                       struct hvm_io_op *mmio_op,
   8.339 -                       unsigned char *ad_size, unsigned char *op_size,
   8.340 -                       unsigned char *seg_sel)
   8.341 -{
   8.342 -    unsigned char size_reg = 0;
   8.343 -    unsigned char rex = 0;
   8.344 -    int index;
   8.345 -
   8.346 -    *ad_size = 0;
   8.347 -    *op_size = 0;
   8.348 -    *seg_sel = 0;
   8.349 -    init_instruction(mmio_op);
   8.350 -
   8.351 -    opcode = check_prefix(opcode, mmio_op, ad_size, op_size, seg_sel, &rex);
   8.352 -
   8.353 -    switch ( address_bytes )
   8.354 -    {
   8.355 -    case 2:
   8.356 -        if ( *op_size == WORD )
   8.357 -            *op_size = LONG;
   8.358 -        else if ( *op_size == LONG )
   8.359 -            *op_size = WORD;
   8.360 -        else if ( *op_size == 0 )
   8.361 -            *op_size = WORD;
   8.362 -        if ( *ad_size == WORD )
   8.363 -            *ad_size = LONG;
   8.364 -        else if ( *ad_size == LONG )
   8.365 -            *ad_size = WORD;
   8.366 -        else if ( *ad_size == 0 )
   8.367 -            *ad_size = WORD;
   8.368 -        break;
   8.369 -    case 4:
   8.370 -        if ( *op_size == 0 )
   8.371 -            *op_size = LONG;
   8.372 -        if ( *ad_size == 0 )
   8.373 -            *ad_size = LONG;
   8.374 -        break;
   8.375 -#ifdef __x86_64__
   8.376 -    case 8:
   8.377 -        if ( *op_size == 0 )
   8.378 -            *op_size = rex & 0x8 ? QUAD : LONG;
   8.379 -        if ( *ad_size == WORD )
   8.380 -            *ad_size = LONG;
   8.381 -        else if ( *ad_size == 0 )
   8.382 -            *ad_size = QUAD;
   8.383 -        break;
   8.384 -#endif
   8.385 -    }
   8.386 -
   8.387 -    /* the operands order in comments conforms to AT&T convention */
   8.388 -
   8.389 -    switch ( *opcode ) {
   8.390 -
   8.391 -    case 0x00: /* add r8, m8 */
   8.392 -        mmio_op->instr = INSTR_ADD;
   8.393 -        *op_size = BYTE;
   8.394 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.395 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.396 -
   8.397 -    case 0x03: /* add m32/16, r32/16 */
   8.398 -        mmio_op->instr = INSTR_ADD;
   8.399 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.400 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.401 -
   8.402 -    case 0x08: /* or r8, m8 */	
   8.403 -        mmio_op->instr = INSTR_OR;
   8.404 -        *op_size = BYTE;
   8.405 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.406 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.407 -
   8.408 -    case 0x09: /* or r32/16, m32/16 */
   8.409 -        mmio_op->instr = INSTR_OR;
   8.410 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.411 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.412 -
   8.413 -    case 0x0A: /* or m8, r8 */
   8.414 -        mmio_op->instr = INSTR_OR;
   8.415 -        *op_size = BYTE;
   8.416 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.417 -        return mem_reg(size_reg, opcode, mmio_op, rex);
   8.418 -
   8.419 -    case 0x0B: /* or m32/16, r32/16 */
   8.420 -        mmio_op->instr = INSTR_OR;
   8.421 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.422 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.423 -
   8.424 -    case 0x20: /* and r8, m8 */
   8.425 -        mmio_op->instr = INSTR_AND;
   8.426 -        *op_size = BYTE;
   8.427 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.428 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.429 -
   8.430 -    case 0x21: /* and r32/16, m32/16 */
   8.431 -        mmio_op->instr = INSTR_AND;
   8.432 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.433 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.434 -
   8.435 -    case 0x22: /* and m8, r8 */
   8.436 -        mmio_op->instr = INSTR_AND;
   8.437 -        *op_size = BYTE;
   8.438 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.439 -        return mem_reg(size_reg, opcode, mmio_op, rex);
   8.440 -
   8.441 -    case 0x23: /* and m32/16, r32/16 */
   8.442 -        mmio_op->instr = INSTR_AND;
   8.443 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.444 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.445 -
   8.446 -    case 0x2B: /* sub m32/16, r32/16 */
   8.447 -        mmio_op->instr = INSTR_SUB;
   8.448 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.449 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.450 -
   8.451 -    case 0x30: /* xor r8, m8 */
   8.452 -        mmio_op->instr = INSTR_XOR;
   8.453 -        *op_size = BYTE;
   8.454 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.455 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.456 -
   8.457 -    case 0x31: /* xor r32/16, m32/16 */
   8.458 -        mmio_op->instr = INSTR_XOR;
   8.459 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.460 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.461 -
   8.462 -    case 0x32: /* xor m8, r8 */
   8.463 -        mmio_op->instr = INSTR_XOR;
   8.464 -        *op_size = BYTE;
   8.465 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.466 -        return mem_reg(size_reg, opcode, mmio_op, rex);
   8.467 -
   8.468 -    case 0x38: /* cmp r8, m8 */
   8.469 -        mmio_op->instr = INSTR_CMP;
   8.470 -        *op_size = BYTE;
   8.471 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.472 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.473 -
   8.474 -    case 0x39: /* cmp r32/16, m32/16 */
   8.475 -        mmio_op->instr = INSTR_CMP;
   8.476 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.477 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.478 -
   8.479 -    case 0x3A: /* cmp m8, r8 */
   8.480 -        mmio_op->instr = INSTR_CMP;
   8.481 -        *op_size = BYTE;
   8.482 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.483 -        return mem_reg(size_reg, opcode, mmio_op, rex);
   8.484 -
   8.485 -    case 0x3B: /* cmp m32/16, r32/16 */
   8.486 -        mmio_op->instr = INSTR_CMP;
   8.487 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.488 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.489 -
   8.490 -    case 0x80:
   8.491 -    case 0x81:
   8.492 -    case 0x83:
   8.493 -    {
   8.494 -        unsigned char ins_subtype = (opcode[1] >> 3) & 7;
   8.495 -
   8.496 -        if ( opcode[0] == 0x80 ) {
   8.497 -            *op_size = BYTE;
   8.498 -            GET_OP_SIZE_FOR_BYTE(size_reg);
   8.499 -        } else {
   8.500 -            GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.501 -            size_reg = *op_size;
   8.502 -        }
   8.503 -
   8.504 -        /* opcode 0x83 always has a single byte operand */
   8.505 -        if ( opcode[0] == 0x83 )
   8.506 -            mmio_op->immediate =
   8.507 -                get_immediate_sign_ext(*ad_size, opcode + 1, BYTE);
   8.508 -        else
   8.509 -            mmio_op->immediate =
   8.510 -                get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
   8.511 -
   8.512 -        mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
   8.513 -        mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
   8.514 -
   8.515 -        switch ( ins_subtype ) {
   8.516 -        case 0: /* add $imm, m32/16 */
   8.517 -            mmio_op->instr = INSTR_ADD;
   8.518 -            return DECODE_success;
   8.519 -
   8.520 -        case 1: /* or $imm, m32/16 */
   8.521 -            mmio_op->instr = INSTR_OR;
   8.522 -            return DECODE_success;
   8.523 -
   8.524 -        case 4: /* and $imm, m32/16 */
   8.525 -            mmio_op->instr = INSTR_AND;
   8.526 -            return DECODE_success;
   8.527 -
   8.528 -        case 5: /* sub $imm, m32/16 */
   8.529 -            mmio_op->instr = INSTR_SUB;
   8.530 -            return DECODE_success;
   8.531 -
   8.532 -        case 6: /* xor $imm, m32/16 */
   8.533 -            mmio_op->instr = INSTR_XOR;
   8.534 -            return DECODE_success;
   8.535 -
   8.536 -        case 7: /* cmp $imm, m32/16 */
   8.537 -            mmio_op->instr = INSTR_CMP;
   8.538 -            return DECODE_success;
   8.539 -
   8.540 -        default:
   8.541 -            printk("%x/%x, This opcode isn't handled yet!\n",
   8.542 -                   *opcode, ins_subtype);
   8.543 -            return DECODE_failure;
   8.544 -        }
   8.545 -    }
   8.546 -
   8.547 -    case 0x84:  /* test r8, m8 */
   8.548 -        mmio_op->instr = INSTR_TEST;
   8.549 -        *op_size = BYTE;
   8.550 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.551 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.552 -
   8.553 -    case 0x85: /* test r16/32, m16/32 */
   8.554 -        mmio_op->instr = INSTR_TEST;
   8.555 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.556 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.557 -
   8.558 -    case 0x86:  /* xchg m8, r8 */
   8.559 -        mmio_op->instr = INSTR_XCHG;
   8.560 -        *op_size = BYTE;
   8.561 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.562 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.563 -
   8.564 -    case 0x87:  /* xchg m16/32, r16/32 */
   8.565 -        mmio_op->instr = INSTR_XCHG;
   8.566 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.567 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.568 -
   8.569 -    case 0x88: /* mov r8, m8 */
   8.570 -        mmio_op->instr = INSTR_MOV;
   8.571 -        *op_size = BYTE;
   8.572 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.573 -        return reg_mem(size_reg, opcode, mmio_op, rex);
   8.574 -
   8.575 -    case 0x89: /* mov r32/16, m32/16 */
   8.576 -        mmio_op->instr = INSTR_MOV;
   8.577 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.578 -        return reg_mem(*op_size, opcode, mmio_op, rex);
   8.579 -
   8.580 -    case 0x8A: /* mov m8, r8 */
   8.581 -        mmio_op->instr = INSTR_MOV;
   8.582 -        *op_size = BYTE;
   8.583 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.584 -        return mem_reg(size_reg, opcode, mmio_op, rex);
   8.585 -
   8.586 -    case 0x8B: /* mov m32/16, r32/16 */
   8.587 -        mmio_op->instr = INSTR_MOV;
   8.588 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.589 -        return mem_reg(*op_size, opcode, mmio_op, rex);
   8.590 -
   8.591 -    case 0xA0: /* mov <addr>, al */
   8.592 -        mmio_op->instr = INSTR_MOV;
   8.593 -        *op_size = BYTE;
   8.594 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.595 -        return mem_acc(size_reg, mmio_op);
   8.596 -
   8.597 -    case 0xA1: /* mov <addr>, ax/eax */
   8.598 -        mmio_op->instr = INSTR_MOV;
   8.599 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.600 -        return mem_acc(*op_size, mmio_op);
   8.601 -
   8.602 -    case 0xA2: /* mov al, <addr> */
   8.603 -        mmio_op->instr = INSTR_MOV;
   8.604 -        *op_size = BYTE;
   8.605 -        GET_OP_SIZE_FOR_BYTE(size_reg);
   8.606 -        return acc_mem(size_reg, mmio_op);
   8.607 -
   8.608 -    case 0xA3: /* mov ax/eax, <addr> */
   8.609 -        mmio_op->instr = INSTR_MOV;
   8.610 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.611 -        return acc_mem(*op_size, mmio_op);
   8.612 -
   8.613 -    case 0xA4: /* movsb */
   8.614 -        mmio_op->instr = INSTR_MOVS;
   8.615 -        *op_size = BYTE;
   8.616 -        return DECODE_success;
   8.617 -
   8.618 -    case 0xA5: /* movsw/movsl */
   8.619 -        mmio_op->instr = INSTR_MOVS;
   8.620 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.621 -        return DECODE_success;
   8.622 -
   8.623 -    case 0xAA: /* stosb */
   8.624 -        mmio_op->instr = INSTR_STOS;
   8.625 -        *op_size = BYTE;
   8.626 -        return DECODE_success;
   8.627 -
   8.628 -    case 0xAB: /* stosw/stosl */
   8.629 -        mmio_op->instr = INSTR_STOS;
   8.630 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.631 -        return DECODE_success;
   8.632 -
   8.633 -    case 0xAC: /* lodsb */
   8.634 -        mmio_op->instr = INSTR_LODS;
   8.635 -        *op_size = BYTE;
   8.636 -        return DECODE_success;
   8.637 -
   8.638 -    case 0xAD: /* lodsw/lodsl */
   8.639 -        mmio_op->instr = INSTR_LODS;
   8.640 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.641 -        return DECODE_success;
   8.642 -
   8.643 -    case 0xC6:
   8.644 -        if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm8, m8 */
   8.645 -            mmio_op->instr = INSTR_MOV;
   8.646 -            *op_size = BYTE;
   8.647 -
   8.648 -            mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
   8.649 -            mmio_op->immediate  =
   8.650 -                    get_immediate(*ad_size, opcode + 1, *op_size);
   8.651 -            mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
   8.652 -
   8.653 -            return DECODE_success;
   8.654 -        } else
   8.655 -            return DECODE_failure;
   8.656 -
   8.657 -    case 0xC7:
   8.658 -        if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm16/32, m16/32 */
   8.659 -            mmio_op->instr = INSTR_MOV;
   8.660 -            GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.661 -
   8.662 -            mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
   8.663 -            mmio_op->immediate =
   8.664 -                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
   8.665 -            mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
   8.666 -
   8.667 -            return DECODE_success;
   8.668 -        } else
   8.669 -            return DECODE_failure;
   8.670 -
   8.671 -    case 0xF6:
   8.672 -    case 0xF7:
   8.673 -        if ( ((opcode[1] >> 3) & 7) == 0 ) { /* test $imm8/16/32, m8/16/32 */
   8.674 -            mmio_op->instr = INSTR_TEST;
   8.675 -
   8.676 -            if ( opcode[0] == 0xF6 ) {
   8.677 -                *op_size = BYTE;
   8.678 -                GET_OP_SIZE_FOR_BYTE(size_reg);
   8.679 -            } else {
   8.680 -                GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.681 -                size_reg = *op_size;
   8.682 -            }
   8.683 -
   8.684 -            mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
   8.685 -            mmio_op->immediate =
   8.686 -                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
   8.687 -            mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
   8.688 -
   8.689 -            return DECODE_success;
   8.690 -        } else
   8.691 -            return DECODE_failure;
   8.692 -
   8.693 -    case 0xFE:
   8.694 -    case 0xFF:
   8.695 -    {
   8.696 -        unsigned char ins_subtype = (opcode[1] >> 3) & 7;
   8.697 -
   8.698 -        if ( opcode[0] == 0xFE ) {
   8.699 -            *op_size = BYTE;
   8.700 -            GET_OP_SIZE_FOR_BYTE(size_reg);
   8.701 -        } else {
   8.702 -            GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.703 -            size_reg = *op_size;
   8.704 -        }
   8.705 -
   8.706 -        mmio_op->immediate = 1;
   8.707 -        mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
   8.708 -        mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
   8.709 -
   8.710 -        switch ( ins_subtype ) {
   8.711 -        case 0: /* inc */
   8.712 -            mmio_op->instr = INSTR_ADD;
   8.713 -            return DECODE_success;
   8.714 -
   8.715 -        case 1: /* dec */
   8.716 -            mmio_op->instr = INSTR_SUB;
   8.717 -            return DECODE_success;
   8.718 -
   8.719 -        case 6: /* push */
   8.720 -            mmio_op->instr = INSTR_PUSH;
   8.721 -            mmio_op->operand[0] = mmio_op->operand[1];
   8.722 -            return DECODE_success;
   8.723 -
   8.724 -        default:
   8.725 -            printk("%x/%x, This opcode isn't handled yet!\n",
   8.726 -                   *opcode, ins_subtype);
   8.727 -            return DECODE_failure;
   8.728 -        }
   8.729 -    }
   8.730 -
   8.731 -    case 0x0F:
   8.732 -        break;
   8.733 -
   8.734 -    default:
   8.735 -        printk("%x, This opcode isn't handled yet!\n", *opcode);
   8.736 -        return DECODE_failure;
   8.737 -    }
   8.738 -
   8.739 -    switch ( *++opcode ) {
   8.740 -    case 0xB6: /* movzx m8, r16/r32/r64 */
   8.741 -        mmio_op->instr = INSTR_MOVZX;
   8.742 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.743 -        index = get_index(opcode + 1, rex);
   8.744 -        mmio_op->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
   8.745 -        mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
   8.746 -        return DECODE_success;
   8.747 -
   8.748 -    case 0xB7: /* movzx m16, r32/r64 */
   8.749 -        mmio_op->instr = INSTR_MOVZX;
   8.750 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.751 -        index = get_index(opcode + 1, rex);
   8.752 -        mmio_op->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
   8.753 -        mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
   8.754 -        return DECODE_success;
   8.755 -
   8.756 -    case 0xBE: /* movsx m8, r16/r32/r64 */
   8.757 -        mmio_op->instr = INSTR_MOVSX;
   8.758 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.759 -        index = get_index(opcode + 1, rex);
   8.760 -        mmio_op->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
   8.761 -        mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
   8.762 -        return DECODE_success;
   8.763 -
   8.764 -    case 0xBF: /* movsx m16, r32/r64 */
   8.765 -        mmio_op->instr = INSTR_MOVSX;
   8.766 -        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.767 -        index = get_index(opcode + 1, rex);
   8.768 -        mmio_op->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
   8.769 -        mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
   8.770 -        return DECODE_success;
   8.771 -
   8.772 -    case 0xA3: /* bt r32, m32 */
   8.773 -        mmio_op->instr = INSTR_BT;
   8.774 -        index = get_index(opcode + 1, rex);
   8.775 -        *op_size = LONG;
   8.776 -        mmio_op->operand[0] = mk_operand(*op_size, index, 0, REGISTER);
   8.777 -        mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
   8.778 -        return DECODE_success;
   8.779 -
   8.780 -    case 0xBA:
   8.781 -        if ( ((opcode[1] >> 3) & 7) == 4 ) /* BT $imm8, m16/32/64 */
   8.782 -        {
   8.783 -            mmio_op->instr = INSTR_BT;
   8.784 -            GET_OP_SIZE_FOR_NONEBYTE(*op_size);
   8.785 -            mmio_op->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
   8.786 -            mmio_op->immediate =
   8.787 -                    (signed char)get_immediate(*ad_size, opcode + 1, BYTE);
   8.788 -            mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
   8.789 -            return DECODE_success;
   8.790 -        }
   8.791 -        else
   8.792 -        {
   8.793 -            printk("0f %x, This opcode subtype isn't handled yet\n", *opcode);
   8.794 -            return DECODE_failure;
   8.795 -        }
   8.796 -
   8.797 -    default:
   8.798 -        printk("0f %x, This opcode isn't handled yet\n", *opcode);
   8.799 -        return DECODE_failure;
   8.800 -    }
   8.801 -}
   8.802 +#include <asm/hvm/emulate.h>
   8.803  
   8.804  int inst_copy_from_guest(
   8.805      unsigned char *buf, unsigned long guest_eip, int inst_len)
   8.806 @@ -984,323 +192,41 @@ void send_invalidate_req(void)
   8.807      hvm_send_assist_req(v);
   8.808  }
   8.809  
   8.810 -static void mmio_operands(int type, unsigned long gpa,
   8.811 -                          struct hvm_io_op *mmio_op,
   8.812 -                          unsigned char op_size)
   8.813 -{
   8.814 -    unsigned long value = 0;
   8.815 -    int df, index, size_reg;
   8.816 -    struct cpu_user_regs *regs = &mmio_op->io_context;
   8.817 -
   8.818 -    df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
   8.819 -
   8.820 -    size_reg = operand_size(mmio_op->operand[0]);
   8.821 -
   8.822 -    if ( mmio_op->operand[0] & REGISTER ) {            /* dest is memory */
   8.823 -        index = operand_index(mmio_op->operand[0]);
   8.824 -        value = get_reg_value(size_reg, index, 0, regs);
   8.825 -        send_mmio_req(type, gpa, 1, op_size, value, IOREQ_WRITE, df, 0);
   8.826 -    } else if ( mmio_op->operand[0] & IMMEDIATE ) {    /* dest is memory */
   8.827 -        value = mmio_op->immediate;
   8.828 -        send_mmio_req(type, gpa, 1, op_size, value, IOREQ_WRITE, df, 0);
   8.829 -    } else if ( mmio_op->operand[0] & MEMORY ) {       /* dest is register */
   8.830 -        /* send the request and wait for the value */
   8.831 -        if ( (mmio_op->instr == INSTR_MOVZX) ||
   8.832 -             (mmio_op->instr == INSTR_MOVSX) )
   8.833 -            send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, df, 0);
   8.834 -        else
   8.835 -            send_mmio_req(type, gpa, 1, op_size, 0, IOREQ_READ, df, 0);
   8.836 -    } else {
   8.837 -        printk("%s: invalid dest mode.\n", __func__);
   8.838 -        domain_crash_synchronous();
   8.839 -    }
   8.840 -}
   8.841 -
   8.842 -#define GET_REPEAT_COUNT() \
   8.843 -     (mmio_op->flags & REPZ ? (ad_size == WORD ? regs->ecx & 0xFFFF : regs->ecx) : 1)
   8.844 -
   8.845 -
   8.846 -void handle_mmio(paddr_t gpa)
   8.847 +int handle_mmio(void)
   8.848  {
   8.849 -    unsigned long inst_addr;
   8.850 -    struct hvm_io_op *mmio_op;
   8.851 -    struct cpu_user_regs *regs;
   8.852 -    unsigned char inst[MAX_INST_LEN], ad_size, op_size, seg_sel;
   8.853 -    int i, address_bytes, df, inst_len;
   8.854 -    struct vcpu *v = current;
   8.855 -
   8.856 -    mmio_op = &v->arch.hvm_vcpu.io_op;
   8.857 -    regs = &mmio_op->io_context;
   8.858 -
   8.859 -    /* Copy current guest state into io instruction state structure. */
   8.860 -    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
   8.861 -
   8.862 -    df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
   8.863 -
   8.864 -    address_bytes = hvm_guest_x86_mode(v);
   8.865 -    if (address_bytes < 2)
   8.866 -        /* real or vm86 modes */
   8.867 -        address_bytes = 2;
   8.868 -    inst_addr = hvm_get_segment_base(v, x86_seg_cs) + regs->eip;
   8.869 -    memset(inst, 0, MAX_INST_LEN);
   8.870 -    inst_len = hvm_instruction_fetch(inst_addr, address_bytes, inst);
   8.871 -    if ( inst_len <= 0 )
   8.872 -    {
   8.873 -        gdprintk(XENLOG_DEBUG, "handle_mmio: failed to get instruction\n");
   8.874 -        /* hvm_instruction_fetch() will have injected a #PF; get out now */
   8.875 -        return;
   8.876 -    }
   8.877 -
   8.878 -    if ( mmio_decode(address_bytes, inst, mmio_op, &ad_size,
   8.879 -                     &op_size, &seg_sel) == DECODE_failure )
   8.880 -    {
   8.881 -        gdprintk(XENLOG_WARNING,
   8.882 -                 "handle_mmio: failed to decode instruction\n");
   8.883 -        gdprintk(XENLOG_WARNING,
   8.884 -                 "mmio opcode: gpa 0x%"PRIpaddr", len %d:", gpa, inst_len);
   8.885 -        for ( i = 0; i < inst_len; i++ )
   8.886 -            printk(" %02x", inst[i] & 0xFF);
   8.887 -        printk("\n");
   8.888 -
   8.889 -        hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0);
   8.890 -        return;
   8.891 -    }
   8.892 -
   8.893 -    regs->eip += inst_len; /* advance %eip */
   8.894 -
   8.895 -    switch ( mmio_op->instr ) {
   8.896 -    case INSTR_MOV:
   8.897 -        mmio_operands(IOREQ_TYPE_COPY, gpa, mmio_op, op_size);
   8.898 -        break;
   8.899 -
   8.900 -    case INSTR_MOVS:
   8.901 -    {
   8.902 -        struct segment_register sreg;
   8.903 -        unsigned long count = GET_REPEAT_COUNT();
   8.904 -        int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
   8.905 -        unsigned long addr, gfn; 
   8.906 -        paddr_t paddr;
   8.907 -        int dir, size = op_size;
   8.908 -        uint32_t pfec;
   8.909 +    struct hvm_emulate_ctxt ctxt;
   8.910 +    struct vcpu *curr = current;
   8.911 +    int rc;
   8.912  
   8.913 -        ASSERT(count);
   8.914 -
   8.915 -        /* determine non-MMIO address */
   8.916 -        addr = regs->edi;
   8.917 -        if ( ad_size == WORD )
   8.918 -            addr &= 0xFFFF;
   8.919 -        addr += hvm_get_segment_base(v, x86_seg_es);        
   8.920 -        pfec = PFEC_page_present | PFEC_write_access;
   8.921 -        hvm_get_segment_register(v, x86_seg_ss, &sreg);
   8.922 -        if ( sreg.attr.fields.dpl == 3 )
   8.923 -            pfec |= PFEC_user_mode;
   8.924 -        gfn = paging_gva_to_gfn(v, addr, &pfec);
   8.925 -        paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
   8.926 -        if ( paddr == gpa )
   8.927 -        {
   8.928 -            enum x86_segment seg;
   8.929 -
   8.930 -            dir = IOREQ_WRITE;
   8.931 -            addr = regs->esi;
   8.932 -            if ( ad_size == WORD )
   8.933 -                addr &= 0xFFFF;
   8.934 -            switch ( seg_sel )
   8.935 -            {
   8.936 -            case 0x26: seg = x86_seg_es; break;
   8.937 -            case 0x2e: seg = x86_seg_cs; break;
   8.938 -            case 0x36: seg = x86_seg_ss; break;
   8.939 -            case 0:
   8.940 -            case 0x3e: seg = x86_seg_ds; break;
   8.941 -            case 0x64: seg = x86_seg_fs; break;
   8.942 -            case 0x65: seg = x86_seg_gs; break;
   8.943 -            default: domain_crash_synchronous();
   8.944 -            }
   8.945 -            addr += hvm_get_segment_base(v, seg);
   8.946 -            pfec &= ~PFEC_write_access;
   8.947 -            gfn = paging_gva_to_gfn(v, addr, &pfec);
   8.948 -            paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
   8.949 -        }
   8.950 -        else
   8.951 -            dir = IOREQ_READ;
   8.952 -
   8.953 -        if ( gfn == INVALID_GFN ) 
   8.954 -        {
   8.955 -            /* The guest does not have the non-mmio address mapped. 
   8.956 -             * Need to send in a page fault */
   8.957 -            regs->eip -= inst_len; /* do not advance %eip */
   8.958 -            hvm_inject_exception(TRAP_page_fault, pfec, addr);
   8.959 -            return;
   8.960 -        }
   8.961 +    hvm_emulate_prepare(&ctxt, guest_cpu_user_regs());
   8.962  
   8.963 -        /*
   8.964 -         * In case of a movs spanning multiple pages, we break the accesses
   8.965 -         * up into multiple pages (the device model works with non-continguous
   8.966 -         * physical guest pages). To copy just one page, we adjust %ecx and
   8.967 -         * do not advance %eip so that the next rep;movs copies the next page.
   8.968 -         * Unaligned accesses, for example movsl starting at PGSZ-2, are
   8.969 -         * turned into a single copy where we handle the overlapping memory
   8.970 -         * copy ourself. After this copy succeeds, "rep movs" is executed
   8.971 -         * again.
   8.972 -         */
   8.973 -        if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
   8.974 -            unsigned long value = 0;
   8.975 -
   8.976 -            mmio_op->flags |= OVERLAP;
   8.977 +    rc = hvm_emulate_one(&ctxt);
   8.978  
   8.979 -            if ( dir == IOREQ_WRITE ) {
   8.980 -                if ( hvm_paging_enabled(v) )
   8.981 -                {
   8.982 -                    int rv = hvm_copy_from_guest_virt(&value, addr, size);
   8.983 -                    if ( rv == HVMCOPY_bad_gva_to_gfn ) 
   8.984 -                        return; /* exception already injected */
   8.985 -                }
   8.986 -                else
   8.987 -                    (void)hvm_copy_from_guest_phys(&value, addr, size);
   8.988 -            } else /* dir != IOREQ_WRITE */
   8.989 -                /* Remember where to write the result, as a *VA*.
   8.990 -                 * Must be a VA so we can handle the page overlap 
   8.991 -                 * correctly in hvm_mmio_assist() */
   8.992 -                mmio_op->addr = addr;
   8.993 -
   8.994 -            if ( count != 1 )
   8.995 -                regs->eip -= inst_len; /* do not advance %eip */
   8.996 -
   8.997 -            send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, df, 0);
   8.998 -        } else {
   8.999 -            unsigned long last_addr = sign > 0 ? addr + count * size - 1
  8.1000 -                                               : addr - (count - 1) * size;
  8.1001 -
  8.1002 -            if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
  8.1003 -            {
  8.1004 -                regs->eip -= inst_len; /* do not advance %eip */
  8.1005 -
  8.1006 -                if ( sign > 0 )
  8.1007 -                    count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
  8.1008 -                else
  8.1009 -                    count = (addr & ~PAGE_MASK) / size + 1;
  8.1010 -            }
  8.1011 -
  8.1012 -            ASSERT(count);
  8.1013 -
  8.1014 -            send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, 
  8.1015 -                          paddr, dir, df, 1);
  8.1016 -        }
  8.1017 +    switch ( rc )
  8.1018 +    {
  8.1019 +    case X86EMUL_UNHANDLEABLE:
  8.1020 +        gdprintk(XENLOG_WARNING,
  8.1021 +                 "MMIO emulation failed @ %04x:%lx: "
  8.1022 +                 "%02x %02x %02x %02x %02x %02x\n",
  8.1023 +                 hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
  8.1024 +                 ctxt.insn_buf_eip,
  8.1025 +                 ctxt.insn_buf[0], ctxt.insn_buf[1],
  8.1026 +                 ctxt.insn_buf[2], ctxt.insn_buf[3],
  8.1027 +                 ctxt.insn_buf[4], ctxt.insn_buf[5]);
  8.1028 +        return 0;
  8.1029 +    case X86EMUL_EXCEPTION:
  8.1030 +        if ( ctxt.flags.exn_pending )
  8.1031 +            hvm_inject_exception(ctxt.exn_vector, 0, 0);
  8.1032 +        break;
  8.1033 +    default:
  8.1034          break;
  8.1035      }
  8.1036  
  8.1037 -    case INSTR_MOVZX:
  8.1038 -    case INSTR_MOVSX:
  8.1039 -        mmio_operands(IOREQ_TYPE_COPY, gpa, mmio_op, op_size);
  8.1040 -        break;
  8.1041 -
  8.1042 -    case INSTR_STOS:
  8.1043 -        /*
  8.1044 -         * Since the destination is always in (contiguous) mmio space we don't
  8.1045 -         * need to break it up into pages.
  8.1046 -         */
  8.1047 -        send_mmio_req(IOREQ_TYPE_COPY, gpa,
  8.1048 -                      GET_REPEAT_COUNT(), op_size, regs->eax, IOREQ_WRITE, df, 0);
  8.1049 -        break;
  8.1050 -
  8.1051 -    case INSTR_LODS:
  8.1052 -        /*
  8.1053 -         * Since the source is always in (contiguous) mmio space we don't
  8.1054 -         * need to break it up into pages.
  8.1055 -         */
  8.1056 -        mmio_op->operand[0] = mk_operand(op_size, 0, 0, REGISTER);
  8.1057 -        send_mmio_req(IOREQ_TYPE_COPY, gpa,
  8.1058 -                      GET_REPEAT_COUNT(), op_size, 0, IOREQ_READ, df, 0);
  8.1059 -        break;
  8.1060 -
  8.1061 -    case INSTR_OR:
  8.1062 -        mmio_operands(IOREQ_TYPE_OR, gpa, mmio_op, op_size);
  8.1063 -        break;
  8.1064 -
  8.1065 -    case INSTR_AND:
  8.1066 -        mmio_operands(IOREQ_TYPE_AND, gpa, mmio_op, op_size);
  8.1067 -        break;
  8.1068 -
  8.1069 -    case INSTR_ADD:
  8.1070 -        mmio_operands(IOREQ_TYPE_ADD, gpa, mmio_op, op_size);
  8.1071 -        break;
  8.1072 -
  8.1073 -    case INSTR_SUB:
  8.1074 -        mmio_operands(IOREQ_TYPE_SUB, gpa, mmio_op, op_size);
  8.1075 -        break;
  8.1076 -
  8.1077 -    case INSTR_XOR:
  8.1078 -        mmio_operands(IOREQ_TYPE_XOR, gpa, mmio_op, op_size);
  8.1079 -        break;
  8.1080 +    hvm_emulate_writeback(&ctxt);
  8.1081  
  8.1082 -    case INSTR_PUSH:
  8.1083 -        if ( ad_size == WORD )
  8.1084 -        {
  8.1085 -            mmio_op->addr = (uint16_t)(regs->esp - op_size);
  8.1086 -            regs->esp = mmio_op->addr | (regs->esp & ~0xffff);
  8.1087 -        }
  8.1088 -        else
  8.1089 -        {
  8.1090 -            regs->esp -= op_size;
  8.1091 -            mmio_op->addr = regs->esp;
  8.1092 -        }
  8.1093 -        /* send the request and wait for the value */
  8.1094 -        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, op_size, 0, IOREQ_READ, df, 0);
  8.1095 -        break;
  8.1096 -
  8.1097 -    case INSTR_CMP:        /* Pass through */
  8.1098 -    case INSTR_TEST:
  8.1099 -        /* send the request and wait for the value */
  8.1100 -        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, op_size, 0, IOREQ_READ, df, 0);
  8.1101 -        break;
  8.1102 -
  8.1103 -    case INSTR_BT:
  8.1104 -    {
  8.1105 -        unsigned long value = 0;
  8.1106 -        int index, size;
  8.1107 +    curr->arch.hvm_vcpu.mmio_in_progress = curr->arch.hvm_vcpu.io_in_progress;
  8.1108  
  8.1109 -        if ( mmio_op->operand[0] & REGISTER )
  8.1110 -        {
  8.1111 -            index = operand_index(mmio_op->operand[0]);
  8.1112 -            size = operand_size(mmio_op->operand[0]);
  8.1113 -            value = get_reg_value(size, index, 0, regs);
  8.1114 -        }
  8.1115 -        else if ( mmio_op->operand[0] & IMMEDIATE )
  8.1116 -        {
  8.1117 -            mmio_op->immediate = mmio_op->immediate;
  8.1118 -            value = mmio_op->immediate;
  8.1119 -        }
  8.1120 -        send_mmio_req(IOREQ_TYPE_COPY, gpa + (value >> 5), 1,
  8.1121 -                      op_size, 0, IOREQ_READ, df, 0);
  8.1122 -        break;
  8.1123 -    }
  8.1124 -
  8.1125 -    case INSTR_XCHG:
  8.1126 -        if ( mmio_op->operand[0] & REGISTER ) {
  8.1127 -            long value;
  8.1128 -            unsigned long operand = mmio_op->operand[0];
  8.1129 -            value = get_reg_value(operand_size(operand),
  8.1130 -                                  operand_index(operand), 0,
  8.1131 -                                  regs);
  8.1132 -            /* send the request and wait for the value */
  8.1133 -            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
  8.1134 -                          op_size, value, IOREQ_WRITE, df, 0);
  8.1135 -        } else {
  8.1136 -            /* the destination is a register */
  8.1137 -            long value;
  8.1138 -            unsigned long operand = mmio_op->operand[1];
  8.1139 -            value = get_reg_value(operand_size(operand),
  8.1140 -                                  operand_index(operand), 0,
  8.1141 -                                  regs);
  8.1142 -            /* send the request and wait for the value */
  8.1143 -            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
  8.1144 -                          op_size, value, IOREQ_WRITE, df, 0);
  8.1145 -        }
  8.1146 -        break;
  8.1147 -
  8.1148 -    default:
  8.1149 -        printk("Unhandled MMIO instruction\n");
  8.1150 -        domain_crash_synchronous();
  8.1151 -    }
  8.1152 +    return 1;
  8.1153  }
  8.1154  
  8.1155  DEFINE_PER_CPU(int, guest_handles_in_xen_space);
     9.1 --- a/xen/arch/x86/hvm/stdvga.c	Tue Feb 19 11:14:40 2008 -0700
     9.2 +++ b/xen/arch/x86/hvm/stdvga.c	Wed Feb 20 14:36:45 2008 +0000
     9.3 @@ -458,33 +458,6 @@ static int mmio_move(struct hvm_hw_stdvg
     9.4      return 1;
     9.5  }
     9.6  
     9.7 -static uint32_t op_and(uint32_t a, uint32_t b) { return a & b; }
     9.8 -static uint32_t op_or (uint32_t a, uint32_t b) { return a | b; }
     9.9 -static uint32_t op_xor(uint32_t a, uint32_t b) { return a ^ b; }
    9.10 -static uint32_t op_add(uint32_t a, uint32_t b) { return a + b; }
    9.11 -static uint32_t op_sub(uint32_t a, uint32_t b) { return a - b; }
    9.12 -static uint32_t (*op_array[])(uint32_t, uint32_t) = {
    9.13 -    [IOREQ_TYPE_AND] = op_and,
    9.14 -    [IOREQ_TYPE_OR ] = op_or,
    9.15 -    [IOREQ_TYPE_XOR] = op_xor,
    9.16 -    [IOREQ_TYPE_ADD] = op_add,
    9.17 -    [IOREQ_TYPE_SUB] = op_sub
    9.18 -};
    9.19 -
    9.20 -static int mmio_op(struct hvm_hw_stdvga *s, ioreq_t *p)
    9.21 -{
    9.22 -    uint32_t orig, mod = 0;
    9.23 -    orig = stdvga_mem_read(p->addr, p->size);
    9.24 -
    9.25 -    if ( p->dir == IOREQ_WRITE )
    9.26 -    {
    9.27 -        mod = (op_array[p->type])(orig, p->data);
    9.28 -        stdvga_mem_write(p->addr, mod, p->size);
    9.29 -    }
    9.30 -
    9.31 -    return 0; /* Don't try to buffer these operations */
    9.32 -}
    9.33 -
    9.34  int stdvga_intercept_mmio(ioreq_t *p)
    9.35  {
    9.36      struct domain *d = current->domain;
    9.37 @@ -506,13 +479,6 @@ int stdvga_intercept_mmio(ioreq_t *p)
    9.38          case IOREQ_TYPE_COPY:
    9.39              buf = mmio_move(s, p);
    9.40              break;
    9.41 -        case IOREQ_TYPE_AND:
    9.42 -        case IOREQ_TYPE_OR:
    9.43 -        case IOREQ_TYPE_XOR:
    9.44 -        case IOREQ_TYPE_ADD:
    9.45 -        case IOREQ_TYPE_SUB:
    9.46 -            buf = mmio_op(s, p);
    9.47 -            break;
    9.48          default:
    9.49              gdprintk(XENLOG_WARNING, "unsupported mmio request type:%d "
    9.50                       "addr:0x%04x data:0x%04x size:%d count:%d state:%d "
    10.1 --- a/xen/arch/x86/hvm/svm/svm.c	Tue Feb 19 11:14:40 2008 -0700
    10.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Feb 20 14:36:45 2008 +0000
    10.3 @@ -66,6 +66,13 @@ static void svm_update_guest_cr(struct v
    10.4  static void svm_update_guest_efer(struct vcpu *v);
    10.5  static void svm_inject_exception(
    10.6      unsigned int trapnr, int errcode, unsigned long cr2);
    10.7 +static void svm_cpuid_intercept(
    10.8 +    unsigned int *eax, unsigned int *ebx,
    10.9 +    unsigned int *ecx, unsigned int *edx);
   10.10 +static void svm_wbinvd_intercept(void);
   10.11 +static void svm_fpu_dirty_intercept(void);
   10.12 +static int svm_msr_read_intercept(struct cpu_user_regs *regs);
   10.13 +static int svm_msr_write_intercept(struct cpu_user_regs *regs);
   10.14  
   10.15  /* va of hardware host save area     */
   10.16  static void *hsa[NR_CPUS] __read_mostly;
   10.17 @@ -112,7 +119,7 @@ static enum handler_return long_mode_do_
   10.18      switch ( ecx )
   10.19      {
   10.20      case MSR_EFER:
   10.21 -        if ( !hvm_set_efer(msr_content) )
   10.22 +        if ( hvm_set_efer(msr_content) )
   10.23              return HNDL_exception_raised;
   10.24          break;
   10.25  
   10.26 @@ -808,7 +815,12 @@ static struct hvm_function_table svm_fun
   10.27      .inject_exception     = svm_inject_exception,
   10.28      .init_hypercall_page  = svm_init_hypercall_page,
   10.29      .event_pending        = svm_event_pending,
   10.30 -    .do_pmu_interrupt     = svm_do_pmu_interrupt
   10.31 +    .do_pmu_interrupt     = svm_do_pmu_interrupt,
   10.32 +    .cpuid_intercept      = svm_cpuid_intercept,
   10.33 +    .wbinvd_intercept     = svm_wbinvd_intercept,
   10.34 +    .fpu_dirty_intercept  = svm_fpu_dirty_intercept,
   10.35 +    .msr_read_intercept   = svm_msr_read_intercept,
   10.36 +    .msr_write_intercept  = svm_msr_write_intercept
   10.37  };
   10.38  
   10.39  int start_svm(struct cpuinfo_x86 *c)
   10.40 @@ -873,7 +885,8 @@ static void svm_do_nested_pgfault(paddr_
   10.41      mfn = gfn_to_mfn_current(gfn, &p2mt);
   10.42      if ( p2mt == p2m_mmio_dm )
   10.43      {
   10.44 -        handle_mmio(gpa);
   10.45 +        if ( !handle_mmio() )
   10.46 +            hvm_inject_exception(TRAP_gp_fault, 0, 0);
   10.47          return;
   10.48      }
   10.49  
   10.50 @@ -882,9 +895,10 @@ static void svm_do_nested_pgfault(paddr_
   10.51      p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
   10.52  }
   10.53  
   10.54 -static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
   10.55 +static void svm_fpu_dirty_intercept(void)
   10.56  {
   10.57      struct vcpu *curr = current;
   10.58 +    struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
   10.59  
   10.60      svm_fpu_enter(curr);
   10.61  
   10.62 @@ -893,72 +907,83 @@ static void svm_do_no_device_fault(struc
   10.63  }
   10.64  
   10.65  #define bitmaskof(idx)  (1U << ((idx) & 31))
   10.66 -static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb,
   10.67 -                                struct cpu_user_regs *regs)
   10.68 +static void svm_cpuid_intercept(
   10.69 +    unsigned int *eax, unsigned int *ebx,
   10.70 +    unsigned int *ecx, unsigned int *edx)
   10.71  {
   10.72 -    unsigned long input = regs->eax;
   10.73 -    unsigned int eax, ebx, ecx, edx;
   10.74 +    unsigned int input = *eax;
   10.75      struct vcpu *v = current;
   10.76 -    int inst_len;
   10.77  
   10.78 -    hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
   10.79 +    hvm_cpuid(input, eax, ebx, ecx, edx);
   10.80  
   10.81      switch ( input )
   10.82      {
   10.83      case 0x00000001:
   10.84          /* Mask Intel-only features. */
   10.85 -        ecx &= ~(bitmaskof(X86_FEATURE_SSSE3) |
   10.86 -                 bitmaskof(X86_FEATURE_SSE4_1) |
   10.87 -                 bitmaskof(X86_FEATURE_SSE4_2));
   10.88 +        *ecx &= ~(bitmaskof(X86_FEATURE_SSSE3) |
   10.89 +                  bitmaskof(X86_FEATURE_SSE4_1) |
   10.90 +                  bitmaskof(X86_FEATURE_SSE4_2));
   10.91          break;
   10.92  
   10.93      case 0x80000001:
   10.94          /* Filter features which are shared with 0x00000001:EDX. */
   10.95          if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
   10.96 -            __clear_bit(X86_FEATURE_APIC & 31, &edx);
   10.97 +            __clear_bit(X86_FEATURE_APIC & 31, edx);
   10.98  #if CONFIG_PAGING_LEVELS >= 3
   10.99          if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
  10.100  #endif
  10.101 -            __clear_bit(X86_FEATURE_PAE & 31, &edx);
  10.102 -        __clear_bit(X86_FEATURE_PSE36 & 31, &edx);
  10.103 +            __clear_bit(X86_FEATURE_PAE & 31, edx);
  10.104 +        __clear_bit(X86_FEATURE_PSE36 & 31, edx);
  10.105  
  10.106          /* Filter all other features according to a whitelist. */
  10.107 -        ecx &= (bitmaskof(X86_FEATURE_LAHF_LM) |
  10.108 -                bitmaskof(X86_FEATURE_ALTMOVCR) |
  10.109 -                bitmaskof(X86_FEATURE_ABM) |
  10.110 -                bitmaskof(X86_FEATURE_SSE4A) |
  10.111 -                bitmaskof(X86_FEATURE_MISALIGNSSE) |
  10.112 -                bitmaskof(X86_FEATURE_3DNOWPF));
  10.113 -        edx &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
  10.114 -                bitmaskof(X86_FEATURE_NX) |
  10.115 -                bitmaskof(X86_FEATURE_LM) |
  10.116 -                bitmaskof(X86_FEATURE_SYSCALL) |
  10.117 -                bitmaskof(X86_FEATURE_MP) |
  10.118 -                bitmaskof(X86_FEATURE_MMXEXT) |
  10.119 -                bitmaskof(X86_FEATURE_FFXSR));
  10.120 +        *ecx &= (bitmaskof(X86_FEATURE_LAHF_LM) |
  10.121 +                 bitmaskof(X86_FEATURE_ALTMOVCR) |
  10.122 +                 bitmaskof(X86_FEATURE_ABM) |
  10.123 +                 bitmaskof(X86_FEATURE_SSE4A) |
  10.124 +                 bitmaskof(X86_FEATURE_MISALIGNSSE) |
  10.125 +                 bitmaskof(X86_FEATURE_3DNOWPF));
  10.126 +        *edx &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
  10.127 +                 bitmaskof(X86_FEATURE_NX) |
  10.128 +                 bitmaskof(X86_FEATURE_LM) |
  10.129 +                 bitmaskof(X86_FEATURE_SYSCALL) |
  10.130 +                 bitmaskof(X86_FEATURE_MP) |
  10.131 +                 bitmaskof(X86_FEATURE_MMXEXT) |
  10.132 +                 bitmaskof(X86_FEATURE_FFXSR));
  10.133          break;
  10.134  
  10.135      case 0x80000007:
  10.136      case 0x8000000A:
  10.137          /* Mask out features of power management and SVM extension. */
  10.138 -        eax = ebx = ecx = edx = 0;
  10.139 +        *eax = *ebx = *ecx = *edx = 0;
  10.140          break;
  10.141  
  10.142      case 0x80000008:
  10.143          /* Make sure Number of CPU core is 1 when HTT=0 */
  10.144 -        ecx &= 0xFFFFFF00;
  10.145 +        *ecx &= 0xFFFFFF00;
  10.146          break;
  10.147      }
  10.148  
  10.149 +    HVMTRACE_3D(CPUID, v, input,
  10.150 +                ((uint64_t)*eax << 32) | *ebx, ((uint64_t)*ecx << 32) | *edx);
  10.151 +}
  10.152 +
  10.153 +static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
  10.154 +{
  10.155 +    unsigned int eax, ebx, ecx, edx, inst_len;
  10.156 +
  10.157 +    eax = regs->eax;
  10.158 +    ebx = regs->ebx;
  10.159 +    ecx = regs->ecx;
  10.160 +    edx = regs->edx;
  10.161 +
  10.162 +    svm_cpuid_intercept(&eax, &ebx, &ecx, &edx);
  10.163 +
  10.164      regs->eax = eax;
  10.165      regs->ebx = ebx;
  10.166      regs->ecx = ecx;
  10.167      regs->edx = edx;
  10.168  
  10.169 -    HVMTRACE_3D(CPUID, v, input,
  10.170 -                ((uint64_t)eax << 32) | ebx, ((uint64_t)ecx << 32) | edx);
  10.171 -
  10.172 -    inst_len = __get_instruction_length(v, INSTR_CPUID, NULL);
  10.173 +    inst_len = __get_instruction_length(current, INSTR_CPUID, NULL);
  10.174      __update_guest_eip(regs, inst_len);
  10.175  }
  10.176  
  10.177 @@ -1484,11 +1509,11 @@ static int mov_to_cr(int gpreg, int cr, 
  10.178      switch ( cr )
  10.179      {
  10.180      case 0: 
  10.181 -        return hvm_set_cr0(value);
  10.182 +        return !hvm_set_cr0(value);
  10.183      case 3:
  10.184 -        return hvm_set_cr3(value);
  10.185 +        return !hvm_set_cr3(value);
  10.186      case 4:
  10.187 -        return hvm_set_cr4(value);
  10.188 +        return !hvm_set_cr4(value);
  10.189      default:
  10.190          gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
  10.191          domain_crash(v->domain);
  10.192 @@ -1564,7 +1589,7 @@ static void svm_cr_access(
  10.193          gpreg = decode_src_reg(prefix, buffer[index+2]);
  10.194          value = get_reg(gpreg, regs, vmcb) & 0xF;
  10.195          value = (v->arch.hvm_vcpu.guest_cr[0] & ~0xF) | value;
  10.196 -        result = hvm_set_cr0(value);
  10.197 +        result = !hvm_set_cr0(value);
  10.198          HVMTRACE_1D(LMSW, current, value);
  10.199          break;
  10.200  
  10.201 @@ -1635,176 +1660,197 @@ static void svm_cr_access(
  10.202          __update_guest_eip(regs, inst_len);
  10.203  }
  10.204  
  10.205 -static void svm_do_msr_access(
  10.206 -    struct vcpu *v, struct cpu_user_regs *regs)
  10.207 +static int svm_msr_read_intercept(struct cpu_user_regs *regs)
  10.208  {
  10.209 -    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  10.210 -    int  inst_len;
  10.211 -    u64 msr_content=0;
  10.212 +    u64 msr_content = 0;
  10.213      u32 ecx = regs->ecx, eax, edx;
  10.214 -
  10.215 -    HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%x, eax=%x, edx=%x, exitinfo = %lx",
  10.216 -                ecx, (u32)regs->eax, (u32)regs->edx,
  10.217 -                (unsigned long)vmcb->exitinfo1);
  10.218 -
  10.219 -    /* is it a read? */
  10.220 -    if (vmcb->exitinfo1 == 0)
  10.221 -    {
  10.222 -        switch (ecx) {
  10.223 -        case MSR_IA32_TSC:
  10.224 -            msr_content = hvm_get_guest_time(v);
  10.225 -            break;
  10.226 -
  10.227 -        case MSR_IA32_APICBASE:
  10.228 -            msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
  10.229 -            break;
  10.230 -
  10.231 -        case MSR_EFER:
  10.232 -            msr_content = v->arch.hvm_vcpu.guest_efer;
  10.233 -            break;
  10.234 -
  10.235 -        case MSR_IA32_MC4_MISC: /* Threshold register */
  10.236 -        case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:
  10.237 -            /*
  10.238 -             * MCA/MCE: We report that the threshold register is unavailable
  10.239 -             * for OS use (locked by the BIOS).
  10.240 -             */
  10.241 -            msr_content = 1ULL << 61; /* MC4_MISC.Locked */
  10.242 -            break;
  10.243 -
  10.244 -        case MSR_IA32_EBC_FREQUENCY_ID:
  10.245 -            /*
  10.246 -             * This Intel-only register may be accessed if this HVM guest
  10.247 -             * has been migrated from an Intel host. The value zero is not
  10.248 -             * particularly meaningful, but at least avoids the guest crashing!
  10.249 -             */
  10.250 -            msr_content = 0;
  10.251 -            break;
  10.252 +    struct vcpu *v = current;
  10.253 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  10.254  
  10.255 -        case MSR_K8_VM_HSAVE_PA:
  10.256 -            svm_inject_exception(TRAP_gp_fault, 0, 0);
  10.257 -            break;
  10.258 -
  10.259 -        case MSR_IA32_MCG_CAP:
  10.260 -        case MSR_IA32_MCG_STATUS:
  10.261 -        case MSR_IA32_MC0_STATUS:
  10.262 -        case MSR_IA32_MC1_STATUS:
  10.263 -        case MSR_IA32_MC2_STATUS:
  10.264 -        case MSR_IA32_MC3_STATUS:
  10.265 -        case MSR_IA32_MC4_STATUS:
  10.266 -        case MSR_IA32_MC5_STATUS:
  10.267 -            /* No point in letting the guest see real MCEs */
  10.268 -            msr_content = 0;
  10.269 -            break;
  10.270 -
  10.271 -        case MSR_IA32_DEBUGCTLMSR:
  10.272 -            msr_content = vmcb->debugctlmsr;
  10.273 -            break;
  10.274 -
  10.275 -        case MSR_IA32_LASTBRANCHFROMIP:
  10.276 -            msr_content = vmcb->lastbranchfromip;
  10.277 -            break;
  10.278 +    switch ( ecx )
  10.279 +    {
  10.280 +    case MSR_IA32_TSC:
  10.281 +        msr_content = hvm_get_guest_time(v);
  10.282 +        break;
  10.283  
  10.284 -        case MSR_IA32_LASTBRANCHTOIP:
  10.285 -            msr_content = vmcb->lastbranchtoip;
  10.286 -            break;
  10.287 -
  10.288 -        case MSR_IA32_LASTINTFROMIP:
  10.289 -            msr_content = vmcb->lastintfromip;
  10.290 -            break;
  10.291 -
  10.292 -        case MSR_IA32_LASTINTTOIP:
  10.293 -            msr_content = vmcb->lastinttoip;
  10.294 -            break;
  10.295 +    case MSR_IA32_APICBASE:
  10.296 +        msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
  10.297 +        break;
  10.298  
  10.299 -        default:
  10.300 -            if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
  10.301 -                 rdmsr_safe(ecx, eax, edx) == 0 )
  10.302 -            {
  10.303 -                regs->eax = eax;
  10.304 -                regs->edx = edx;
  10.305 -                goto done;
  10.306 -            }
  10.307 -            svm_inject_exception(TRAP_gp_fault, 0, 0);
  10.308 -            return;
  10.309 +    case MSR_EFER:
  10.310 +        msr_content = v->arch.hvm_vcpu.guest_efer;
  10.311 +        break;
  10.312 +
  10.313 +    case MSR_IA32_MC4_MISC: /* Threshold register */
  10.314 +    case MSR_F10_MC4_MISC1 ... MSR_F10_MC4_MISC3:
  10.315 +        /*
  10.316 +         * MCA/MCE: We report that the threshold register is unavailable
  10.317 +         * for OS use (locked by the BIOS).
  10.318 +         */
  10.319 +        msr_content = 1ULL << 61; /* MC4_MISC.Locked */
  10.320 +        break;
  10.321 +
  10.322 +    case MSR_IA32_EBC_FREQUENCY_ID:
  10.323 +        /*
  10.324 +         * This Intel-only register may be accessed if this HVM guest
  10.325 +         * has been migrated from an Intel host. The value zero is not
  10.326 +         * particularly meaningful, but at least avoids the guest crashing!
  10.327 +         */
  10.328 +        msr_content = 0;
  10.329 +        break;
  10.330 +
  10.331 +    case MSR_K8_VM_HSAVE_PA:
  10.332 +        goto gpf;
  10.333 +
  10.334 +    case MSR_IA32_MCG_CAP:
  10.335 +    case MSR_IA32_MCG_STATUS:
  10.336 +    case MSR_IA32_MC0_STATUS:
  10.337 +    case MSR_IA32_MC1_STATUS:
  10.338 +    case MSR_IA32_MC2_STATUS:
  10.339 +    case MSR_IA32_MC3_STATUS:
  10.340 +    case MSR_IA32_MC4_STATUS:
  10.341 +    case MSR_IA32_MC5_STATUS:
  10.342 +        /* No point in letting the guest see real MCEs */
  10.343 +        msr_content = 0;
  10.344 +        break;
  10.345 +
  10.346 +    case MSR_IA32_DEBUGCTLMSR:
  10.347 +        msr_content = vmcb->debugctlmsr;
  10.348 +        break;
  10.349 +
  10.350 +    case MSR_IA32_LASTBRANCHFROMIP:
  10.351 +        msr_content = vmcb->lastbranchfromip;
  10.352 +        break;
  10.353 +
  10.354 +    case MSR_IA32_LASTBRANCHTOIP:
  10.355 +        msr_content = vmcb->lastbranchtoip;
  10.356 +        break;
  10.357 +
  10.358 +    case MSR_IA32_LASTINTFROMIP:
  10.359 +        msr_content = vmcb->lastintfromip;
  10.360 +        break;
  10.361 +
  10.362 +    case MSR_IA32_LASTINTTOIP:
  10.363 +        msr_content = vmcb->lastinttoip;
  10.364 +        break;
  10.365 +
  10.366 +    default:
  10.367 +        if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
  10.368 +             rdmsr_safe(ecx, eax, edx) == 0 )
  10.369 +        {
  10.370 +            regs->eax = eax;
  10.371 +            regs->edx = edx;
  10.372 +            goto done;
  10.373          }
  10.374 -        regs->eax = msr_content & 0xFFFFFFFF;
  10.375 -        regs->edx = msr_content >> 32;
  10.376 +        goto gpf;
  10.377 +    }
  10.378 +    regs->eax = msr_content & 0xFFFFFFFF;
  10.379 +    regs->edx = msr_content >> 32;
  10.380  
  10.381   done:
  10.382 -        hvmtrace_msr_read(v, ecx, msr_content);
  10.383 -        HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
  10.384 -                    ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
  10.385 +    hvmtrace_msr_read(v, ecx, msr_content);
  10.386 +    HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
  10.387 +                ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
  10.388 +    return X86EMUL_OKAY;
  10.389  
  10.390 + gpf:
  10.391 +    svm_inject_exception(TRAP_gp_fault, 0, 0);
  10.392 +    return X86EMUL_EXCEPTION;
  10.393 +}
  10.394 +
  10.395 +static int svm_msr_write_intercept(struct cpu_user_regs *regs)
  10.396 +{
  10.397 +    u64 msr_content = 0;
  10.398 +    u32 ecx = regs->ecx;
  10.399 +    struct vcpu *v = current;
  10.400 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  10.401 +
  10.402 +    msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
  10.403 +
  10.404 +    hvmtrace_msr_write(v, ecx, msr_content);
  10.405 +
  10.406 +    switch ( ecx )
  10.407 +    {
  10.408 +    case MSR_IA32_TSC:
  10.409 +        hvm_set_guest_time(v, msr_content);
  10.410 +        pt_reset(v);
  10.411 +        break;
  10.412 +
  10.413 +    case MSR_IA32_APICBASE:
  10.414 +        vlapic_msr_set(vcpu_vlapic(v), msr_content);
  10.415 +        break;
  10.416 +
  10.417 +    case MSR_K8_VM_HSAVE_PA:
  10.418 +        goto gpf;
  10.419 +
  10.420 +    case MSR_IA32_DEBUGCTLMSR:
  10.421 +        vmcb->debugctlmsr = msr_content;
  10.422 +        if ( !msr_content || !cpu_has_svm_lbrv )
  10.423 +            break;
  10.424 +        vmcb->lbr_control.fields.enable = 1;
  10.425 +        svm_disable_intercept_for_msr(v, MSR_IA32_DEBUGCTLMSR);
  10.426 +        svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHFROMIP);
  10.427 +        svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHTOIP);
  10.428 +        svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTFROMIP);
  10.429 +        svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTTOIP);
  10.430 +        break;
  10.431 +
  10.432 +    case MSR_IA32_LASTBRANCHFROMIP:
  10.433 +        vmcb->lastbranchfromip = msr_content;
  10.434 +        break;
  10.435 +
  10.436 +    case MSR_IA32_LASTBRANCHTOIP:
  10.437 +        vmcb->lastbranchtoip = msr_content;
  10.438 +        break;
  10.439 +
  10.440 +    case MSR_IA32_LASTINTFROMIP:
  10.441 +        vmcb->lastintfromip = msr_content;
  10.442 +        break;
  10.443 +
  10.444 +    case MSR_IA32_LASTINTTOIP:
  10.445 +        vmcb->lastinttoip = msr_content;
  10.446 +        break;
  10.447 +
  10.448 +    default:
  10.449 +        switch ( long_mode_do_msr_write(regs) )
  10.450 +        {
  10.451 +        case HNDL_unhandled:
  10.452 +            wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
  10.453 +            break;
  10.454 +        case HNDL_exception_raised:
  10.455 +            return X86EMUL_EXCEPTION;
  10.456 +        case HNDL_done:
  10.457 +            break;
  10.458 +        }
  10.459 +        break;
  10.460 +    }
  10.461 +
  10.462 +    return X86EMUL_OKAY;
  10.463 +
  10.464 + gpf:
  10.465 +    svm_inject_exception(TRAP_gp_fault, 0, 0);
  10.466 +    return X86EMUL_EXCEPTION;
  10.467 +}
  10.468 +
  10.469 +static void svm_do_msr_access(struct cpu_user_regs *regs)
  10.470 +{
  10.471 +    int rc, inst_len;
  10.472 +    struct vcpu *v = current;
  10.473 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  10.474 +
  10.475 +    if ( vmcb->exitinfo1 == 0 )
  10.476 +    {
  10.477 +        rc = svm_msr_read_intercept(regs);
  10.478          inst_len = __get_instruction_length(v, INSTR_RDMSR, NULL);
  10.479      }
  10.480      else
  10.481      {
  10.482 -        msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
  10.483 -
  10.484 -        hvmtrace_msr_write(v, ecx, msr_content);
  10.485 -
  10.486 -        switch (ecx)
  10.487 -        {
  10.488 -        case MSR_IA32_TSC:
  10.489 -            hvm_set_guest_time(v, msr_content);
  10.490 -            pt_reset(v);
  10.491 -            break;
  10.492 -
  10.493 -        case MSR_IA32_APICBASE:
  10.494 -            vlapic_msr_set(vcpu_vlapic(v), msr_content);
  10.495 -            break;
  10.496 -
  10.497 -        case MSR_K8_VM_HSAVE_PA:
  10.498 -            svm_inject_exception(TRAP_gp_fault, 0, 0);
  10.499 -            break;
  10.500 -
  10.501 -        case MSR_IA32_DEBUGCTLMSR:
  10.502 -            vmcb->debugctlmsr = msr_content;
  10.503 -            if ( !msr_content || !cpu_has_svm_lbrv )
  10.504 -                break;
  10.505 -            vmcb->lbr_control.fields.enable = 1;
  10.506 -            svm_disable_intercept_for_msr(v, MSR_IA32_DEBUGCTLMSR);
  10.507 -            svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHFROMIP);
  10.508 -            svm_disable_intercept_for_msr(v, MSR_IA32_LASTBRANCHTOIP);
  10.509 -            svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTFROMIP);
  10.510 -            svm_disable_intercept_for_msr(v, MSR_IA32_LASTINTTOIP);
  10.511 -            break;
  10.512 -
  10.513 -        case MSR_IA32_LASTBRANCHFROMIP:
  10.514 -            vmcb->lastbranchfromip = msr_content;
  10.515 -            break;
  10.516 -
  10.517 -        case MSR_IA32_LASTBRANCHTOIP:
  10.518 -            vmcb->lastbranchtoip = msr_content;
  10.519 -            break;
  10.520 -
  10.521 -        case MSR_IA32_LASTINTFROMIP:
  10.522 -            vmcb->lastintfromip = msr_content;
  10.523 -            break;
  10.524 -
  10.525 -        case MSR_IA32_LASTINTTOIP:
  10.526 -            vmcb->lastinttoip = msr_content;
  10.527 -            break;
  10.528 -
  10.529 -        default:
  10.530 -            switch ( long_mode_do_msr_write(regs) )
  10.531 -            {
  10.532 -            case HNDL_unhandled:
  10.533 -                wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
  10.534 -                break;
  10.535 -            case HNDL_exception_raised:
  10.536 -                return;
  10.537 -            case HNDL_done:
  10.538 -                break;
  10.539 -            }
  10.540 -            break;
  10.541 -        }
  10.542 -
  10.543 +        rc = svm_msr_write_intercept(regs);
  10.544          inst_len = __get_instruction_length(v, INSTR_WRMSR, NULL);
  10.545      }
  10.546  
  10.547 -    __update_guest_eip(regs, inst_len);
  10.548 +    if ( rc == X86EMUL_OKAY )
  10.549 +        __update_guest_eip(regs, inst_len);
  10.550  }
  10.551  
  10.552  static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb,
  10.553 @@ -1830,21 +1876,26 @@ static void svm_vmexit_do_hlt(struct vmc
  10.554      hvm_hlt(regs->eflags);
  10.555  }
  10.556  
  10.557 +static void wbinvd_ipi(void *info)
  10.558 +{
  10.559 +    wbinvd();
  10.560 +}
  10.561 +
  10.562 +static void svm_wbinvd_intercept(void)
  10.563 +{
  10.564 +    if ( !list_empty(&(domain_hvm_iommu(current->domain)->pdev_list)) )
  10.565 +        on_each_cpu(wbinvd_ipi, NULL, 1, 1);
  10.566 +}
  10.567 +
  10.568  static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)
  10.569  {
  10.570      enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };
  10.571 -    struct vcpu *curr = current;
  10.572 -    struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
  10.573      int inst_len;
  10.574  
  10.575 -    if ( !list_empty(&(domain_hvm_iommu(curr->domain)->pdev_list)) )
  10.576 -    {
  10.577 -        vmcb->general2_intercepts &= ~GENERAL2_INTERCEPT_WBINVD;
  10.578 -        wbinvd();
  10.579 -    }
  10.580 +    svm_wbinvd_intercept();
  10.581  
  10.582      inst_len = __get_instruction_length_from_list(
  10.583 -        curr, list, ARRAY_SIZE(list), NULL, NULL);
  10.584 +        current, list, ARRAY_SIZE(list), NULL, NULL);
  10.585      __update_guest_eip(regs, inst_len);
  10.586  }
  10.587  
  10.588 @@ -1982,7 +2033,7 @@ asmlinkage void svm_vmexit_handler(struc
  10.589          break;
  10.590  
  10.591      case VMEXIT_EXCEPTION_NM:
  10.592 -        svm_do_no_device_fault(vmcb);
  10.593 +        svm_fpu_dirty_intercept();
  10.594          break;  
  10.595  
  10.596      case VMEXIT_EXCEPTION_PF: {
  10.597 @@ -2036,7 +2087,7 @@ asmlinkage void svm_vmexit_handler(struc
  10.598      }
  10.599  
  10.600      case VMEXIT_CPUID:
  10.601 -        svm_vmexit_do_cpuid(vmcb, regs);
  10.602 +        svm_vmexit_do_cpuid(regs);
  10.603          break;
  10.604  
  10.605      case VMEXIT_HLT:
  10.606 @@ -2083,7 +2134,7 @@ asmlinkage void svm_vmexit_handler(struc
  10.607          break;
  10.608  
  10.609      case VMEXIT_MSR:
  10.610 -        svm_do_msr_access(v, regs);
  10.611 +        svm_do_msr_access(regs);
  10.612          break;
  10.613  
  10.614      case VMEXIT_SHUTDOWN:
    11.1 --- a/xen/arch/x86/hvm/vmx/realmode.c	Tue Feb 19 11:14:40 2008 -0700
    11.2 +++ b/xen/arch/x86/hvm/vmx/realmode.c	Wed Feb 20 14:36:45 2008 +0000
    11.3 @@ -3,7 +3,7 @@
    11.4   * 
    11.5   * Real-mode emulation for VMX.
    11.6   * 
    11.7 - * Copyright (c) 2007 Citrix Systems, Inc.
    11.8 + * Copyright (c) 2007-2008 Citrix Systems, Inc.
    11.9   * 
   11.10   * Authors:
   11.11   *    Keir Fraser <keir.fraser@citrix.com>
   11.12 @@ -15,33 +15,14 @@
   11.13  #include <xen/sched.h>
   11.14  #include <xen/paging.h>
   11.15  #include <asm/event.h>
   11.16 +#include <asm/hvm/emulate.h>
   11.17  #include <asm/hvm/hvm.h>
   11.18  #include <asm/hvm/support.h>
   11.19  #include <asm/hvm/vmx/vmx.h>
   11.20  #include <asm/hvm/vmx/vmcs.h>
   11.21 -#include <asm/x86_emulate.h>
   11.22  
   11.23  struct realmode_emulate_ctxt {
   11.24 -    struct x86_emulate_ctxt ctxt;
   11.25 -
   11.26 -    /* Cache of 16 bytes of instruction. */
   11.27 -    uint8_t insn_buf[16];
   11.28 -    unsigned long insn_buf_eip;
   11.29 -
   11.30 -    struct segment_register seg_reg[10];
   11.31 -
   11.32 -    union {
   11.33 -        struct {
   11.34 -            unsigned int hlt:1;
   11.35 -            unsigned int mov_ss:1;
   11.36 -            unsigned int sti:1;
   11.37 -        } flags;
   11.38 -        unsigned int flag_word;
   11.39 -    };
   11.40 -
   11.41 -    uint8_t exn_vector;
   11.42 -    uint8_t exn_insn_len;
   11.43 -
   11.44 +    struct hvm_emulate_ctxt hvm;
   11.45      uint32_t intr_shadow;
   11.46  };
   11.47  
   11.48 @@ -50,13 +31,16 @@ static void realmode_deliver_exception(
   11.49      unsigned int insn_len,
   11.50      struct realmode_emulate_ctxt *rm_ctxt)
   11.51  {
   11.52 -    struct segment_register *idtr = &rm_ctxt->seg_reg[x86_seg_idtr];
   11.53 -    struct segment_register *csr = &rm_ctxt->seg_reg[x86_seg_cs];
   11.54 -    struct cpu_user_regs *regs = rm_ctxt->ctxt.regs;
   11.55 +    struct segment_register *idtr, *csr;
   11.56 +    struct cpu_user_regs *regs = rm_ctxt->hvm.ctxt.regs;
   11.57      uint32_t cs_eip, pstk;
   11.58      uint16_t frame[3];
   11.59      unsigned int last_byte;
   11.60  
   11.61 +    idtr = hvmemul_get_seg_reg(x86_seg_idtr, &rm_ctxt->hvm);
   11.62 +    csr  = hvmemul_get_seg_reg(x86_seg_cs,   &rm_ctxt->hvm);
   11.63 +    __set_bit(x86_seg_cs, &rm_ctxt->hvm.seg_reg_dirty);
   11.64 +
   11.65   again:
   11.66      last_byte = (vector * 4) + 3;
   11.67      if ( idtr->limit < last_byte )
   11.68 @@ -90,7 +74,7 @@ static void realmode_deliver_exception(
   11.69      frame[1] = csr->sel;
   11.70      frame[2] = regs->eflags & ~X86_EFLAGS_RF;
   11.71  
   11.72 -    if ( rm_ctxt->ctxt.addr_size == 32 )
   11.73 +    if ( rm_ctxt->hvm.ctxt.addr_size == 32 )
   11.74      {
   11.75          regs->esp -= 6;
   11.76          pstk = regs->esp;
   11.77 @@ -102,7 +86,7 @@ static void realmode_deliver_exception(
   11.78          regs->esp |= pstk;
   11.79      }
   11.80  
   11.81 -    pstk += rm_ctxt->seg_reg[x86_seg_ss].base;
   11.82 +    pstk += hvmemul_get_seg_reg(x86_seg_ss, &rm_ctxt->hvm)->base;
   11.83      (void)hvm_copy_to_guest_phys(pstk, frame, sizeof(frame));
   11.84  
   11.85      csr->sel  = cs_eip >> 16;
   11.86 @@ -118,597 +102,34 @@ static void realmode_deliver_exception(
   11.87      }
   11.88  }
   11.89  
   11.90 -static uint32_t virtual_to_linear(
   11.91 -    enum x86_segment seg,
   11.92 -    uint32_t offset,
   11.93 -    struct realmode_emulate_ctxt *rm_ctxt)
   11.94 -{
   11.95 -    uint32_t addr = offset;
   11.96 -    if ( seg == x86_seg_none )
   11.97 -        return addr;
   11.98 -    ASSERT(is_x86_user_segment(seg));
   11.99 -    return addr + rm_ctxt->seg_reg[seg].base;
  11.100 -}
  11.101 -
  11.102 -static int
  11.103 -realmode_read(
  11.104 -    enum x86_segment seg,
  11.105 -    unsigned long offset,
  11.106 -    unsigned long *val,
  11.107 -    unsigned int bytes,
  11.108 -    enum hvm_access_type access_type,
  11.109 -    struct realmode_emulate_ctxt *rm_ctxt)
  11.110 -{
  11.111 -    uint32_t addr = virtual_to_linear(seg, offset, rm_ctxt);
  11.112 -
  11.113 -    *val = 0;
  11.114 -
  11.115 -    if ( hvm_copy_from_guest_virt_nofault(val, addr, bytes) )
  11.116 -    {
  11.117 -        struct vcpu *curr = current;
  11.118 -
  11.119 -        if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.120 -            return X86EMUL_UNHANDLEABLE;
  11.121 -
  11.122 -        if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.123 -            return X86EMUL_UNHANDLEABLE;
  11.124 -
  11.125 -        if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.126 -        {
  11.127 -            curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.128 -            send_mmio_req(IOREQ_TYPE_COPY, addr, 1, bytes,
  11.129 -                          0, IOREQ_READ, 0, 0);
  11.130 -        }
  11.131 -
  11.132 -        if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.133 -            return X86EMUL_RETRY;
  11.134 -
  11.135 -        *val = curr->arch.hvm_vmx.real_mode_io_data;
  11.136 -        curr->arch.hvm_vmx.real_mode_io_completed = 0;
  11.137 -    }
  11.138 -
  11.139 -    return X86EMUL_OKAY;
  11.140 -}
  11.141 -
  11.142 -static int
  11.143 -realmode_emulate_read(
  11.144 -    enum x86_segment seg,
  11.145 -    unsigned long offset,
  11.146 -    unsigned long *val,
  11.147 -    unsigned int bytes,
  11.148 -    struct x86_emulate_ctxt *ctxt)
  11.149 +static void realmode_emulate_one(struct realmode_emulate_ctxt *rm_ctxt)
  11.150  {
  11.151 -    return realmode_read(
  11.152 -        seg, offset, val, bytes, hvm_access_read,
  11.153 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt));
  11.154 -}
  11.155 -
  11.156 -static int
  11.157 -realmode_emulate_insn_fetch(
  11.158 -    enum x86_segment seg,
  11.159 -    unsigned long offset,
  11.160 -    unsigned long *val,
  11.161 -    unsigned int bytes,
  11.162 -    struct x86_emulate_ctxt *ctxt)
  11.163 -{
  11.164 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.165 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.166 -    unsigned int insn_off = offset - rm_ctxt->insn_buf_eip;
  11.167 -
  11.168 -    /* Fall back if requested bytes are not in the prefetch cache. */
  11.169 -    if ( unlikely((insn_off + bytes) > sizeof(rm_ctxt->insn_buf)) )
  11.170 -        return realmode_read(
  11.171 -            seg, offset, val, bytes,
  11.172 -            hvm_access_insn_fetch, rm_ctxt);
  11.173 -
  11.174 -    /* Hit the cache. Simple memcpy. */
  11.175 -    *val = 0;
  11.176 -    memcpy(val, &rm_ctxt->insn_buf[insn_off], bytes);
  11.177 -    return X86EMUL_OKAY;
  11.178 -}
  11.179 -
  11.180 -static int
  11.181 -realmode_emulate_write(
  11.182 -    enum x86_segment seg,
  11.183 -    unsigned long offset,
  11.184 -    unsigned long val,
  11.185 -    unsigned int bytes,
  11.186 -    struct x86_emulate_ctxt *ctxt)
  11.187 -{
  11.188 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.189 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.190 -    uint32_t addr = virtual_to_linear(seg, offset, rm_ctxt);
  11.191 -
  11.192 -    if ( hvm_copy_to_guest_virt_nofault(addr, &val, bytes) )
  11.193 -    {
  11.194 -        struct vcpu *curr = current;
  11.195 -
  11.196 -        if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.197 -            return X86EMUL_UNHANDLEABLE;
  11.198 -
  11.199 -        if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.200 -            return X86EMUL_UNHANDLEABLE;
  11.201 -
  11.202 -        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.203 -        send_mmio_req(IOREQ_TYPE_COPY, addr, 1, bytes,
  11.204 -                      val, IOREQ_WRITE, 0, 0);
  11.205 -    }
  11.206 -
  11.207 -    return X86EMUL_OKAY;
  11.208 -}
  11.209 -
  11.210 -static int 
  11.211 -realmode_emulate_cmpxchg(
  11.212 -    enum x86_segment seg,
  11.213 -    unsigned long offset,
  11.214 -    unsigned long old,
  11.215 -    unsigned long new,
  11.216 -    unsigned int bytes,
  11.217 -    struct x86_emulate_ctxt *ctxt)
  11.218 -{
  11.219 -    /* Fix this in case the guest is really relying on r-m-w atomicity. */
  11.220 -    return realmode_emulate_write(seg, offset, new, bytes, ctxt);
  11.221 -}
  11.222 +    struct cpu_user_regs *regs = rm_ctxt->hvm.ctxt.regs;
  11.223 +    struct vcpu *curr = current;
  11.224 +    unsigned long seg_reg_dirty;
  11.225 +    uint32_t new_intr_shadow, intr_info;
  11.226 +    int rc;
  11.227  
  11.228 -static int 
  11.229 -realmode_rep_ins(
  11.230 -    uint16_t src_port,
  11.231 -    enum x86_segment dst_seg,
  11.232 -    unsigned long dst_offset,
  11.233 -    unsigned int bytes_per_rep,
  11.234 -    unsigned long *reps,
  11.235 -    struct x86_emulate_ctxt *ctxt)
  11.236 -{
  11.237 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.238 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.239 -    struct vcpu *curr = current;
  11.240 -    uint32_t paddr = virtual_to_linear(dst_seg, dst_offset, rm_ctxt);
  11.241 -
  11.242 -    if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.243 -        return X86EMUL_UNHANDLEABLE;
  11.244 -
  11.245 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.246 -        return X86EMUL_UNHANDLEABLE;
  11.247 -
  11.248 -    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.249 -    {
  11.250 -        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.251 -        send_pio_req(src_port, *reps, bytes_per_rep,
  11.252 -                     paddr, IOREQ_READ,
  11.253 -                     !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
  11.254 -    }
  11.255 -
  11.256 -    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.257 -        return X86EMUL_RETRY;
  11.258 -
  11.259 -    curr->arch.hvm_vmx.real_mode_io_completed = 0;
  11.260 -
  11.261 -    return X86EMUL_OKAY;
  11.262 -}
  11.263 -
  11.264 -static int 
  11.265 -realmode_rep_outs(
  11.266 -    enum x86_segment src_seg,
  11.267 -    unsigned long src_offset,
  11.268 -    uint16_t dst_port,
  11.269 -    unsigned int bytes_per_rep,
  11.270 -    unsigned long *reps,
  11.271 -    struct x86_emulate_ctxt *ctxt)
  11.272 -{
  11.273 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.274 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.275 -    struct vcpu *curr = current;
  11.276 -    uint32_t paddr = virtual_to_linear(src_seg, src_offset, rm_ctxt);
  11.277 -
  11.278 -    if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.279 -        return X86EMUL_UNHANDLEABLE;
  11.280 -
  11.281 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.282 -        return X86EMUL_UNHANDLEABLE;
  11.283 -
  11.284 -    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.285 -    send_pio_req(dst_port, *reps, bytes_per_rep,
  11.286 -                 paddr, IOREQ_WRITE,
  11.287 -                 !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
  11.288 -
  11.289 -    return X86EMUL_OKAY;
  11.290 -}
  11.291 +    seg_reg_dirty = rm_ctxt->hvm.seg_reg_dirty;
  11.292 +    rm_ctxt->hvm.seg_reg_dirty = 0;
  11.293  
  11.294 -static int 
  11.295 -realmode_rep_movs(
  11.296 -   enum x86_segment src_seg,
  11.297 -   unsigned long src_offset,
  11.298 -   enum x86_segment dst_seg,
  11.299 -   unsigned long dst_offset,
  11.300 -   unsigned int bytes_per_rep,
  11.301 -   unsigned long *reps,
  11.302 -   struct x86_emulate_ctxt *ctxt)
  11.303 -{
  11.304 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.305 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.306 -    struct vcpu *curr = current;
  11.307 -    uint32_t saddr = virtual_to_linear(src_seg, src_offset, rm_ctxt);
  11.308 -    uint32_t daddr = virtual_to_linear(dst_seg, dst_offset, rm_ctxt);
  11.309 -    p2m_type_t p2mt;
  11.310 +    rc = hvm_emulate_one(&rm_ctxt->hvm);
  11.311  
  11.312 -    if ( (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ||
  11.313 -         curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.314 -        return X86EMUL_UNHANDLEABLE;
  11.315 -
  11.316 -    mfn_x(gfn_to_mfn_current(saddr >> PAGE_SHIFT, &p2mt));
  11.317 -    if ( !p2m_is_ram(p2mt) )
  11.318 -    {
  11.319 -        if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.320 -        {
  11.321 -            curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.322 -            send_mmio_req(IOREQ_TYPE_COPY, saddr, *reps, bytes_per_rep,
  11.323 -                      daddr, IOREQ_READ,
  11.324 -                      !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
  11.325 -        }
  11.326 -
  11.327 -        if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.328 -            return X86EMUL_RETRY;
  11.329 -
  11.330 -        curr->arch.hvm_vmx.real_mode_io_completed = 0;
  11.331 -    }
  11.332 -    else
  11.333 +    if ( test_bit(x86_seg_cs, &rm_ctxt->hvm.seg_reg_dirty) )
  11.334      {
  11.335 -        mfn_x(gfn_to_mfn_current(daddr >> PAGE_SHIFT, &p2mt));
  11.336 -        if ( p2m_is_ram(p2mt) )
  11.337 -            return X86EMUL_UNHANDLEABLE;
  11.338 -        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.339 -        send_mmio_req(IOREQ_TYPE_COPY, daddr, *reps, bytes_per_rep,
  11.340 -                      saddr, IOREQ_WRITE,
  11.341 -                      !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
  11.342 -    }
  11.343 -
  11.344 -    return X86EMUL_OKAY;
  11.345 -}
  11.346 -
  11.347 -static int
  11.348 -realmode_read_segment(
  11.349 -    enum x86_segment seg,
  11.350 -    struct segment_register *reg,
  11.351 -    struct x86_emulate_ctxt *ctxt)
  11.352 -{
  11.353 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.354 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.355 -    memcpy(reg, &rm_ctxt->seg_reg[seg], sizeof(struct segment_register));
  11.356 -    return X86EMUL_OKAY;
  11.357 -}
  11.358 -
  11.359 -static int
  11.360 -realmode_write_segment(
  11.361 -    enum x86_segment seg,
  11.362 -    struct segment_register *reg,
  11.363 -    struct x86_emulate_ctxt *ctxt)
  11.364 -{
  11.365 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.366 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.367 -    struct vcpu *curr = current;
  11.368 -
  11.369 -    if ( seg == x86_seg_cs )
  11.370 -    {
  11.371 -        if ( reg->attr.fields.dpl != 0 )
  11.372 -            return X86EMUL_UNHANDLEABLE;
  11.373          curr->arch.hvm_vmx.vmxemul &= ~VMXEMUL_BAD_CS;
  11.374 -        if ( reg->sel & 3 )
  11.375 +        if ( hvmemul_get_seg_reg(x86_seg_cs, &rm_ctxt->hvm)->sel & 3 )
  11.376              curr->arch.hvm_vmx.vmxemul |= VMXEMUL_BAD_CS;
  11.377      }
  11.378  
  11.379 -    if ( seg == x86_seg_ss )
  11.380 -    {
  11.381 -        if ( reg->attr.fields.dpl != 0 )
  11.382 -            return X86EMUL_UNHANDLEABLE;
  11.383 -        curr->arch.hvm_vmx.vmxemul &= ~VMXEMUL_BAD_SS;
  11.384 -        if ( reg->sel & 3 )
  11.385 -            curr->arch.hvm_vmx.vmxemul |= VMXEMUL_BAD_SS;
  11.386 -        rm_ctxt->flags.mov_ss = 1;
  11.387 -    }
  11.388 -
  11.389 -    memcpy(&rm_ctxt->seg_reg[seg], reg, sizeof(struct segment_register));
  11.390 -
  11.391 -    return X86EMUL_OKAY;
  11.392 -}
  11.393 -
  11.394 -static int
  11.395 -realmode_read_io(
  11.396 -    unsigned int port,
  11.397 -    unsigned int bytes,
  11.398 -    unsigned long *val,
  11.399 -    struct x86_emulate_ctxt *ctxt)
  11.400 -{
  11.401 -    struct vcpu *curr = current;
  11.402 -
  11.403 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.404 -        return X86EMUL_UNHANDLEABLE;
  11.405 -
  11.406 -    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.407 -    {
  11.408 -        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.409 -        send_pio_req(port, 1, bytes, 0, IOREQ_READ, 0, 0);
  11.410 -    }
  11.411 -
  11.412 -    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
  11.413 -        return X86EMUL_RETRY;
  11.414 -
  11.415 -    *val = curr->arch.hvm_vmx.real_mode_io_data;
  11.416 -    curr->arch.hvm_vmx.real_mode_io_completed = 0;
  11.417 -
  11.418 -    return X86EMUL_OKAY;
  11.419 -}
  11.420 -
  11.421 -static int realmode_write_io(
  11.422 -    unsigned int port,
  11.423 -    unsigned int bytes,
  11.424 -    unsigned long val,
  11.425 -    struct x86_emulate_ctxt *ctxt)
  11.426 -{
  11.427 -    struct vcpu *curr = current;
  11.428 -
  11.429 -    if ( port == 0xe9 )
  11.430 +    if ( test_bit(x86_seg_ss, &rm_ctxt->hvm.seg_reg_dirty) )
  11.431      {
  11.432 -        hvm_print_line(curr, val);
  11.433 -        return X86EMUL_OKAY;
  11.434 -    }
  11.435 -
  11.436 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.437 -        return X86EMUL_UNHANDLEABLE;
  11.438 -
  11.439 -    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
  11.440 -    send_pio_req(port, 1, bytes, val, IOREQ_WRITE, 0, 0);
  11.441 -
  11.442 -    return X86EMUL_OKAY;
  11.443 -}
  11.444 -
  11.445 -static int
  11.446 -realmode_read_cr(
  11.447 -    unsigned int reg,
  11.448 -    unsigned long *val,
  11.449 -    struct x86_emulate_ctxt *ctxt)
  11.450 -{
  11.451 -    switch ( reg )
  11.452 -    {
  11.453 -    case 0:
  11.454 -    case 2:
  11.455 -    case 3:
  11.456 -    case 4:
  11.457 -        *val = current->arch.hvm_vcpu.guest_cr[reg];
  11.458 -        break;
  11.459 -    default:
  11.460 -        return X86EMUL_UNHANDLEABLE;
  11.461 -    }
  11.462 -
  11.463 -    return X86EMUL_OKAY;
  11.464 -}
  11.465 -
  11.466 -static int
  11.467 -realmode_write_cr(
  11.468 -    unsigned int reg,
  11.469 -    unsigned long val,
  11.470 -    struct x86_emulate_ctxt *ctxt)
  11.471 -{
  11.472 -    switch ( reg )
  11.473 -    {
  11.474 -    case 0:
  11.475 -        if ( !hvm_set_cr0(val) )
  11.476 -            return X86EMUL_UNHANDLEABLE;
  11.477 -        break;
  11.478 -    case 2:
  11.479 -        current->arch.hvm_vcpu.guest_cr[2] = val;
  11.480 -        break;
  11.481 -    case 3:
  11.482 -        if ( !hvm_set_cr3(val) )
  11.483 -            return X86EMUL_UNHANDLEABLE;
  11.484 -        break;
  11.485 -    case 4:
  11.486 -        if ( !hvm_set_cr4(val) )
  11.487 -            return X86EMUL_UNHANDLEABLE;
  11.488 -        break;
  11.489 -    default:
  11.490 -        return X86EMUL_UNHANDLEABLE;
  11.491 -    }
  11.492 -
  11.493 -    return X86EMUL_OKAY;
  11.494 -}
  11.495 -
  11.496 -static int
  11.497 -realmode_read_msr(
  11.498 -    unsigned long reg,
  11.499 -    uint64_t *val,
  11.500 -    struct x86_emulate_ctxt *ctxt)
  11.501 -{
  11.502 -    struct cpu_user_regs _regs;
  11.503 -
  11.504 -    _regs.ecx = (uint32_t)reg;
  11.505 -
  11.506 -    if ( !vmx_msr_read_intercept(&_regs) )
  11.507 -    {
  11.508 -        struct realmode_emulate_ctxt *rm_ctxt =
  11.509 -            container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.510 -        rm_ctxt->exn_vector = (uint8_t)__vmread(VM_ENTRY_INTR_INFO);
  11.511 -        rm_ctxt->exn_insn_len = 0;
  11.512 -        __vmwrite(VM_ENTRY_INTR_INFO, 0);
  11.513 -        return X86EMUL_EXCEPTION;
  11.514 +        curr->arch.hvm_vmx.vmxemul &= ~VMXEMUL_BAD_SS;
  11.515 +        if ( hvmemul_get_seg_reg(x86_seg_ss, &rm_ctxt->hvm)->sel & 3 )
  11.516 +            curr->arch.hvm_vmx.vmxemul |= VMXEMUL_BAD_SS;
  11.517      }
  11.518  
  11.519 -    *val = ((uint64_t)(uint32_t)_regs.edx << 32) || (uint32_t)_regs.eax;
  11.520 -    return X86EMUL_OKAY;
  11.521 -}
  11.522 -
  11.523 -static int
  11.524 -realmode_write_msr(
  11.525 -    unsigned long reg,
  11.526 -    uint64_t val,
  11.527 -    struct x86_emulate_ctxt *ctxt)
  11.528 -{
  11.529 -    struct cpu_user_regs _regs;
  11.530 -
  11.531 -    _regs.edx = (uint32_t)(val >> 32);
  11.532 -    _regs.eax = (uint32_t)val;
  11.533 -    _regs.ecx = (uint32_t)reg;
  11.534 -
  11.535 -    if ( !vmx_msr_write_intercept(&_regs) )
  11.536 -    {
  11.537 -        struct realmode_emulate_ctxt *rm_ctxt =
  11.538 -            container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.539 -        rm_ctxt->exn_vector = (uint8_t)__vmread(VM_ENTRY_INTR_INFO);
  11.540 -        rm_ctxt->exn_insn_len = 0;
  11.541 -        __vmwrite(VM_ENTRY_INTR_INFO, 0);
  11.542 -        return X86EMUL_EXCEPTION;
  11.543 -    }
  11.544 -
  11.545 -    return X86EMUL_OKAY;
  11.546 -}
  11.547 -
  11.548 -static int realmode_write_rflags(
  11.549 -    unsigned long val,
  11.550 -    struct x86_emulate_ctxt *ctxt)
  11.551 -{
  11.552 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.553 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.554 -    if ( (val & X86_EFLAGS_IF) && !(ctxt->regs->eflags & X86_EFLAGS_IF) )
  11.555 -        rm_ctxt->flags.sti = 1;
  11.556 -    return X86EMUL_OKAY;
  11.557 -}
  11.558 -
  11.559 -static int realmode_wbinvd(
  11.560 -    struct x86_emulate_ctxt *ctxt)
  11.561 -{
  11.562 -    vmx_wbinvd_intercept();
  11.563 -    return X86EMUL_OKAY;
  11.564 -}
  11.565 -
  11.566 -static int realmode_cpuid(
  11.567 -    unsigned int *eax,
  11.568 -    unsigned int *ebx,
  11.569 -    unsigned int *ecx,
  11.570 -    unsigned int *edx,
  11.571 -    struct x86_emulate_ctxt *ctxt)
  11.572 -{
  11.573 -    vmx_cpuid_intercept(eax, ebx, ecx, edx);
  11.574 -    return X86EMUL_OKAY;
  11.575 -}
  11.576 -
  11.577 -static int realmode_hlt(
  11.578 -    struct x86_emulate_ctxt *ctxt)
  11.579 -{
  11.580 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.581 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.582 -    rm_ctxt->flags.hlt = 1;
  11.583 -    return X86EMUL_OKAY;
  11.584 -}
  11.585 -
  11.586 -static int realmode_inject_hw_exception(
  11.587 -    uint8_t vector,
  11.588 -    uint16_t error_code,
  11.589 -    struct x86_emulate_ctxt *ctxt)
  11.590 -{
  11.591 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.592 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.593 -
  11.594 -    /* We don't emulate protected-mode exception delivery. */
  11.595 -    if ( current->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.596 -        return X86EMUL_UNHANDLEABLE;
  11.597 -
  11.598 -    if ( error_code != 0 )
  11.599 -        return X86EMUL_UNHANDLEABLE;
  11.600 -
  11.601 -    rm_ctxt->exn_vector = vector;
  11.602 -    rm_ctxt->exn_insn_len = 0;
  11.603 -
  11.604 -    return X86EMUL_OKAY;
  11.605 -}
  11.606 -
  11.607 -static int realmode_inject_sw_interrupt(
  11.608 -    uint8_t vector,
  11.609 -    uint8_t insn_len,
  11.610 -    struct x86_emulate_ctxt *ctxt)
  11.611 -{
  11.612 -    struct realmode_emulate_ctxt *rm_ctxt =
  11.613 -        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
  11.614 -
  11.615 -    /* We don't emulate protected-mode exception delivery. */
  11.616 -    if ( current->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.617 -        return X86EMUL_UNHANDLEABLE;
  11.618 -
  11.619 -    rm_ctxt->exn_vector = vector;
  11.620 -    rm_ctxt->exn_insn_len = insn_len;
  11.621 -
  11.622 -    return X86EMUL_OKAY;
  11.623 -}
  11.624 -
  11.625 -static void realmode_load_fpu_ctxt(
  11.626 -    struct x86_emulate_ctxt *ctxt)
  11.627 -{
  11.628 -    if ( !current->fpu_dirtied )
  11.629 -        vmx_do_no_device_fault();
  11.630 -}
  11.631 -
  11.632 -static struct x86_emulate_ops realmode_emulator_ops = {
  11.633 -    .read          = realmode_emulate_read,
  11.634 -    .insn_fetch    = realmode_emulate_insn_fetch,
  11.635 -    .write         = realmode_emulate_write,
  11.636 -    .cmpxchg       = realmode_emulate_cmpxchg,
  11.637 -    .rep_ins       = realmode_rep_ins,
  11.638 -    .rep_outs      = realmode_rep_outs,
  11.639 -    .rep_movs      = realmode_rep_movs,
  11.640 -    .read_segment  = realmode_read_segment,
  11.641 -    .write_segment = realmode_write_segment,
  11.642 -    .read_io       = realmode_read_io,
  11.643 -    .write_io      = realmode_write_io,
  11.644 -    .read_cr       = realmode_read_cr,
  11.645 -    .write_cr      = realmode_write_cr,
  11.646 -    .read_msr      = realmode_read_msr,
  11.647 -    .write_msr     = realmode_write_msr,
  11.648 -    .write_rflags  = realmode_write_rflags,
  11.649 -    .wbinvd        = realmode_wbinvd,
  11.650 -    .cpuid         = realmode_cpuid,
  11.651 -    .hlt           = realmode_hlt,
  11.652 -    .inject_hw_exception = realmode_inject_hw_exception,
  11.653 -    .inject_sw_interrupt = realmode_inject_sw_interrupt,
  11.654 -    .load_fpu_ctxt = realmode_load_fpu_ctxt
  11.655 -};
  11.656 -
  11.657 -static void realmode_emulate_one(struct realmode_emulate_ctxt *rm_ctxt)
  11.658 -{
  11.659 -    struct cpu_user_regs *regs = rm_ctxt->ctxt.regs;
  11.660 -    struct vcpu *curr = current;
  11.661 -    u32 new_intr_shadow;
  11.662 -    int rc, io_completed;
  11.663 -    unsigned long addr;
  11.664 -
  11.665 -    rm_ctxt->ctxt.addr_size =
  11.666 -        rm_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
  11.667 -    rm_ctxt->ctxt.sp_size =
  11.668 -        rm_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
  11.669 -
  11.670 -    rm_ctxt->insn_buf_eip = (uint32_t)regs->eip;
  11.671 -    addr = virtual_to_linear(x86_seg_cs, regs->eip, rm_ctxt);
  11.672 -    if ( hvm_fetch_from_guest_virt_nofault(rm_ctxt->insn_buf, addr,
  11.673 -                                           sizeof(rm_ctxt->insn_buf))
  11.674 -         != HVMCOPY_okay )
  11.675 -    {
  11.676 -        gdprintk(XENLOG_ERR, "Failed to pre-fetch instruction bytes.\n");
  11.677 -        goto fail;
  11.678 -    }
  11.679 -
  11.680 -    rm_ctxt->flag_word = 0;
  11.681 -
  11.682 -    io_completed = curr->arch.hvm_vmx.real_mode_io_completed;
  11.683 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.684 -    {
  11.685 -        gdprintk(XENLOG_ERR, "I/O in progress before insn is emulated.\n");
  11.686 -        goto fail;
  11.687 -    }
  11.688 -
  11.689 -    rc = x86_emulate(&rm_ctxt->ctxt, &realmode_emulator_ops);
  11.690 -
  11.691 -    if ( curr->arch.hvm_vmx.real_mode_io_completed )
  11.692 -    {
  11.693 -        gdprintk(XENLOG_ERR, "I/O completion after insn is emulated.\n");
  11.694 -        goto fail;
  11.695 -    }
  11.696 +    rm_ctxt->hvm.seg_reg_dirty |= seg_reg_dirty;
  11.697  
  11.698      if ( rc == X86EMUL_UNHANDLEABLE )
  11.699      {
  11.700 @@ -717,31 +138,18 @@ static void realmode_emulate_one(struct 
  11.701      }
  11.702  
  11.703      if ( rc == X86EMUL_RETRY )
  11.704 -    {
  11.705 -        BUG_ON(!curr->arch.hvm_vmx.real_mode_io_in_progress);
  11.706 -        if ( !io_completed )
  11.707 -            return;
  11.708 -        gdprintk(XENLOG_ERR, "Multiple I/O reads in a single insn.\n");
  11.709 -        goto fail;
  11.710 -    }
  11.711 -
  11.712 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress &&
  11.713 -         (get_ioreq(curr)->vp_ioreq.dir == IOREQ_READ) )
  11.714 -    {
  11.715 -        gdprintk(XENLOG_ERR, "I/O read in progress but insn is retired.\n");
  11.716 -        goto fail;
  11.717 -    }
  11.718 +        return;
  11.719  
  11.720      new_intr_shadow = rm_ctxt->intr_shadow;
  11.721  
  11.722      /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */
  11.723 -    if ( rm_ctxt->flags.mov_ss )
  11.724 +    if ( rm_ctxt->hvm.flags.mov_ss )
  11.725          new_intr_shadow ^= VMX_INTR_SHADOW_MOV_SS;
  11.726      else
  11.727          new_intr_shadow &= ~VMX_INTR_SHADOW_MOV_SS;
  11.728  
  11.729      /* STI instruction toggles STI shadow, else we just clear it. */
  11.730 -    if ( rm_ctxt->flags.sti )
  11.731 +    if ( rm_ctxt->hvm.flags.sti )
  11.732          new_intr_shadow ^= VMX_INTR_SHADOW_STI;
  11.733      else
  11.734          new_intr_shadow &= ~VMX_INTR_SHADOW_STI;
  11.735 @@ -755,10 +163,30 @@ static void realmode_emulate_one(struct 
  11.736  
  11.737      if ( rc == X86EMUL_EXCEPTION )
  11.738      {
  11.739 +        if ( !rm_ctxt->hvm.flags.exn_pending )
  11.740 +        {
  11.741 +            intr_info = __vmread(VM_ENTRY_INTR_INFO);
  11.742 +            __vmwrite(VM_ENTRY_INTR_INFO, 0);
  11.743 +            if ( !(intr_info & INTR_INFO_VALID_MASK) )
  11.744 +            {
  11.745 +                gdprintk(XENLOG_ERR, "Exception pending but no info.\n");
  11.746 +                goto fail;
  11.747 +            }
  11.748 +            rm_ctxt->hvm.exn_vector = (uint8_t)intr_info;
  11.749 +            rm_ctxt->hvm.exn_insn_len = 0;
  11.750 +        }
  11.751 +
  11.752 +        if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
  11.753 +        {
  11.754 +            gdprintk(XENLOG_ERR, "Exception %02x in protected mode.\n",
  11.755 +                     rm_ctxt->hvm.exn_vector);
  11.756 +            goto fail;
  11.757 +        }
  11.758 +
  11.759          realmode_deliver_exception(
  11.760 -            rm_ctxt->exn_vector, rm_ctxt->exn_insn_len, rm_ctxt);
  11.761 +            rm_ctxt->hvm.exn_vector, rm_ctxt->hvm.exn_insn_len, rm_ctxt);
  11.762      }
  11.763 -    else if ( rm_ctxt->flags.hlt && !hvm_local_events_need_delivery(curr) )
  11.764 +    else if ( rm_ctxt->hvm.flags.hlt && !hvm_local_events_need_delivery(curr) )
  11.765      {
  11.766          hvm_hlt(regs->eflags);
  11.767      }
  11.768 @@ -769,10 +197,11 @@ static void realmode_emulate_one(struct 
  11.769      gdprintk(XENLOG_ERR,
  11.770               "Real-mode emulation failed @ %04x:%08lx: "
  11.771               "%02x %02x %02x %02x %02x %02x\n",
  11.772 -             rm_ctxt->seg_reg[x86_seg_cs].sel, rm_ctxt->insn_buf_eip,
  11.773 -             rm_ctxt->insn_buf[0], rm_ctxt->insn_buf[1],
  11.774 -             rm_ctxt->insn_buf[2], rm_ctxt->insn_buf[3],
  11.775 -             rm_ctxt->insn_buf[4], rm_ctxt->insn_buf[5]);
  11.776 +             hvmemul_get_seg_reg(x86_seg_cs, &rm_ctxt->hvm)->sel,
  11.777 +             rm_ctxt->hvm.insn_buf_eip,
  11.778 +             rm_ctxt->hvm.insn_buf[0], rm_ctxt->hvm.insn_buf[1],
  11.779 +             rm_ctxt->hvm.insn_buf[2], rm_ctxt->hvm.insn_buf[3],
  11.780 +             rm_ctxt->hvm.insn_buf[4], rm_ctxt->hvm.insn_buf[5]);
  11.781      domain_crash_synchronous();
  11.782  }
  11.783  
  11.784 @@ -780,18 +209,20 @@ void vmx_realmode(struct cpu_user_regs *
  11.785  {
  11.786      struct vcpu *curr = current;
  11.787      struct realmode_emulate_ctxt rm_ctxt;
  11.788 -    unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO);
  11.789 -    unsigned int i, emulations = 0;
  11.790 +    struct segment_register *sreg;
  11.791 +    unsigned long intr_info;
  11.792 +    unsigned int emulations = 0;
  11.793  
  11.794 -    rm_ctxt.ctxt.regs = regs;
  11.795 +    /* Get-and-clear VM_ENTRY_INTR_INFO. */
  11.796 +    intr_info = __vmread(VM_ENTRY_INTR_INFO);
  11.797 +    if ( intr_info & INTR_INFO_VALID_MASK )
  11.798 +        __vmwrite(VM_ENTRY_INTR_INFO, 0);
  11.799  
  11.800 -    for ( i = 0; i < 10; i++ )
  11.801 -        hvm_get_segment_register(curr, i, &rm_ctxt.seg_reg[i]);
  11.802 -
  11.803 +    hvm_emulate_prepare(&rm_ctxt.hvm, regs);
  11.804      rm_ctxt.intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
  11.805  
  11.806 -    if ( curr->arch.hvm_vmx.real_mode_io_in_progress ||
  11.807 -         curr->arch.hvm_vmx.real_mode_io_completed )
  11.808 +    if ( curr->arch.hvm_vcpu.io_in_progress ||
  11.809 +         curr->arch.hvm_vcpu.io_completed )
  11.810          realmode_emulate_one(&rm_ctxt);
  11.811  
  11.812      /* Only deliver interrupts into emulated real mode. */
  11.813 @@ -799,12 +230,12 @@ void vmx_realmode(struct cpu_user_regs *
  11.814           (intr_info & INTR_INFO_VALID_MASK) )
  11.815      {
  11.816          realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
  11.817 -        __vmwrite(VM_ENTRY_INTR_INFO, 0);
  11.818 +        intr_info = 0;
  11.819      }
  11.820  
  11.821      while ( curr->arch.hvm_vmx.vmxemul &&
  11.822              !softirq_pending(smp_processor_id()) &&
  11.823 -            !curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.824 +            !curr->arch.hvm_vcpu.io_in_progress )
  11.825      {
  11.826          /*
  11.827           * Check for pending interrupts only every 16 instructions, because
  11.828 @@ -825,34 +256,22 @@ void vmx_realmode(struct cpu_user_regs *
  11.829           * At this point CS.RPL == SS.RPL == CS.DPL == SS.DPL == 0. For
  11.830           * DS, ES, FS and GS the most uninvasive trick is to set DPL == RPL.
  11.831           */
  11.832 -        rm_ctxt.seg_reg[x86_seg_ds].attr.fields.dpl =
  11.833 -            rm_ctxt.seg_reg[x86_seg_ds].sel & 3;
  11.834 -        rm_ctxt.seg_reg[x86_seg_es].attr.fields.dpl =
  11.835 -            rm_ctxt.seg_reg[x86_seg_es].sel & 3;
  11.836 -        rm_ctxt.seg_reg[x86_seg_fs].attr.fields.dpl =
  11.837 -            rm_ctxt.seg_reg[x86_seg_fs].sel & 3;
  11.838 -        rm_ctxt.seg_reg[x86_seg_gs].attr.fields.dpl =
  11.839 -            rm_ctxt.seg_reg[x86_seg_gs].sel & 3;
  11.840 +        sreg = hvmemul_get_seg_reg(x86_seg_ds, &rm_ctxt.hvm);
  11.841 +        sreg->attr.fields.dpl = sreg->sel & 3;
  11.842 +        sreg = hvmemul_get_seg_reg(x86_seg_es, &rm_ctxt.hvm);
  11.843 +        sreg->attr.fields.dpl = sreg->sel & 3;
  11.844 +        sreg = hvmemul_get_seg_reg(x86_seg_fs, &rm_ctxt.hvm);
  11.845 +        sreg->attr.fields.dpl = sreg->sel & 3;
  11.846 +        sreg = hvmemul_get_seg_reg(x86_seg_gs, &rm_ctxt.hvm);
  11.847 +        sreg->attr.fields.dpl = sreg->sel & 3;
  11.848 +        rm_ctxt.hvm.seg_reg_dirty |=
  11.849 +            (1ul << x86_seg_ds) | (1ul << x86_seg_es) |
  11.850 +            (1ul << x86_seg_fs) | (1ul << x86_seg_gs);
  11.851      }
  11.852  
  11.853 -    for ( i = 0; i < 10; i++ )
  11.854 -        hvm_set_segment_register(curr, i, &rm_ctxt.seg_reg[i]);
  11.855 -}
  11.856 -
  11.857 -int vmx_realmode_io_complete(void)
  11.858 -{
  11.859 -    struct vcpu *curr = current;
  11.860 -    ioreq_t *p = &get_ioreq(curr)->vp_ioreq;
  11.861 +    hvm_emulate_writeback(&rm_ctxt.hvm);
  11.862  
  11.863 -    if ( !curr->arch.hvm_vmx.real_mode_io_in_progress )
  11.864 -        return 0;
  11.865 -
  11.866 -    curr->arch.hvm_vmx.real_mode_io_in_progress = 0;
  11.867 -    if ( p->dir == IOREQ_READ )
  11.868 -    {
  11.869 -        curr->arch.hvm_vmx.real_mode_io_completed = 1;
  11.870 -        curr->arch.hvm_vmx.real_mode_io_data = p->data;
  11.871 -    }
  11.872 -
  11.873 -    return 1;
  11.874 +    /* Re-instate VM_ENTRY_INTR_INFO if we did not discharge it. */
  11.875 +    if ( intr_info & INTR_INFO_VALID_MASK )
  11.876 +        __vmwrite(VM_ENTRY_INTR_INFO, intr_info);
  11.877  }
    12.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Tue Feb 19 11:14:40 2008 -0700
    12.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Feb 20 14:36:45 2008 +0000
    12.3 @@ -60,6 +60,13 @@ static void vmx_free_vlapic_mapping(stru
    12.4  static void vmx_install_vlapic_mapping(struct vcpu *v);
    12.5  static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr);
    12.6  static void vmx_update_guest_efer(struct vcpu *v);
    12.7 +static void vmx_cpuid_intercept(
    12.8 +    unsigned int *eax, unsigned int *ebx,
    12.9 +    unsigned int *ecx, unsigned int *edx);
   12.10 +static void vmx_wbinvd_intercept(void);
   12.11 +static void vmx_fpu_dirty_intercept(void);
   12.12 +static int vmx_msr_read_intercept(struct cpu_user_regs *regs);
   12.13 +static int vmx_msr_write_intercept(struct cpu_user_regs *regs);
   12.14  
   12.15  static int vmx_domain_initialise(struct domain *d)
   12.16  {
   12.17 @@ -96,7 +103,6 @@ static int vmx_vcpu_initialise(struct vc
   12.18      /* %eax == 1 signals full real-mode support to the guest loader. */
   12.19      if ( v->vcpu_id == 0 )
   12.20          v->arch.guest_context.user_regs.eax = 1;
   12.21 -    v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete;
   12.22  
   12.23      return 0;
   12.24  }
   12.25 @@ -204,7 +210,7 @@ static enum handler_return long_mode_do_
   12.26      switch ( ecx )
   12.27      {
   12.28      case MSR_EFER:
   12.29 -        if ( !hvm_set_efer(msr_content) )
   12.30 +        if ( hvm_set_efer(msr_content) )
   12.31              goto exception_raised;
   12.32          break;
   12.33  
   12.34 @@ -375,7 +381,7 @@ static enum handler_return long_mode_do_
   12.35      switch ( regs->ecx )
   12.36      {
   12.37      case MSR_EFER:
   12.38 -        if ( !hvm_set_efer(msr_content) )
   12.39 +        if ( hvm_set_efer(msr_content) )
   12.40              return HNDL_exception_raised;
   12.41          break;
   12.42  
   12.43 @@ -1076,6 +1082,11 @@ static struct hvm_function_table vmx_fun
   12.44      .do_pmu_interrupt     = vmx_do_pmu_interrupt,
   12.45      .cpu_up               = vmx_cpu_up,
   12.46      .cpu_down             = vmx_cpu_down,
   12.47 +    .cpuid_intercept      = vmx_cpuid_intercept,
   12.48 +    .wbinvd_intercept     = vmx_wbinvd_intercept,
   12.49 +    .fpu_dirty_intercept  = vmx_fpu_dirty_intercept,
   12.50 +    .msr_read_intercept   = vmx_msr_read_intercept,
   12.51 +    .msr_write_intercept  = vmx_msr_write_intercept
   12.52  };
   12.53  
   12.54  void start_vmx(void)
   12.55 @@ -1147,7 +1158,7 @@ static void __update_guest_eip(unsigned 
   12.56          vmx_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0);
   12.57  }
   12.58  
   12.59 -void vmx_do_no_device_fault(void)
   12.60 +static void vmx_fpu_dirty_intercept(void)
   12.61  {
   12.62      struct vcpu *curr = current;
   12.63  
   12.64 @@ -1162,7 +1173,7 @@ void vmx_do_no_device_fault(void)
   12.65  }
   12.66  
   12.67  #define bitmaskof(idx)  (1U << ((idx) & 31))
   12.68 -void vmx_cpuid_intercept(
   12.69 +static void vmx_cpuid_intercept(
   12.70      unsigned int *eax, unsigned int *ebx,
   12.71      unsigned int *ecx, unsigned int *edx)
   12.72  {
   12.73 @@ -1751,13 +1762,13 @@ static int mov_to_cr(int gp, int cr, str
   12.74      switch ( cr )
   12.75      {
   12.76      case 0:
   12.77 -        return hvm_set_cr0(value);
   12.78 +        return !hvm_set_cr0(value);
   12.79  
   12.80      case 3:
   12.81 -        return hvm_set_cr3(value);
   12.82 +        return !hvm_set_cr3(value);
   12.83  
   12.84      case 4:
   12.85 -        return hvm_set_cr4(value);
   12.86 +        return !hvm_set_cr4(value);
   12.87  
   12.88      case 8:
   12.89          vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
   12.90 @@ -1848,7 +1859,7 @@ static int vmx_cr_access(unsigned long e
   12.91          value = (value & ~0xF) |
   12.92              (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
   12.93          HVMTRACE_1D(LMSW, current, value);
   12.94 -        return hvm_set_cr0(value);
   12.95 +        return !hvm_set_cr0(value);
   12.96      default:
   12.97          BUG();
   12.98      }
   12.99 @@ -1932,7 +1943,7 @@ static int is_last_branch_msr(u32 ecx)
  12.100      return 0;
  12.101  }
  12.102  
  12.103 -int vmx_msr_read_intercept(struct cpu_user_regs *regs)
  12.104 +static int vmx_msr_read_intercept(struct cpu_user_regs *regs)
  12.105  {
  12.106      u64 msr_content = 0;
  12.107      u32 ecx = regs->ecx, eax, edx;
  12.108 @@ -2017,7 +2028,7 @@ int vmx_msr_read_intercept(struct cpu_us
  12.109              case HNDL_unhandled:
  12.110                  break;
  12.111              case HNDL_exception_raised:
  12.112 -                return 0;
  12.113 +                return X86EMUL_EXCEPTION;
  12.114              case HNDL_done:
  12.115                  goto done;
  12.116          }
  12.117 @@ -2050,11 +2061,11 @@ done:
  12.118      HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
  12.119                  ecx, (unsigned long)regs->eax,
  12.120                  (unsigned long)regs->edx);
  12.121 -    return 1;
  12.122 +    return X86EMUL_OKAY;
  12.123  
  12.124  gp_fault:
  12.125      vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
  12.126 -    return 0;
  12.127 +    return X86EMUL_EXCEPTION;
  12.128  }
  12.129  
  12.130  static int vmx_alloc_vlapic_mapping(struct domain *d)
  12.131 @@ -2124,7 +2135,7 @@ extern bool_t mtrr_fix_range_msr_set(str
  12.132  extern bool_t mtrr_def_type_msr_set(struct mtrr_state *v, u64 msr_content);
  12.133  extern bool_t pat_msr_set(u64 *pat, u64 msr);
  12.134  
  12.135 -int vmx_msr_write_intercept(struct cpu_user_regs *regs)
  12.136 +static int vmx_msr_write_intercept(struct cpu_user_regs *regs)
  12.137  {
  12.138      u32 ecx = regs->ecx;
  12.139      u64 msr_content;
  12.140 @@ -2219,7 +2230,7 @@ int vmx_msr_write_intercept(struct cpu_u
  12.141          goto gp_fault;
  12.142      default:
  12.143          if ( vpmu_do_wrmsr(regs) )
  12.144 -            return 1;
  12.145 +            return X86EMUL_OKAY;
  12.146          switch ( long_mode_do_msr_write(regs) )
  12.147          {
  12.148              case HNDL_unhandled:
  12.149 @@ -2228,18 +2239,18 @@ int vmx_msr_write_intercept(struct cpu_u
  12.150                      wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
  12.151                  break;
  12.152              case HNDL_exception_raised:
  12.153 -                return 0;
  12.154 +                return X86EMUL_EXCEPTION;
  12.155              case HNDL_done:
  12.156                  break;
  12.157          }
  12.158          break;
  12.159      }
  12.160  
  12.161 -    return 1;
  12.162 +    return X86EMUL_OKAY;
  12.163  
  12.164  gp_fault:
  12.165      vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
  12.166 -    return 0;
  12.167 +    return X86EMUL_EXCEPTION;
  12.168  }
  12.169  
  12.170  static void vmx_do_hlt(struct cpu_user_regs *regs)
  12.171 @@ -2320,7 +2331,7 @@ static void wbinvd_ipi(void *info)
  12.172      wbinvd();
  12.173  }
  12.174  
  12.175 -void vmx_wbinvd_intercept(void)
  12.176 +static void vmx_wbinvd_intercept(void)
  12.177  {
  12.178      if ( list_empty(&(domain_hvm_iommu(current->domain)->pdev_list)) )
  12.179          return;
  12.180 @@ -2447,7 +2458,7 @@ asmlinkage void vmx_vmexit_handler(struc
  12.181              domain_pause_for_debugger();
  12.182              break;
  12.183          case TRAP_no_device:
  12.184 -            vmx_do_no_device_fault();
  12.185 +            vmx_fpu_dirty_intercept();
  12.186              break;
  12.187          case TRAP_page_fault:
  12.188              exit_qualification = __vmread(EXIT_QUALIFICATION);
  12.189 @@ -2566,12 +2577,12 @@ asmlinkage void vmx_vmexit_handler(struc
  12.190          break;
  12.191      case EXIT_REASON_MSR_READ:
  12.192          inst_len = __get_instruction_length(); /* Safe: RDMSR */
  12.193 -        if ( vmx_msr_read_intercept(regs) )
  12.194 +        if ( vmx_msr_read_intercept(regs) == X86EMUL_OKAY )
  12.195              __update_guest_eip(inst_len);
  12.196          break;
  12.197      case EXIT_REASON_MSR_WRITE:
  12.198          inst_len = __get_instruction_length(); /* Safe: WRMSR */
  12.199 -        if ( vmx_msr_write_intercept(regs) )
  12.200 +        if ( vmx_msr_write_intercept(regs) == X86EMUL_OKAY )
  12.201              __update_guest_eip(inst_len);
  12.202          break;
  12.203  
  12.204 @@ -2597,7 +2608,8 @@ asmlinkage void vmx_vmexit_handler(struc
  12.205          unsigned long offset;
  12.206          exit_qualification = __vmread(EXIT_QUALIFICATION);
  12.207          offset = exit_qualification & 0x0fffUL;
  12.208 -        handle_mmio(APIC_DEFAULT_PHYS_BASE | offset);
  12.209 +        if ( !handle_mmio() )
  12.210 +            hvm_inject_exception(TRAP_gp_fault, 0, 0);
  12.211          break;
  12.212      }
  12.213  
    13.1 --- a/xen/arch/x86/mm/shadow/multi.c	Tue Feb 19 11:14:40 2008 -0700
    13.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Feb 20 14:36:45 2008 +0000
    13.3 @@ -2816,8 +2816,7 @@ static int sh_page_fault(struct vcpu *v,
    13.4              perfc_incr(shadow_fault_fast_mmio);
    13.5              SHADOW_PRINTK("fast path mmio %#"PRIpaddr"\n", gpa);
    13.6              reset_early_unshadow(v);
    13.7 -            handle_mmio(gpa);
    13.8 -            return EXCRET_fault_fixed;
    13.9 +            return handle_mmio() ? EXCRET_fault_fixed : 0;
   13.10          }
   13.11          else
   13.12          {
   13.13 @@ -3117,8 +3116,7 @@ static int sh_page_fault(struct vcpu *v,
   13.14      shadow_audit_tables(v);
   13.15      reset_early_unshadow(v);
   13.16      shadow_unlock(d);
   13.17 -    handle_mmio(gpa);
   13.18 -    return EXCRET_fault_fixed;
   13.19 +    return handle_mmio() ? EXCRET_fault_fixed : 0;
   13.20  
   13.21   not_a_shadow_fault:
   13.22      sh_audit_gw(v, &gw);
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen/include/asm-x86/hvm/emulate.h	Wed Feb 20 14:36:45 2008 +0000
    14.3 @@ -0,0 +1,55 @@
    14.4 +/******************************************************************************
    14.5 + * hvm/emulate.h
    14.6 + * 
    14.7 + * HVM instruction emulation. Used for MMIO and VMX real mode.
    14.8 + * 
    14.9 + * Copyright (c) 2008 Citrix Systems, Inc.
   14.10 + * 
   14.11 + * Authors:
   14.12 + *    Keir Fraser <keir.fraser@citrix.com>
   14.13 + */
   14.14 +
   14.15 +#ifndef __ASM_X86_HVM_EMULATE_H__
   14.16 +#define __ASM_X86_HVM_EMULATE_H__
   14.17 +
   14.18 +#include <xen/config.h>
   14.19 +#include <asm/x86_emulate.h>
   14.20 +
   14.21 +struct hvm_emulate_ctxt {
   14.22 +    struct x86_emulate_ctxt ctxt;
   14.23 +
   14.24 +    /* Cache of 16 bytes of instruction. */
   14.25 +    uint8_t insn_buf[16];
   14.26 +    unsigned long insn_buf_eip;
   14.27 +    unsigned int insn_buf_bytes;
   14.28 +
   14.29 +    struct segment_register seg_reg[10];
   14.30 +    unsigned long seg_reg_accessed;
   14.31 +    unsigned long seg_reg_dirty;
   14.32 +
   14.33 +    union {
   14.34 +        struct {
   14.35 +            unsigned int hlt:1;
   14.36 +            unsigned int mov_ss:1;
   14.37 +            unsigned int sti:1;
   14.38 +            unsigned int exn_pending:1;
   14.39 +        } flags;
   14.40 +        unsigned int flag_word;
   14.41 +    };
   14.42 +
   14.43 +    uint8_t exn_vector;
   14.44 +    uint8_t exn_insn_len;
   14.45 +};
   14.46 +
   14.47 +int hvm_emulate_one(
   14.48 +    struct hvm_emulate_ctxt *hvmemul_ctxt);
   14.49 +void hvm_emulate_prepare(
   14.50 +    struct hvm_emulate_ctxt *hvmemul_ctxt,
   14.51 +    struct cpu_user_regs *regs);
   14.52 +void hvm_emulate_writeback(
   14.53 +    struct hvm_emulate_ctxt *hvmemul_ctxt);
   14.54 +struct segment_register *hvmemul_get_seg_reg(
   14.55 +    enum x86_segment seg,
   14.56 +    struct hvm_emulate_ctxt *hvmemul_ctxt);
   14.57 +
   14.58 +#endif /* __ASM_X86_HVM_EMULATE_H__ */
    15.1 --- a/xen/include/asm-x86/hvm/hvm.h	Tue Feb 19 11:14:40 2008 -0700
    15.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Wed Feb 20 14:36:45 2008 +0000
    15.3 @@ -117,6 +117,15 @@ struct hvm_function_table {
    15.4  
    15.5      int  (*cpu_up)(void);
    15.6      void (*cpu_down)(void);
    15.7 +
    15.8 +    /* Instruction intercepts: non-void return values are X86EMUL codes. */
    15.9 +    void (*cpuid_intercept)(
   15.10 +        unsigned int *eax, unsigned int *ebx,
   15.11 +        unsigned int *ecx, unsigned int *edx);
   15.12 +    void (*wbinvd_intercept)(void);
   15.13 +    void (*fpu_dirty_intercept)(void);
   15.14 +    int (*msr_read_intercept)(struct cpu_user_regs *regs);
   15.15 +    int (*msr_write_intercept)(struct cpu_user_regs *regs);
   15.16  };
   15.17  
   15.18  extern struct hvm_function_table hvm_funcs;
   15.19 @@ -163,9 +172,6 @@ hvm_guest_x86_mode(struct vcpu *v)
   15.20      return hvm_funcs.guest_x86_mode(v);
   15.21  }
   15.22  
   15.23 -int hvm_instruction_fetch(unsigned long pc, int address_bytes,
   15.24 -                          unsigned char *buf);
   15.25 -
   15.26  static inline void
   15.27  hvm_update_host_cr3(struct vcpu *v)
   15.28  {
    16.1 --- a/xen/include/asm-x86/hvm/io.h	Tue Feb 19 11:14:40 2008 -0700
    16.2 +++ b/xen/include/asm-x86/hvm/io.h	Wed Feb 20 14:36:45 2008 +0000
    16.3 @@ -120,8 +120,8 @@ struct hvm_mmio_handler {
    16.4  };
    16.5  
    16.6  /* global io interception point in HV */
    16.7 -extern int hvm_io_intercept(ioreq_t *p, int type);
    16.8 -extern int register_io_handler(
    16.9 +int hvm_io_intercept(ioreq_t *p, int type);
   16.10 +int register_io_handler(
   16.11      struct domain *d, unsigned long addr, unsigned long size,
   16.12      void *action, int type);
   16.13  
   16.14 @@ -135,8 +135,8 @@ static inline int hvm_buffered_io_interc
   16.15      return hvm_io_intercept(p, HVM_BUFFERED_IO);
   16.16  }
   16.17  
   16.18 -extern int hvm_mmio_intercept(ioreq_t *p);
   16.19 -extern int hvm_buffered_io_send(ioreq_t *p);
   16.20 +int hvm_mmio_intercept(ioreq_t *p);
   16.21 +int hvm_buffered_io_send(ioreq_t *p);
   16.22  
   16.23  static inline int register_portio_handler(
   16.24      struct domain *d, unsigned long addr,
   16.25 @@ -159,11 +159,11 @@ void send_pio_req(unsigned long port, un
   16.26                    paddr_t value, int dir, int df, int value_is_ptr);
   16.27  void send_timeoffset_req(unsigned long timeoff);
   16.28  void send_invalidate_req(void);
   16.29 -extern void handle_mmio(paddr_t gpa);
   16.30 -extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
   16.31 -extern void hvm_io_assist(void);
   16.32 -extern void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
   16.33 -                         union vioapic_redir_entry *ent);
   16.34 +int handle_mmio(void);
   16.35 +void hvm_interrupt_post(struct vcpu *v, int vector, int type);
   16.36 +void hvm_io_assist(void);
   16.37 +void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
   16.38 +                  union vioapic_redir_entry *ent);
   16.39  
   16.40  struct hvm_hw_stdvga {
   16.41      uint8_t sr_index;
    17.1 --- a/xen/include/asm-x86/hvm/support.h	Tue Feb 19 11:14:40 2008 -0700
    17.2 +++ b/xen/include/asm-x86/hvm/support.h	Wed Feb 20 14:36:45 2008 +0000
    17.3 @@ -138,6 +138,7 @@ int hvm_do_hypercall(struct cpu_user_reg
    17.4  void hvm_hlt(unsigned long rflags);
    17.5  void hvm_triple_fault(void);
    17.6  
    17.7 +/* These functions all return X86EMUL return codes. */
    17.8  int hvm_set_efer(uint64_t value);
    17.9  int hvm_set_cr0(unsigned long value);
   17.10  int hvm_set_cr3(unsigned long value);
    18.1 --- a/xen/include/asm-x86/hvm/vcpu.h	Tue Feb 19 11:14:40 2008 -0700
    18.2 +++ b/xen/include/asm-x86/hvm/vcpu.h	Wed Feb 20 14:36:45 2008 +0000
    18.3 @@ -59,9 +59,6 @@ struct hvm_vcpu {
    18.4      bool_t              flag_dr_dirty;
    18.5      bool_t              debug_state_latch;
    18.6  
    18.7 -    /* Callback function for I/O completion. */
    18.8 -    int                 (*io_complete)(void);
    18.9 -
   18.10      union {
   18.11          struct arch_vmx_struct vmx;
   18.12          struct arch_svm_struct svm;
   18.13 @@ -72,6 +69,12 @@ struct hvm_vcpu {
   18.14  
   18.15      /* Which cache mode is this VCPU in (CR0:CD/NW)? */
   18.16      u8                  cache_mode;
   18.17 +
   18.18 +    /* I/O request in flight to device model. */
   18.19 +    bool_t              mmio_in_progress;
   18.20 +    bool_t              io_in_progress;
   18.21 +    bool_t              io_completed;
   18.22 +    unsigned long       io_data;
   18.23  };
   18.24  
   18.25  #define ARCH_HVM_IO_WAIT         1   /* Waiting for I/O completion */
    19.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Tue Feb 19 11:14:40 2008 -0700
    19.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Wed Feb 20 14:36:45 2008 +0000
    19.3 @@ -94,11 +94,6 @@ struct arch_vmx_struct {
    19.4  #define VMXEMUL_BAD_CS   2  /* Yes, because CS.RPL != CPL */
    19.5  #define VMXEMUL_BAD_SS   4  /* Yes, because SS.RPL != CPL */
    19.6      uint8_t              vmxemul;
    19.7 -
    19.8 -    /* I/O request in flight to device model. */
    19.9 -    bool_t               real_mode_io_in_progress;
   19.10 -    bool_t               real_mode_io_completed;
   19.11 -    unsigned long        real_mode_io_data;
   19.12  };
   19.13  
   19.14  int vmx_create_vmcs(struct vcpu *v);
    20.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Tue Feb 19 11:14:40 2008 -0700
    20.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Wed Feb 20 14:36:45 2008 +0000
    20.3 @@ -33,15 +33,7 @@ void vmx_intr_assist(void);
    20.4  void vmx_do_resume(struct vcpu *);
    20.5  void set_guest_time(struct vcpu *v, u64 gtime);
    20.6  void vmx_vlapic_msr_changed(struct vcpu *v);
    20.7 -void vmx_do_no_device_fault(void);
    20.8 -void vmx_cpuid_intercept(
    20.9 -    unsigned int *eax, unsigned int *ebx,
   20.10 -    unsigned int *ecx, unsigned int *edx);
   20.11 -int vmx_msr_read_intercept(struct cpu_user_regs *regs);
   20.12 -int vmx_msr_write_intercept(struct cpu_user_regs *regs);
   20.13 -void vmx_wbinvd_intercept(void);
   20.14  void vmx_realmode(struct cpu_user_regs *regs);
   20.15 -int vmx_realmode_io_complete(void);
   20.16  
   20.17  /*
   20.18   * Exit Reasons
    21.1 --- a/xen/include/public/hvm/ioreq.h	Tue Feb 19 11:14:40 2008 -0700
    21.2 +++ b/xen/include/public/hvm/ioreq.h	Wed Feb 20 14:36:45 2008 +0000
    21.3 @@ -34,14 +34,8 @@
    21.4  
    21.5  #define IOREQ_TYPE_PIO          0 /* pio */
    21.6  #define IOREQ_TYPE_COPY         1 /* mmio ops */
    21.7 -#define IOREQ_TYPE_AND          2
    21.8 -#define IOREQ_TYPE_OR           3
    21.9 -#define IOREQ_TYPE_XOR          4
   21.10 -#define IOREQ_TYPE_XCHG         5
   21.11 -#define IOREQ_TYPE_ADD          6
   21.12  #define IOREQ_TYPE_TIMEOFFSET   7
   21.13  #define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
   21.14 -#define IOREQ_TYPE_SUB          9
   21.15  
   21.16  /*
   21.17   * VMExit dispatcher should cooperate with instruction decoder to