ia64/xen-unstable

changeset 16459:368bcf480772

vmx realmode: Plumb through I/O port accesses in emulated realmode.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Nov 25 11:43:53 2007 +0000 (2007-11-25)
parents ce3e5e859d66
children a194083696d5
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/vmx/realmode.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/x86_emulate.c xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Sun Nov 25 09:23:02 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/io.c	Sun Nov 25 11:43:53 2007 +0000
     1.3 @@ -841,13 +841,17 @@ void hvm_io_assist(void)
     1.4      if ( p->state != STATE_IORESP_READY )
     1.5      {
     1.6          gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
     1.7 -        domain_crash_synchronous();
     1.8 +        domain_crash(v->domain);
     1.9 +        goto out;
    1.10      }
    1.11  
    1.12      rmb(); /* see IORESP_READY /then/ read contents of ioreq */
    1.13  
    1.14      p->state = STATE_IOREQ_NONE;
    1.15  
    1.16 +    if ( v->arch.hvm_vcpu.io_complete && v->arch.hvm_vcpu.io_complete() )
    1.17 +        goto out;
    1.18 +
    1.19      switch ( p->type )
    1.20      {
    1.21      case IOREQ_TYPE_INVALIDATE:
     2.1 --- a/xen/arch/x86/hvm/vmx/realmode.c	Sun Nov 25 09:23:02 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/realmode.c	Sun Nov 25 11:43:53 2007 +0000
     2.3 @@ -178,7 +178,24 @@ realmode_read_io(
     2.4      unsigned long *val,
     2.5      struct x86_emulate_ctxt *ctxt)
     2.6  {
     2.7 -    return X86EMUL_UNHANDLEABLE;
     2.8 +    struct vcpu *curr = current;
     2.9 +
    2.10 +    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.11 +        return X86EMUL_UNHANDLEABLE;
    2.12 +
    2.13 +    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
    2.14 +    {
    2.15 +        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
    2.16 +        send_pio_req(port, 1, bytes, 0, IOREQ_READ, 0, 0);
    2.17 +    }
    2.18 +
    2.19 +    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
    2.20 +        return X86EMUL_UNHANDLEABLE;
    2.21 +    
    2.22 +    *val = curr->arch.hvm_vmx.real_mode_io_data;
    2.23 +    curr->arch.hvm_vmx.real_mode_io_completed = 0;
    2.24 +
    2.25 +    return X86EMUL_OKAY;
    2.26  }
    2.27  
    2.28  static int realmode_write_io(
    2.29 @@ -187,7 +204,15 @@ static int realmode_write_io(
    2.30      unsigned long val,
    2.31      struct x86_emulate_ctxt *ctxt)
    2.32  {
    2.33 -    return X86EMUL_UNHANDLEABLE;
    2.34 +    struct vcpu *curr = current;
    2.35 +
    2.36 +    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.37 +        return X86EMUL_UNHANDLEABLE;
    2.38 +
    2.39 +    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
    2.40 +    send_pio_req(port, 1, bytes, val, IOREQ_WRITE, 0, 0);
    2.41 +
    2.42 +    return X86EMUL_OKAY;
    2.43  }
    2.44  
    2.45  static int
    2.46 @@ -259,8 +284,19 @@ int vmx_realmode(struct cpu_user_regs *r
    2.47                   rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3],
    2.48                   rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]);
    2.49  
    2.50 -        if ( x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops) )
    2.51 -        {            
    2.52 +        rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
    2.53 +
    2.54 +        if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.55 +        {
    2.56 +            ioreq_t *p = &get_ioreq(curr)->vp_ioreq;
    2.57 +            gdprintk(XENLOG_DEBUG, "RM I/O %d %c addr=%lx data=%lx\n",
    2.58 +                     p->type, p->dir ? 'R' : 'W', p->addr, p->data);
    2.59 +            rc = 0;
    2.60 +            break;
    2.61 +        }
    2.62 +
    2.63 +        if ( rc )
    2.64 +        {
    2.65              gdprintk(XENLOG_ERR, "Emulation failed\n");
    2.66              rc = -EINVAL;
    2.67              break;
    2.68 @@ -272,3 +308,21 @@ int vmx_realmode(struct cpu_user_regs *r
    2.69  
    2.70      return rc;
    2.71  }
    2.72 +
    2.73 +int vmx_realmode_io_complete(void)
    2.74 +{
    2.75 +    struct vcpu *curr = current;
    2.76 +    ioreq_t *p = &get_ioreq(curr)->vp_ioreq;
    2.77 +
    2.78 +    if ( !curr->arch.hvm_vmx.real_mode_io_in_progress )
    2.79 +        return 0;
    2.80 +
    2.81 +    curr->arch.hvm_vmx.real_mode_io_in_progress = 0;
    2.82 +    if ( p->dir == IOREQ_READ )
    2.83 +    {
    2.84 +        curr->arch.hvm_vmx.real_mode_io_completed = 1;
    2.85 +        curr->arch.hvm_vmx.real_mode_io_data = p->data;
    2.86 +    }
    2.87 +
    2.88 +    return 1;
    2.89 +}
     3.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Sun Nov 25 09:23:02 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Sun Nov 25 11:43:53 2007 +0000
     3.3 @@ -95,6 +95,7 @@ static int vmx_vcpu_initialise(struct vc
     3.4  #ifndef VMXASSIST
     3.5      if ( v->vcpu_id == 0 )
     3.6          v->arch.guest_context.user_regs.eax = 1;
     3.7 +    v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete;
     3.8  #endif
     3.9  
    3.10      return 0;
     4.1 --- a/xen/arch/x86/x86_emulate.c	Sun Nov 25 09:23:02 2007 +0000
     4.2 +++ b/xen/arch/x86/x86_emulate.c	Sun Nov 25 11:43:53 2007 +0000
     4.3 @@ -264,6 +264,7 @@ struct operand {
     4.4  };
     4.5  
     4.6  /* EFLAGS bit definitions. */
     4.7 +#define EFLG_VM (1<<17)
     4.8  #define EFLG_RF (1<<16)
     4.9  #define EFLG_OF (1<<11)
    4.10  #define EFLG_DF (1<<10)
    4.11 @@ -478,10 +479,6 @@ do {                                    
    4.12  /* In future we will be able to generate arbitrary exceptions. */
    4.13  #define generate_exception_if(p, e) fail_if(p)
    4.14  
    4.15 -/* To be done... */
    4.16 -#define mode_ring0() (0)
    4.17 -#define mode_iopl()  (0)
    4.18 -
    4.19  /* Given byte has even parity (even number of 1s)? */
    4.20  static int even_parity(uint8_t v)
    4.21  {
    4.22 @@ -680,6 +677,35 @@ test_cc(
    4.23  }
    4.24  
    4.25  static int
    4.26 +get_cpl(
    4.27 +    struct x86_emulate_ctxt *ctxt,
    4.28 +    struct x86_emulate_ops  *ops)
    4.29 +{
    4.30 +    struct segment_register reg;
    4.31 +
    4.32 +    if ( ctxt->regs->eflags & EFLG_VM )
    4.33 +        return 3;
    4.34 +
    4.35 +    if ( (ops->read_segment == NULL) ||
    4.36 +         ops->read_segment(x86_seg_ss, &reg, ctxt) )
    4.37 +        return -1;
    4.38 +
    4.39 +    return reg.attr.fields.dpl;
    4.40 +}
    4.41 +
    4.42 +static int
    4.43 +_mode_iopl(
    4.44 +    struct x86_emulate_ctxt *ctxt,
    4.45 +    struct x86_emulate_ops  *ops)
    4.46 +{
    4.47 +    int cpl = get_cpl(ctxt, ops);
    4.48 +    return ((cpl >= 0) && (cpl <= ((ctxt->regs->eflags >> 12) & 3)));
    4.49 +}
    4.50 +
    4.51 +#define mode_ring0() (get_cpl(ctxt, ops) == 0)
    4.52 +#define mode_iopl()  _mode_iopl(ctxt, ops)
    4.53 +
    4.54 +static int
    4.55  in_realmode(
    4.56      struct x86_emulate_ctxt *ctxt,
    4.57      struct x86_emulate_ops  *ops)
     5.1 --- a/xen/include/asm-x86/hvm/vcpu.h	Sun Nov 25 09:23:02 2007 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/vcpu.h	Sun Nov 25 11:43:53 2007 +0000
     5.3 @@ -59,6 +59,9 @@ struct hvm_vcpu {
     5.4      bool_t              flag_dr_dirty;
     5.5      bool_t              debug_state_latch;
     5.6  
     5.7 +    /* Callback function for I/O completion. */
     5.8 +    int                 (*io_complete)(void);
     5.9 +
    5.10      union {
    5.11          struct arch_vmx_struct vmx;
    5.12          struct arch_svm_struct svm;
     6.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Sun Nov 25 09:23:02 2007 +0000
     6.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Sun Nov 25 11:43:53 2007 +0000
     6.3 @@ -92,6 +92,10 @@ struct arch_vmx_struct {
     6.4      unsigned long        vmxassist_enabled:1;
     6.5      unsigned long        irqbase_mode:1;
     6.6      unsigned char        pm_irqbase[2];
     6.7 +#else
     6.8 +    bool_t               real_mode_io_in_progress;
     6.9 +    bool_t               real_mode_io_completed;
    6.10 +    unsigned long        real_mode_io_data;
    6.11  #endif
    6.12  };
    6.13  
     7.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Sun Nov 25 09:23:02 2007 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Sun Nov 25 11:43:53 2007 +0000
     7.3 @@ -34,6 +34,7 @@ void vmx_do_resume(struct vcpu *);
     7.4  void set_guest_time(struct vcpu *v, u64 gtime);
     7.5  void vmx_vlapic_msr_changed(struct vcpu *v);
     7.6  int vmx_realmode(struct cpu_user_regs *regs);
     7.7 +int vmx_realmode_io_complete(void);
     7.8  
     7.9  /*
    7.10   * Exit Reasons