direct-io.hg

changeset 10704:3fa8b914e2b5

[HVM] Create I/O context for MMIO/PIO processing in an
off-stack structure.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Xin B Li <xin.b.li@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jul 14 13:59:15 2006 +0100 (2006-07-14)
parents fa143f374f3d
children 32dccb981757
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/platform.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/io.h xen/include/asm-x86/hvm/vcpu.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Fri Jul 14 13:53:59 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/io.c	Fri Jul 14 13:59:15 2006 +0100
     1.3 @@ -360,19 +360,19 @@ static inline void set_eflags_PF(int siz
     1.4  }
     1.5  
     1.6  static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     1.7 -                           struct mmio_op *mmio_opp)
     1.8 +                           struct hvm_io_op *pio_opp)
     1.9  {
    1.10      unsigned long old_eax;
    1.11      int sign = p->df ? -1 : 1;
    1.12  
    1.13 -    if ( p->pdata_valid || (mmio_opp->flags & OVERLAP) )
    1.14 +    if ( p->pdata_valid || (pio_opp->flags & OVERLAP) )
    1.15      {
    1.16 -        if ( mmio_opp->flags & REPZ )
    1.17 +        if ( pio_opp->flags & REPZ )
    1.18              regs->ecx -= p->count;
    1.19          if ( p->dir == IOREQ_READ )
    1.20          {
    1.21              regs->edi += sign * p->count * p->size;
    1.22 -            if ( mmio_opp->flags & OVERLAP )
    1.23 +            if ( pio_opp->flags & OVERLAP )
    1.24              {
    1.25                  unsigned long addr = regs->edi;
    1.26                  if (hvm_realmode(current))
    1.27 @@ -409,8 +409,8 @@ static void hvm_pio_assist(struct cpu_us
    1.28      }
    1.29  }
    1.30  
    1.31 -static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
    1.32 -                            ioreq_t *p, struct mmio_op *mmio_opp)
    1.33 +static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
    1.34 +                            struct hvm_io_op *mmio_opp)
    1.35  {
    1.36      int sign = p->df ? -1 : 1;
    1.37      int size = -1, index = -1;
    1.38 @@ -657,51 +657,51 @@ static void hvm_mmio_assist(struct vcpu 
    1.39          break;
    1.40  
    1.41      case INSTR_XCHG:
    1.42 -	if (src & REGISTER) {
    1.43 -		index = operand_index(src);
    1.44 -		set_reg_value(size, index, 0, regs, p->u.data);
    1.45 -	} else {
    1.46 -		index = operand_index(dst);
    1.47 -		set_reg_value(size, index, 0, regs, p->u.data);
    1.48 -	}
    1.49 -	break;
    1.50 +        if (src & REGISTER) {
    1.51 +            index = operand_index(src);
    1.52 +            set_reg_value(size, index, 0, regs, p->u.data);
    1.53 +        } else {
    1.54 +            index = operand_index(dst);
    1.55 +            set_reg_value(size, index, 0, regs, p->u.data);
    1.56 +        }
    1.57 +        break;
    1.58      }
    1.59 -
    1.60 -    hvm_load_cpu_guest_regs(v, regs);
    1.61  }
    1.62  
    1.63  void hvm_io_assist(struct vcpu *v)
    1.64  {
    1.65      vcpu_iodata_t *vio;
    1.66      ioreq_t *p;
    1.67 -    struct cpu_user_regs *regs = guest_cpu_user_regs();
    1.68 -    struct mmio_op *mmio_opp;
    1.69 -    struct cpu_user_regs *inst_decoder_regs;
    1.70 +    struct cpu_user_regs *regs;
    1.71 +    struct hvm_io_op *io_opp;
    1.72  
    1.73 -    mmio_opp = &v->arch.hvm_vcpu.mmio_op;
    1.74 -    inst_decoder_regs = mmio_opp->inst_decoder_regs;
    1.75 +    io_opp = &v->arch.hvm_vcpu.io_op;
    1.76 +    regs   = &io_opp->io_context;
    1.77  
    1.78      vio = get_vio(v->domain, v->vcpu_id);
    1.79  
    1.80 -    if (vio == 0) {
    1.81 -        HVM_DBG_LOG(DBG_LEVEL_1,
    1.82 -                    "bad shared page: %lx", (unsigned long) vio);
    1.83 -        printf("bad shared page: %lx\n", (unsigned long) vio);
    1.84 +    if ( vio == 0 ) {
    1.85 +        printf("bad shared page: %lx\n", (unsigned long)vio);
    1.86          domain_crash_synchronous();
    1.87      }
    1.88  
    1.89      p = &vio->vp_ioreq;
    1.90  
    1.91      /* clear IO wait HVM flag */
    1.92 -    if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
    1.93 -        if (p->state == STATE_IORESP_READY) {
    1.94 +    if ( test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) {
    1.95 +        if ( p->state == STATE_IORESP_READY ) {
    1.96              p->state = STATE_INVALID;
    1.97              clear_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
    1.98  
    1.99 -            if (p->type == IOREQ_TYPE_PIO)
   1.100 -                hvm_pio_assist(regs, p, mmio_opp);
   1.101 -            else
   1.102 -                hvm_mmio_assist(v, regs, p, mmio_opp);
   1.103 +            if ( p->type == IOREQ_TYPE_PIO )
   1.104 +                hvm_pio_assist(regs, p, io_opp);
   1.105 +            else {
   1.106 +                hvm_mmio_assist(regs, p, io_opp);
   1.107 +                hvm_load_cpu_guest_regs(v, regs);
   1.108 +            }
   1.109 +
   1.110 +            /* Copy register changes back into current guest state. */
   1.111 +            memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
   1.112          }
   1.113          /* else an interrupt send event raced us */
   1.114      }
     2.1 --- a/xen/arch/x86/hvm/platform.c	Fri Jul 14 13:53:59 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/platform.c	Fri Jul 14 13:59:15 2006 +0100
     2.3 @@ -729,7 +729,7 @@ void send_mmio_req(
     2.4      ioreq_t *p;
     2.5      struct cpu_user_regs *regs;
     2.6  
     2.7 -    regs = current->arch.hvm_vcpu.mmio_op.inst_decoder_regs;
     2.8 +    regs = &current->arch.hvm_vcpu.io_op.io_context;
     2.9  
    2.10      vio = get_vio(v->domain, v->vcpu_id);
    2.11      if (vio == NULL) {
    2.12 @@ -777,7 +777,7 @@ void send_mmio_req(
    2.13  }
    2.14  
    2.15  static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
    2.16 -                          struct mmio_op *mmio_opp, struct cpu_user_regs *regs)
    2.17 +                          struct hvm_io_op *mmio_opp, struct cpu_user_regs *regs)
    2.18  {
    2.19      unsigned long value = 0;
    2.20      int index, size_reg;
    2.21 @@ -815,16 +815,19 @@ static void mmio_operands(int type, unsi
    2.22  void handle_mmio(unsigned long va, unsigned long gpa)
    2.23  {
    2.24      unsigned long inst_addr;
    2.25 -    struct mmio_op *mmio_opp;
    2.26 +    struct hvm_io_op *mmio_opp;
    2.27      struct cpu_user_regs *regs;
    2.28      struct instruction mmio_inst;
    2.29      unsigned char inst[MAX_INST_LEN];
    2.30      int i, realmode, ret, inst_len;
    2.31      struct vcpu *v = current;
    2.32  
    2.33 -    mmio_opp = &v->arch.hvm_vcpu.mmio_op;
    2.34 +    mmio_opp = &v->arch.hvm_vcpu.io_op;
    2.35 +    regs = &mmio_opp->io_context;
    2.36  
    2.37 -    regs = mmio_opp->inst_decoder_regs;
    2.38 +    /* Copy current guest state into io instruction state structure. */
    2.39 +    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
    2.40 +
    2.41      hvm_store_cpu_guest_regs(v, regs, NULL);
    2.42  
    2.43      if ((inst_len = hvm_instruction_length(v)) <= 0) {
    2.44 @@ -1009,7 +1012,7 @@ void handle_mmio(unsigned long va, unsig
    2.45              unsigned long operand = mmio_inst.operand[0];
    2.46              value = get_reg_value(operand_size(operand),
    2.47                                    operand_index(operand), 0,
    2.48 -                                  mmio_opp->inst_decoder_regs);
    2.49 +                                  regs);
    2.50              /* send the request and wait for the value */
    2.51              send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.52                            mmio_inst.op_size, value, IOREQ_WRITE, 0);
    2.53 @@ -1019,7 +1022,7 @@ void handle_mmio(unsigned long va, unsig
    2.54              unsigned long operand = mmio_inst.operand[1];
    2.55              value = get_reg_value(operand_size(operand),
    2.56                                    operand_index(operand), 0,
    2.57 -                                  mmio_opp->inst_decoder_regs);
    2.58 +                                  regs);
    2.59              /* send the request and wait for the value */
    2.60              send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
    2.61                            mmio_inst.op_size, value, IOREQ_WRITE, 0);
     3.1 --- a/xen/arch/x86/hvm/svm/svm.c	Fri Jul 14 13:53:59 2006 +0100
     3.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Jul 14 13:59:15 2006 +0100
     3.3 @@ -1374,18 +1374,24 @@ static inline int svm_get_io_address(
     3.4  }
     3.5  
     3.6  
     3.7 -static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs) 
     3.8 +static void svm_io_instruction(struct vcpu *v)
     3.9  {
    3.10 -    struct mmio_op *mmio_opp;
    3.11 +    struct cpu_user_regs *regs;
    3.12 +    struct hvm_io_op *pio_opp;
    3.13      unsigned int port;
    3.14      unsigned int size, dir;
    3.15      ioio_info_t info;
    3.16      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    3.17  
    3.18      ASSERT(vmcb);
    3.19 -    mmio_opp = &current->arch.hvm_vcpu.mmio_op;
    3.20 -    mmio_opp->instr = INSTR_PIO;
    3.21 -    mmio_opp->flags = 0;
    3.22 +    pio_opp = &current->arch.hvm_vcpu.io_op;
    3.23 +    pio_opp->instr = INSTR_PIO;
    3.24 +    pio_opp->flags = 0;
    3.25 +
    3.26 +    regs = &pio_opp->io_context;
    3.27 +
    3.28 +    /* Copy current guest state into io instruction state structure. */
    3.29 +    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
    3.30  
    3.31      info.bytes = vmcb->exitinfo1;
    3.32  
    3.33 @@ -1421,7 +1427,7 @@ static void svm_io_instruction(struct vc
    3.34          /* "rep" prefix */
    3.35          if (info.fields.rep) 
    3.36          {
    3.37 -            mmio_opp->flags |= REPZ;
    3.38 +            pio_opp->flags |= REPZ;
    3.39          }
    3.40          else 
    3.41          {
    3.42 @@ -1436,7 +1442,7 @@ static void svm_io_instruction(struct vc
    3.43          {
    3.44              unsigned long value = 0;
    3.45  
    3.46 -            mmio_opp->flags |= OVERLAP;
    3.47 +            pio_opp->flags |= OVERLAP;
    3.48  
    3.49              if (dir == IOREQ_WRITE)
    3.50                  hvm_copy(&value, addr, size, HVM_COPY_IN);
    3.51 @@ -2785,9 +2791,6 @@ asmlinkage void svm_vmexit_handler(struc
    3.52                  (unsigned long)regs.ecx, (unsigned long)regs.edx,
    3.53                  (unsigned long)regs.esi, (unsigned long)regs.edi);
    3.54  
    3.55 -        v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
    3.56 -
    3.57 -//printk("PF1\n");
    3.58          if (!(error = svm_do_page_fault(va, &regs))) 
    3.59          {
    3.60              /* Inject #PG using Interruption-Information Fields */
    3.61 @@ -2936,7 +2939,7 @@ asmlinkage void svm_vmexit_handler(struc
    3.62          break;
    3.63  
    3.64      case VMEXIT_IOIO:
    3.65 -        svm_io_instruction(v, &regs);
    3.66 +        svm_io_instruction(v);
    3.67          break;
    3.68  
    3.69      case VMEXIT_MSR:
     4.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Fri Jul 14 13:53:59 2006 +0100
     4.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Jul 14 13:59:15 2006 +0100
     4.3 @@ -1056,17 +1056,23 @@ extern void send_pio_req(struct cpu_user
     4.4                           unsigned long count, int size, long value,
     4.5  			 int dir, int pvalid);
     4.6  
     4.7 -static void vmx_io_instruction(struct cpu_user_regs *regs,
     4.8 -                               unsigned long exit_qualification, unsigned long inst_len)
     4.9 +static void vmx_io_instruction(unsigned long exit_qualification,
    4.10 +                               unsigned long inst_len)
    4.11  {
    4.12 -    struct mmio_op *mmio_opp;
    4.13 +    struct cpu_user_regs *regs;
    4.14 +    struct hvm_io_op *pio_opp;
    4.15      unsigned long eip, cs, eflags;
    4.16      unsigned long port, size, dir;
    4.17      int vm86;
    4.18  
    4.19 -    mmio_opp = &current->arch.hvm_vcpu.mmio_op;
    4.20 -    mmio_opp->instr = INSTR_PIO;
    4.21 -    mmio_opp->flags = 0;
    4.22 +    pio_opp = &current->arch.hvm_vcpu.io_op;
    4.23 +    pio_opp->instr = INSTR_PIO;
    4.24 +    pio_opp->flags = 0;
    4.25 +
    4.26 +    regs = &pio_opp->io_context;
    4.27 +
    4.28 +    /* Copy current guest state into io instruction state structure. */
    4.29 +    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
    4.30  
    4.31      __vmread(GUEST_RIP, &eip);
    4.32      __vmread(GUEST_CS_SELECTOR, &cs);
    4.33 @@ -1100,7 +1106,7 @@ static void vmx_io_instruction(struct cp
    4.34              addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
    4.35  
    4.36          if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
    4.37 -            mmio_opp->flags |= REPZ;
    4.38 +            pio_opp->flags |= REPZ;
    4.39              count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
    4.40          }
    4.41  
    4.42 @@ -1111,7 +1117,7 @@ static void vmx_io_instruction(struct cp
    4.43          if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
    4.44              unsigned long value = 0;
    4.45  
    4.46 -            mmio_opp->flags |= OVERLAP;
    4.47 +            pio_opp->flags |= OVERLAP;
    4.48              if (dir == IOREQ_WRITE)
    4.49                  hvm_copy(&value, addr, size, HVM_COPY_IN);
    4.50              send_pio_req(regs, port, 1, size, value, dir, 0);
    4.51 @@ -2206,7 +2212,6 @@ asmlinkage void vmx_vmexit_handler(struc
    4.52                          (unsigned long)regs.eax, (unsigned long)regs.ebx,
    4.53                          (unsigned long)regs.ecx, (unsigned long)regs.edx,
    4.54                          (unsigned long)regs.esi, (unsigned long)regs.edi);
    4.55 -            v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
    4.56  
    4.57              if (!(error = vmx_do_page_fault(va, &regs))) {
    4.58                  /*
    4.59 @@ -2299,7 +2304,7 @@ asmlinkage void vmx_vmexit_handler(struc
    4.60      case EXIT_REASON_IO_INSTRUCTION:
    4.61          __vmread(EXIT_QUALIFICATION, &exit_qualification);
    4.62          __get_instruction_length(inst_len);
    4.63 -        vmx_io_instruction(&regs, exit_qualification, inst_len);
    4.64 +        vmx_io_instruction(exit_qualification, inst_len);
    4.65          TRACE_VMEXIT(4,exit_qualification);
    4.66          break;
    4.67      case EXIT_REASON_MSR_READ:
     5.1 --- a/xen/include/asm-x86/hvm/io.h	Fri Jul 14 13:53:59 2006 +0100
     5.2 +++ b/xen/include/asm-x86/hvm/io.h	Fri Jul 14 13:59:15 2006 +0100
     5.3 @@ -80,12 +80,12 @@ struct instruction {
     5.4  
     5.5  #define MAX_INST_LEN      15 /* Maximum instruction length = 15 bytes */
     5.6  
     5.7 -struct mmio_op {
     5.8 +struct hvm_io_op {
     5.9      int                    flags;
    5.10      int                    instr;       /* instruction */
    5.11      unsigned long          operand[2];  /* operands */
    5.12      unsigned long          immediate;   /* immediate portion */
    5.13 -    struct cpu_user_regs   *inst_decoder_regs; /* current context */
    5.14 +    struct cpu_user_regs   io_context;  /* current context */
    5.15  };
    5.16  
    5.17  #define MAX_IO_HANDLER              8
     6.1 --- a/xen/include/asm-x86/hvm/vcpu.h	Fri Jul 14 13:53:59 2006 +0100
     6.2 +++ b/xen/include/asm-x86/hvm/vcpu.h	Fri Jul 14 13:59:15 2006 +0100
     6.3 @@ -29,17 +29,17 @@
     6.4  #define HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI     1
     6.5  
     6.6  struct hvm_vcpu {
     6.7 -    unsigned long   ioflags;
     6.8 -    struct mmio_op  mmio_op;
     6.9 -    struct vlapic   *vlapic;
    6.10 -    s64             cache_tsc_offset;
    6.11 -    u64             guest_time;
    6.12 +    unsigned long       ioflags;
    6.13 +    struct hvm_io_op    io_op;
    6.14 +    struct vlapic       *vlapic;
    6.15 +    s64                 cache_tsc_offset;
    6.16 +    u64                 guest_time;
    6.17  
    6.18      /* For AP startup */
    6.19 -    unsigned long   init_sipi_sipi_state;
    6.20 +    unsigned long       init_sipi_sipi_state;
    6.21  
    6.22      /* Flags */
    6.23 -    int   flag_dr_dirty;
    6.24 +    int                 flag_dr_dirty;
    6.25  
    6.26      union {
    6.27          struct arch_vmx_struct vmx;
    6.28 @@ -47,7 +47,9 @@ struct hvm_vcpu {
    6.29      } u;
    6.30  };
    6.31  
    6.32 -#define ARCH_HVM_IO_WAIT   1       /* Waiting for I/O completion */
    6.33 +#define ARCH_HVM_IO_WAIT            1   /* Waiting for I/O completion */
    6.34 +
    6.35 +#define HVM_CONTEXT_STACK_BYTES     (offsetof(struct cpu_user_regs, error_code))
    6.36  
    6.37  #endif /* __ASM_X86_HVM_VCPU_H__ */
    6.38