direct-io.hg

changeset 15425:6e934c799051

vmx: Make use of VMX_INSTRUCTION_INFO field to obtain the segment
register of OUTS

Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Wed Jun 27 20:53:57 2007 +0100 (2007-06-27)
parents 87d34c8c2fe1
children 9590c9b48e07
files xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/vmx/vmcs.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Wed Jun 27 20:17:54 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Wed Jun 27 20:53:57 2007 +0100
     1.3 @@ -43,6 +43,7 @@ u32 vmx_cpu_based_exec_control __read_mo
     1.4  u32 vmx_secondary_exec_control __read_mostly;
     1.5  u32 vmx_vmexit_control __read_mostly;
     1.6  u32 vmx_vmentry_control __read_mostly;
     1.7 +bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly;
     1.8  
     1.9  static u32 vmcs_revision_id __read_mostly;
    1.10  
    1.11 @@ -133,6 +134,7 @@ void vmx_init_vmcs_config(void)
    1.12          vmx_secondary_exec_control = _vmx_secondary_exec_control;
    1.13          vmx_vmexit_control         = _vmx_vmexit_control;
    1.14          vmx_vmentry_control        = _vmx_vmentry_control;
    1.15 +        cpu_has_vmx_ins_outs_instr_info = !!(vmx_msr_high & (1U<<22));
    1.16      }
    1.17      else
    1.18      {
    1.19 @@ -142,6 +144,7 @@ void vmx_init_vmcs_config(void)
    1.20          BUG_ON(vmx_secondary_exec_control != _vmx_secondary_exec_control);
    1.21          BUG_ON(vmx_vmexit_control != _vmx_vmexit_control);
    1.22          BUG_ON(vmx_vmentry_control != _vmx_vmentry_control);
    1.23 +        BUG_ON(cpu_has_vmx_ins_outs_instr_info != !!(vmx_msr_high & (1U<<22)));
    1.24      }
    1.25  
    1.26      /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
     2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Jun 27 20:17:54 2007 +0100
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Jun 27 20:53:57 2007 +0100
     2.3 @@ -1466,16 +1466,34 @@ static void vmx_do_invlpg(unsigned long 
     2.4      paging_invlpg(v, va);
     2.5  }
     2.6  
     2.7 -/*
     2.8 - * get segment for string pio according to guest instruction
     2.9 - */
    2.10 -static void vmx_str_pio_get_segment(int long_mode, unsigned long eip,
    2.11 -                                   int inst_len, enum x86_segment *seg)
    2.12 +/* Get segment for OUTS according to guest instruction. */
    2.13 +static enum x86_segment vmx_outs_get_segment(
    2.14 +    int long_mode, unsigned long eip, int inst_len)
    2.15  {
    2.16      unsigned char inst[MAX_INST_LEN];
    2.17 +    enum x86_segment seg = x86_seg_ds;
    2.18      int i;
    2.19      extern int inst_copy_from_guest(unsigned char *, unsigned long, int);
    2.20  
    2.21 +    if ( likely(cpu_has_vmx_ins_outs_instr_info) )
    2.22 +    {
    2.23 +        unsigned int instr_info = __vmread(VMX_INSTRUCTION_INFO);
    2.24 +
    2.25 +        /* Get segment register according to bits 17:15. */
    2.26 +        switch ( (instr_info >> 15) & 7 )
    2.27 +        {
    2.28 +        case 0: seg = x86_seg_es; break;
    2.29 +        case 1: seg = x86_seg_cs; break;
    2.30 +        case 2: seg = x86_seg_ss; break;
    2.31 +        case 3: seg = x86_seg_ds; break;
    2.32 +        case 4: seg = x86_seg_fs; break;
    2.33 +        case 5: seg = x86_seg_gs; break;
    2.34 +        default: BUG();
    2.35 +        }
    2.36 +
    2.37 +        goto out;
    2.38 +    }
    2.39 +
    2.40      if ( !long_mode )
    2.41          eip += __vmread(GUEST_CS_BASE);
    2.42  
    2.43 @@ -1484,7 +1502,7 @@ static void vmx_str_pio_get_segment(int 
    2.44      {
    2.45          gdprintk(XENLOG_ERR, "Get guest instruction failed\n");
    2.46          domain_crash(current->domain);
    2.47 -        return;
    2.48 +        goto out;
    2.49      }
    2.50  
    2.51      for ( i = 0; i < inst_len; i++ )
    2.52 @@ -1501,25 +1519,28 @@ static void vmx_str_pio_get_segment(int 
    2.53  #endif
    2.54              continue;
    2.55          case 0x2e: /* CS */
    2.56 -            *seg = x86_seg_cs;
    2.57 +            seg = x86_seg_cs;
    2.58              continue;
    2.59          case 0x36: /* SS */
    2.60 -            *seg = x86_seg_ss;
    2.61 +            seg = x86_seg_ss;
    2.62              continue;
    2.63          case 0x26: /* ES */
    2.64 -            *seg = x86_seg_es;
    2.65 +            seg = x86_seg_es;
    2.66              continue;
    2.67          case 0x64: /* FS */
    2.68 -            *seg = x86_seg_fs;
    2.69 +            seg = x86_seg_fs;
    2.70              continue;
    2.71          case 0x65: /* GS */
    2.72 -            *seg = x86_seg_gs;
    2.73 +            seg = x86_seg_gs;
    2.74              continue;
    2.75          case 0x3e: /* DS */
    2.76 -            *seg = x86_seg_ds;
    2.77 +            seg = x86_seg_ds;
    2.78              continue;
    2.79          }
    2.80      }
    2.81 +
    2.82 + out:
    2.83 +    return seg;
    2.84  }
    2.85  
    2.86  static int vmx_str_pio_check_descriptor(int long_mode, unsigned long eip,
    2.87 @@ -1532,7 +1553,7 @@ static int vmx_str_pio_check_descriptor(
    2.88      *base = 0;
    2.89      *limit = 0;
    2.90      if ( seg != x86_seg_es )
    2.91 -        vmx_str_pio_get_segment(long_mode, eip, inst_len, &seg);
    2.92 +        seg = vmx_outs_get_segment(long_mode, eip, inst_len);
    2.93  
    2.94      switch ( seg )
    2.95      {
    2.96 @@ -1578,7 +1599,7 @@ static int vmx_str_pio_check_descriptor(
    2.97      }
    2.98      *ar_bytes = __vmread(ar_field);
    2.99  
   2.100 -    return !(*ar_bytes & 0x10000);
   2.101 +    return !(*ar_bytes & X86_SEG_AR_SEG_UNUSABLE);
   2.102  }
   2.103  
   2.104  
     3.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Wed Jun 27 20:17:54 2007 +0100
     3.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Wed Jun 27 20:53:57 2007 +0100
     3.3 @@ -131,6 +131,8 @@ extern u32 vmx_vmentry_control;
     3.4  #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
     3.5  extern u32 vmx_secondary_exec_control;
     3.6  
     3.7 +extern bool_t cpu_has_vmx_ins_outs_instr_info;
     3.8 +
     3.9  #define cpu_has_vmx_virtualize_apic_accesses \
    3.10      (vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
    3.11  #define cpu_has_vmx_tpr_shadow \