ia64/xen-unstable

changeset 12504:6a26f49d3b16

HVM cleanups:
1) make vmx/svm time functions hvm common, since they are actually the same.
2) move hvm_send_assist_req from platform.c to hvm.c.
2) rename VMX MSR context switch functions to make them more readable.
3) misc coding style clean ups.

Signed-off-by: Xin Li <xin.b.li@intel.com>
author kfraser@localhost.localdomain
date Fri Nov 17 10:29:08 2006 +0000 (2006-11-17)
parents d19b8542865b
children 51edd3c6a4d8
files xen/arch/x86/hvm/hvm.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/hvm.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/hvm.c	Fri Nov 17 10:24:22 2006 +0000
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Nov 17 10:29:08 2006 +0000
     1.3 @@ -74,6 +74,30 @@ void hvm_set_guest_time(struct vcpu *v, 
     1.4      hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
     1.5  }
     1.6  
     1.7 +u64 hvm_get_guest_time(struct vcpu *v)
     1.8 +{
     1.9 +    u64    host_tsc;
    1.10 +
    1.11 +    rdtscll(host_tsc);
    1.12 +    return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset;
    1.13 +}
    1.14 +
    1.15 +void hvm_freeze_time(struct vcpu *v)
    1.16 +{
    1.17 +    struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
    1.18 +
    1.19 +    if ( pt->enabled && pt->first_injected
    1.20 +            && (v->vcpu_id == pt->bind_vcpu)
    1.21 +            && !v->arch.hvm_vcpu.guest_time ) {
    1.22 +        v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    1.23 +        if ( !test_bit(_VCPUF_blocked, &v->vcpu_flags) )
    1.24 +        {
    1.25 +            stop_timer(&pt->timer);
    1.26 +            rtc_freeze(v);
    1.27 +        }
    1.28 +    }
    1.29 +}
    1.30 +
    1.31  void hvm_migrate_timers(struct vcpu *v)
    1.32  {
    1.33      struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
    1.34 @@ -203,7 +227,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
    1.35                 pt_timer_fn, v, v->processor);
    1.36      pit_init(v, cpu_khz);
    1.37      rtc_init(v, RTC_PORT(0), RTC_IRQ);
    1.38 -    pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); 
    1.39 +    pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
    1.40  
    1.41      /* Init guest TSC to start from zero. */
    1.42      hvm_set_guest_time(v, 0);
    1.43 @@ -226,14 +250,6 @@ void pic_irq_request(void *data, int lev
    1.44      *interrupt_request = level;
    1.45  }
    1.46  
    1.47 -u64 hvm_get_guest_time(struct vcpu *v)
    1.48 -{
    1.49 -    u64    host_tsc;
    1.50 -    
    1.51 -    rdtscll(host_tsc);
    1.52 -    return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset;
    1.53 -}
    1.54 -
    1.55  int cpu_get_interrupt(struct vcpu *v, int *type)
    1.56  {
    1.57      int intno;
    1.58 @@ -284,6 +300,28 @@ static void hvm_vcpu_down(void)
    1.59      }
    1.60  }
    1.61  
    1.62 +void hvm_send_assist_req(struct vcpu *v)
    1.63 +{
    1.64 +    ioreq_t *p;
    1.65 +
    1.66 +    p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
    1.67 +    if ( unlikely(p->state != STATE_IOREQ_NONE) )
    1.68 +    {
    1.69 +        /* This indicates a bug in the device model.  Crash the domain. */
    1.70 +        gdprintk(XENLOG_ERR, "Device model set bad IO state %d.\n", p->state);
    1.71 +        domain_crash_synchronous();
    1.72 +    }
    1.73 +
    1.74 +    prepare_wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port);
    1.75 +
    1.76 +    /*
    1.77 +     * Following happens /after/ blocking and setting up ioreq contents.
    1.78 +     * prepare_wait_on_xen_event_channel() is an implicit barrier.
    1.79 +     */
    1.80 +    p->state = STATE_IOREQ_READY;
    1.81 +    notify_via_xen_event_channel(v->arch.hvm_vcpu.xen_port);
    1.82 +}
    1.83 +
    1.84  void hvm_hlt(unsigned long rflags)
    1.85  {
    1.86      /*
     2.1 --- a/xen/arch/x86/hvm/platform.c	Fri Nov 17 10:24:22 2006 +0000
     2.2 +++ b/xen/arch/x86/hvm/platform.c	Fri Nov 17 10:29:08 2006 +0000
     2.3 @@ -346,7 +346,7 @@ static int reg_mem(unsigned char size, u
     2.4      return DECODE_success;
     2.5  }
     2.6  
     2.7 -static int hvm_decode(int realmode, unsigned char *opcode,
     2.8 +static int mmio_decode(int realmode, unsigned char *opcode,
     2.9                        struct hvm_io_op *mmio_op, unsigned char *op_size)
    2.10  {
    2.11      unsigned char size_reg = 0;
    2.12 @@ -722,28 +722,6 @@ int inst_copy_from_guest(unsigned char *
    2.13      return inst_len;
    2.14  }
    2.15  
    2.16 -static void hvm_send_assist_req(struct vcpu *v)
    2.17 -{
    2.18 -    ioreq_t *p;
    2.19 -
    2.20 -    p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
    2.21 -    if ( unlikely(p->state != STATE_IOREQ_NONE) )
    2.22 -    {
    2.23 -        /* This indicates a bug in the device model.  Crash the domain. */
    2.24 -        gdprintk(XENLOG_ERR, "Device model set bad IO state %d.\n", p->state);
    2.25 -        domain_crash_synchronous();
    2.26 -    }
    2.27 -
    2.28 -    prepare_wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port);
    2.29 -
    2.30 -    /*
    2.31 -     * Following happens /after/ blocking and setting up ioreq contents.
    2.32 -     * prepare_wait_on_xen_event_channel() is an implicit barrier.
    2.33 -     */
    2.34 -    p->state = STATE_IOREQ_READY;
    2.35 -    notify_via_xen_event_channel(v->arch.hvm_vcpu.xen_port);
    2.36 -}
    2.37 -
    2.38  void send_pio_req(unsigned long port, unsigned long count, int size,
    2.39                    long value, int dir, int df, int value_is_ptr)
    2.40  {
    2.41 @@ -927,7 +905,7 @@ void handle_mmio(unsigned long gpa)
    2.42          domain_crash_synchronous();
    2.43      }
    2.44  
    2.45 -    if ( hvm_decode(realmode, inst, mmio_op, &op_size) == DECODE_failure ) {
    2.46 +    if ( mmio_decode(realmode, inst, mmio_op, &op_size) == DECODE_failure ) {
    2.47          printk("handle_mmio: failed to decode instruction\n");
    2.48          printk("mmio opcode: gpa 0x%lx, len %d:", gpa, inst_len);
    2.49          for ( i = 0; i < inst_len; i++ )
     3.1 --- a/xen/arch/x86/hvm/svm/svm.c	Fri Nov 17 10:24:22 2006 +0000
     3.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Nov 17 10:29:08 2006 +0000
     3.3 @@ -714,26 +714,9 @@ static void arch_svm_do_launch(struct vc
     3.4      reset_stack_and_jump(svm_asm_do_launch);
     3.5  }
     3.6  
     3.7 -static void svm_freeze_time(struct vcpu *v)
     3.8 -{
     3.9 -    struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
    3.10 -
    3.11 -    if ( pt->enabled && pt->first_injected
    3.12 -            && (v->vcpu_id == pt->bind_vcpu)
    3.13 -            && !v->arch.hvm_vcpu.guest_time ) {
    3.14 -        v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    3.15 -        if ( test_bit(_VCPUF_blocked, &v->vcpu_flags) )
    3.16 -        {
    3.17 -            stop_timer(&pt->timer);
    3.18 -            rtc_freeze(v);
    3.19 -        }
    3.20 -    }
    3.21 -}
    3.22 -
    3.23 -
    3.24  static void svm_ctxt_switch_from(struct vcpu *v)
    3.25  {
    3.26 -    svm_freeze_time(v);
    3.27 +    hvm_freeze_time(v);
    3.28      svm_save_dr(v);
    3.29  }
    3.30  
    3.31 @@ -852,7 +835,6 @@ int start_svm(void)
    3.32      return 1;
    3.33  }
    3.34  
    3.35 -
    3.36  void arch_svm_do_resume(struct vcpu *v) 
    3.37  {
    3.38      /* pinning VCPU to a different core? */
    3.39 @@ -871,8 +853,6 @@ void arch_svm_do_resume(struct vcpu *v)
    3.40      }
    3.41  }
    3.42  
    3.43 -
    3.44 -
    3.45  static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) 
    3.46  {
    3.47      struct vcpu *v = current;
     4.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Fri Nov 17 10:24:22 2006 +0000
     4.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Nov 17 10:29:08 2006 +0000
     4.3 @@ -78,75 +78,48 @@ static void vmx_vcpu_destroy(struct vcpu
     4.4  
     4.5  #ifdef __x86_64__
     4.6  
     4.7 -static DEFINE_PER_CPU(struct vmx_msr_state, percpu_msr);
     4.8 +static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state);
     4.9  
    4.10 -static u32 msr_data_index[VMX_MSR_COUNT] =
    4.11 +static u32 msr_index[VMX_MSR_COUNT] =
    4.12  {
    4.13      MSR_LSTAR, MSR_STAR, MSR_CSTAR,
    4.14      MSR_SYSCALL_MASK, MSR_EFER,
    4.15  };
    4.16  
    4.17 -static void vmx_save_segments(struct vcpu *v)
    4.18 -{
    4.19 -    rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_content.shadow_gs);
    4.20 -}
    4.21 -
    4.22 -/*
    4.23 - * To avoid MSR save/restore at every VM exit/entry time, we restore
    4.24 - * the x86_64 specific MSRs at domain switch time. Since those MSRs are
    4.25 - * are not modified once set for generic domains, we don't save them,
    4.26 - * but simply reset them to the values set at percpu_traps_init().
    4.27 - */
    4.28 -static void vmx_load_msrs(void)
    4.29 +static void vmx_save_host_msrs(void)
    4.30  {
    4.31 -    struct vmx_msr_state *host_state = &this_cpu(percpu_msr);
    4.32 -    int i;
    4.33 -
    4.34 -    while ( host_state->flags )
    4.35 -    {
    4.36 -        i = find_first_set_bit(host_state->flags);
    4.37 -        wrmsrl(msr_data_index[i], host_state->msr_items[i]);
    4.38 -        clear_bit(i, &host_state->flags);
    4.39 -    }
    4.40 -}
    4.41 -
    4.42 -static void vmx_save_init_msrs(void)
    4.43 -{
    4.44 -    struct vmx_msr_state *host_state = &this_cpu(percpu_msr);
    4.45 +    struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
    4.46      int i;
    4.47  
    4.48      for ( i = 0; i < VMX_MSR_COUNT; i++ )
    4.49 -        rdmsrl(msr_data_index[i], host_state->msr_items[i]);
    4.50 +        rdmsrl(msr_index[i], host_msr_state->msrs[i]);
    4.51  }
    4.52  
    4.53 -#define CASE_READ_MSR(address)              \
    4.54 -    case MSR_ ## address:                 \
    4.55 -    msr_content = msr->msr_items[VMX_INDEX_MSR_ ## address]; \
    4.56 -    break
    4.57 +#define CASE_READ_MSR(address)                                              \
    4.58 +    case MSR_ ## address:                                                   \
    4.59 +        msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_ ## address];     \
    4.60 +        break
    4.61  
    4.62 -#define CASE_WRITE_MSR(address)                                     \
    4.63 -    case MSR_ ## address:                                           \
    4.64 -    {                                                               \
    4.65 -        msr->msr_items[VMX_INDEX_MSR_ ## address] = msr_content;    \
    4.66 -        if (!test_bit(VMX_INDEX_MSR_ ## address, &msr->flags)) {    \
    4.67 -            set_bit(VMX_INDEX_MSR_ ## address, &msr->flags);        \
    4.68 -        }                                                           \
    4.69 -        wrmsrl(MSR_ ## address, msr_content);                       \
    4.70 -        set_bit(VMX_INDEX_MSR_ ## address, &host_state->flags);     \
    4.71 -    }                                                               \
    4.72 -    break
    4.73 +#define CASE_WRITE_MSR(address)                                             \
    4.74 +    case MSR_ ## address:                                                   \
    4.75 +        guest_msr_state->msrs[VMX_INDEX_MSR_ ## address] = msr_content;     \
    4.76 +        if ( !test_bit(VMX_INDEX_MSR_ ## address, &guest_msr_state->flags) )\
    4.77 +            set_bit(VMX_INDEX_MSR_ ## address, &guest_msr_state->flags);    \
    4.78 +        wrmsrl(MSR_ ## address, msr_content);                               \
    4.79 +        set_bit(VMX_INDEX_MSR_ ## address, &host_msr_state->flags);         \
    4.80 +        break
    4.81  
    4.82  #define IS_CANO_ADDRESS(add) 1
    4.83  static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
    4.84  {
    4.85      u64 msr_content = 0;
    4.86      struct vcpu *v = current;
    4.87 -    struct vmx_msr_state *msr = &v->arch.hvm_vmx.msr_content;
    4.88 +    struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
    4.89  
    4.90      switch ( regs->ecx ) {
    4.91      case MSR_EFER:
    4.92          HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content 0x%"PRIx64, msr_content);
    4.93 -        msr_content = msr->msr_items[VMX_INDEX_MSR_EFER];
    4.94 +        msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_EFER];
    4.95          break;
    4.96  
    4.97      case MSR_FS_BASE:
    4.98 @@ -164,7 +137,7 @@ static inline int long_mode_do_msr_read(
    4.99          break;
   4.100  
   4.101      case MSR_SHADOW_GS_BASE:
   4.102 -        msr_content = msr->shadow_gs;
   4.103 +        msr_content = guest_msr_state->shadow_gs;
   4.104          break;
   4.105  
   4.106      CASE_READ_MSR(STAR);
   4.107 @@ -193,8 +166,8 @@ static inline int long_mode_do_msr_write
   4.108  {
   4.109      u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
   4.110      struct vcpu *v = current;
   4.111 -    struct vmx_msr_state *msr = &v->arch.hvm_vmx.msr_content;
   4.112 -    struct vmx_msr_state *host_state = &this_cpu(percpu_msr);
   4.113 +    struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
   4.114 +    struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
   4.115  
   4.116      HVM_DBG_LOG(DBG_LEVEL_1, "msr 0x%lx msr_content 0x%"PRIx64"\n",
   4.117                  (unsigned long)regs->ecx, msr_content);
   4.118 @@ -211,7 +184,7 @@ static inline int long_mode_do_msr_write
   4.119          }
   4.120  
   4.121          if ( (msr_content & EFER_LME)
   4.122 -             &&  !(msr->msr_items[VMX_INDEX_MSR_EFER] & EFER_LME) )
   4.123 +             &&  !(guest_msr_state->msrs[VMX_INDEX_MSR_EFER] & EFER_LME) )
   4.124          {
   4.125              if ( unlikely(vmx_paging_enabled(v)) )
   4.126              {
   4.127 @@ -221,7 +194,7 @@ static inline int long_mode_do_msr_write
   4.128              }
   4.129          }
   4.130          else if ( !(msr_content & EFER_LME)
   4.131 -                  && (msr->msr_items[VMX_INDEX_MSR_EFER] & EFER_LME) )
   4.132 +                  && (guest_msr_state->msrs[VMX_INDEX_MSR_EFER] & EFER_LME) )
   4.133          {
   4.134              if ( unlikely(vmx_paging_enabled(v)) )
   4.135              {
   4.136 @@ -231,12 +204,12 @@ static inline int long_mode_do_msr_write
   4.137              }
   4.138          }
   4.139  
   4.140 -        msr->msr_items[VMX_INDEX_MSR_EFER] = msr_content;
   4.141 +        guest_msr_state->msrs[VMX_INDEX_MSR_EFER] = msr_content;
   4.142          break;
   4.143  
   4.144      case MSR_FS_BASE:
   4.145      case MSR_GS_BASE:
   4.146 -        if ( !(vmx_long_mode_enabled(v)) )
   4.147 +        if ( !vmx_long_mode_enabled(v) )
   4.148              goto exit_and_crash;
   4.149  
   4.150          if ( !IS_CANO_ADDRESS(msr_content) )
   4.151 @@ -257,7 +230,7 @@ static inline int long_mode_do_msr_write
   4.152          if ( !(vmx_long_mode_enabled(v)) )
   4.153              goto exit_and_crash;
   4.154  
   4.155 -        v->arch.hvm_vmx.msr_content.shadow_gs = msr_content;
   4.156 +        v->arch.hvm_vmx.msr_state.shadow_gs = msr_content;
   4.157          wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
   4.158          break;
   4.159  
   4.160 @@ -278,40 +251,57 @@ static inline int long_mode_do_msr_write
   4.161      return 1; /* handled */
   4.162  }
   4.163  
   4.164 -static void vmx_restore_msrs(struct vcpu *v)
   4.165 +/*
   4.166 + * To avoid MSR save/restore at every VM exit/entry time, we restore
   4.167 + * the x86_64 specific MSRs at domain switch time. Since these MSRs
   4.168 + * are not modified once set for para domains, we don't save them,
   4.169 + * but simply reset them to values set in percpu_traps_init().
   4.170 + */
   4.171 +static void vmx_restore_host_msrs(void)
   4.172  {
   4.173 -    int i = 0;
   4.174 -    struct vmx_msr_state *guest_state;
   4.175 -    struct vmx_msr_state *host_state;
   4.176 -    unsigned long guest_flags ;
   4.177 +    struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
   4.178 +    int i;
   4.179  
   4.180 -    guest_state = &v->arch.hvm_vmx.msr_content;;
   4.181 -    host_state = &this_cpu(percpu_msr);
   4.182 +    while ( host_msr_state->flags )
   4.183 +    {
   4.184 +        i = find_first_set_bit(host_msr_state->flags);
   4.185 +        wrmsrl(msr_index[i], host_msr_state->msrs[i]);
   4.186 +        clear_bit(i, &host_msr_state->flags);
   4.187 +    }
   4.188 +}
   4.189  
   4.190 -    wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
   4.191 -    guest_flags = guest_state->flags;
   4.192 -    if (!guest_flags)
   4.193 +static void vmx_restore_guest_msrs(struct vcpu *v)
   4.194 +{
   4.195 +    struct vmx_msr_state *guest_msr_state, *host_msr_state;
   4.196 +    unsigned long guest_flags;
   4.197 +    int i;
   4.198 +
   4.199 +    guest_msr_state = &v->arch.hvm_vmx.msr_state;
   4.200 +    host_msr_state = &this_cpu(host_msr_state);
   4.201 +
   4.202 +    wrmsrl(MSR_SHADOW_GS_BASE, guest_msr_state->shadow_gs);
   4.203 +
   4.204 +    guest_flags = guest_msr_state->flags;
   4.205 +    if ( !guest_flags )
   4.206          return;
   4.207  
   4.208 -    while (guest_flags){
   4.209 +    while ( guest_flags ) {
   4.210          i = find_first_set_bit(guest_flags);
   4.211  
   4.212          HVM_DBG_LOG(DBG_LEVEL_2,
   4.213 -                    "restore guest's index %d msr %lx with %lx\n",
   4.214 -                    i, (unsigned long)msr_data_index[i],
   4.215 -                    (unsigned long)guest_state->msr_items[i]);
   4.216 -        set_bit(i, &host_state->flags);
   4.217 -        wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
   4.218 +                    "restore guest's index %d msr %x with value %lx",
   4.219 +                    i, msr_index[i], guest_msr_state->msrs[i]);
   4.220 +        set_bit(i, &host_msr_state->flags);
   4.221 +        wrmsrl(msr_index[i], guest_msr_state->msrs[i]);
   4.222          clear_bit(i, &guest_flags);
   4.223      }
   4.224  }
   4.225  
   4.226  #else  /* __i386__ */
   4.227  
   4.228 -#define vmx_save_segments(v)      ((void)0)
   4.229 -#define vmx_load_msrs()           ((void)0)
   4.230 -#define vmx_restore_msrs(v)       ((void)0)
   4.231 -#define vmx_save_init_msrs()      ((void)0)
   4.232 +#define vmx_save_host_msrs()        ((void)0)
   4.233 +#define vmx_restore_host_msrs()     ((void)0)
   4.234 +#define vmx_restore_guest_msrs(v)   ((void)0)
   4.235  
   4.236  static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
   4.237  {
   4.238 @@ -325,9 +315,9 @@ static inline int long_mode_do_msr_write
   4.239  
   4.240  #endif /* __i386__ */
   4.241  
   4.242 -#define loaddebug(_v,_reg) \
   4.243 +#define loaddebug(_v,_reg)  \
   4.244      __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
   4.245 -#define savedebug(_v,_reg) \
   4.246 +#define savedebug(_v,_reg)  \
   4.247      __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg]))
   4.248  
   4.249  static inline void vmx_save_dr(struct vcpu *v)
   4.250 @@ -374,34 +364,21 @@ static inline void vmx_restore_dr(struct
   4.251          __restore_debug_registers(v);
   4.252  }
   4.253  
   4.254 -static void vmx_freeze_time(struct vcpu *v)
   4.255 -{
   4.256 -    struct hvm_domain *plat = &v->domain->arch.hvm_domain;
   4.257 -    struct periodic_time *pt = &plat->pl_time.periodic_tm;
   4.258 -
   4.259 -    if ( pt->enabled && pt->first_injected
   4.260 -            && (v->vcpu_id == pt->bind_vcpu)
   4.261 -            && !v->arch.hvm_vcpu.guest_time ) {
   4.262 -        v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
   4.263 -        if ( !test_bit(_VCPUF_blocked, &v->vcpu_flags) )
   4.264 -        {
   4.265 -            stop_timer(&pt->timer);
   4.266 -            rtc_freeze(v);
   4.267 -        }
   4.268 -    }
   4.269 -}
   4.270 -
   4.271  static void vmx_ctxt_switch_from(struct vcpu *v)
   4.272  {
   4.273 -    vmx_freeze_time(v);
   4.274 -    vmx_save_segments(v);
   4.275 -    vmx_load_msrs();
   4.276 +    hvm_freeze_time(v);
   4.277 +
   4.278 +    /* NB. MSR_SHADOW_GS_BASE may be changed by swapgs instrucion in guest,
   4.279 +     * so we must save it. */
   4.280 +    rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_state.shadow_gs);
   4.281 +
   4.282 +    vmx_restore_host_msrs();
   4.283      vmx_save_dr(v);
   4.284  }
   4.285  
   4.286  static void vmx_ctxt_switch_to(struct vcpu *v)
   4.287  {
   4.288 -    vmx_restore_msrs(v);
   4.289 +    vmx_restore_guest_msrs(v);
   4.290      vmx_restore_dr(v);
   4.291  }
   4.292  
   4.293 @@ -409,6 +386,7 @@ static void stop_vmx(void)
   4.294  {
   4.295      if ( !(read_cr4() & X86_CR4_VMXE) )
   4.296          return;
   4.297 +
   4.298      __vmxoff();
   4.299      clear_in_cr4(X86_CR4_VMXE);
   4.300  }
   4.301 @@ -706,7 +684,7 @@ int start_vmx(void)
   4.302  
   4.303      printk("VMXON is done\n");
   4.304  
   4.305 -    vmx_save_init_msrs();
   4.306 +    vmx_save_host_msrs();
   4.307  
   4.308      vmx_setup_hvm_funcs();
   4.309  
   4.310 @@ -843,14 +821,14 @@ static void vmx_do_cpuid(struct cpu_user
   4.311  
   4.312              if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
   4.313                  clear_bit(X86_FEATURE_APIC, &edx);
   4.314 -    
   4.315 +
   4.316  #if CONFIG_PAGING_LEVELS >= 3
   4.317              if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
   4.318  #endif
   4.319                  clear_bit(X86_FEATURE_PAE, &edx);
   4.320              clear_bit(X86_FEATURE_PSE36, &edx);
   4.321  
   4.322 -            ebx &= NUM_THREADS_RESET_MASK;  
   4.323 +            ebx &= NUM_THREADS_RESET_MASK;
   4.324  
   4.325              /* Unsupportable for virtualised CPUs. */
   4.326              ecx &= ~(bitmaskof(X86_FEATURE_VMXE)  |
   4.327 @@ -863,7 +841,7 @@ static void vmx_do_cpuid(struct cpu_user
   4.328                       bitmaskof(X86_FEATURE_ACPI)  |
   4.329                       bitmaskof(X86_FEATURE_ACC) );
   4.330          }
   4.331 -        else if (  ( input == CPUID_LEAF_0x6 ) 
   4.332 +        else if (  ( input == CPUID_LEAF_0x6 )
   4.333                  || ( input == CPUID_LEAF_0x9 )
   4.334                  || ( input == CPUID_LEAF_0xA ))
   4.335          {
   4.336 @@ -1319,7 +1297,7 @@ static int vmx_assist(struct vcpu *v, in
   4.337                  goto error;
   4.338              if ( vmx_world_restore(v, &c) != 0 )
   4.339                  goto error;
   4.340 -            v->arch.hvm_vmx.vmxassist_enabled = 1;            
   4.341 +            v->arch.hvm_vmx.vmxassist_enabled = 1;
   4.342              return 1;
   4.343          }
   4.344          break;
   4.345 @@ -1389,7 +1367,7 @@ static int vmx_set_cr0(unsigned long val
   4.346          mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
   4.347          if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
   4.348          {
   4.349 -            gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", 
   4.350 +            gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n",
   4.351                       v->arch.hvm_vmx.cpu_cr3, mfn);
   4.352              domain_crash(v->domain);
   4.353              return 0;
   4.354 @@ -1404,10 +1382,10 @@ static int vmx_set_cr0(unsigned long val
   4.355                              "with EFER.LME set but not CR4.PAE\n");
   4.356                  vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
   4.357              }
   4.358 -            else 
   4.359 +            else
   4.360              {
   4.361                  HVM_DBG_LOG(DBG_LEVEL_1, "Enabling long mode\n");
   4.362 -                v->arch.hvm_vmx.msr_content.msr_items[VMX_INDEX_MSR_EFER]
   4.363 +                v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER]
   4.364                      |= EFER_LMA;
   4.365                  vm_entry_value = __vmread(VM_ENTRY_CONTROLS);
   4.366                  vm_entry_value |= VM_ENTRY_IA32E_MODE;
   4.367 @@ -1461,7 +1439,7 @@ static int vmx_set_cr0(unsigned long val
   4.368               */
   4.369              if ( vmx_long_mode_enabled(v) )
   4.370              {
   4.371 -                v->arch.hvm_vmx.msr_content.msr_items[VMX_INDEX_MSR_EFER]
   4.372 +                v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER]
   4.373                      &= ~EFER_LMA;
   4.374                  vm_entry_value = __vmread(VM_ENTRY_CONTROLS);
   4.375                  vm_entry_value &= ~VM_ENTRY_IA32E_MODE;
   4.376 @@ -1494,8 +1472,7 @@ static int vmx_set_cr0(unsigned long val
   4.377      {
   4.378          if ( vmx_long_mode_enabled(v) )
   4.379          {
   4.380 -            v->arch.hvm_vmx.msr_content.msr_items[VMX_INDEX_MSR_EFER]
   4.381 -              &= ~EFER_LMA;
   4.382 +            v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER] &= ~EFER_LMA;
   4.383              vm_entry_value = __vmread(VM_ENTRY_CONTROLS);
   4.384              vm_entry_value &= ~VM_ENTRY_IA32E_MODE;
   4.385              __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
   4.386 @@ -1853,8 +1830,8 @@ static inline void vmx_do_msr_write(stru
   4.387          {
   4.388              struct periodic_time *pt =
   4.389                  &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
   4.390 -            if ( pt->enabled && pt->first_injected 
   4.391 -                    && v->vcpu_id == pt->bind_vcpu ) 
   4.392 +            if ( pt->enabled && pt->first_injected
   4.393 +                    && v->vcpu_id == pt->bind_vcpu )
   4.394                  pt->first_injected = 0;
   4.395          }
   4.396          hvm_set_guest_time(v, msr_content);
   4.397 @@ -1963,7 +1940,7 @@ void store_cpu_user_regs(struct cpu_user
   4.398      regs->es = __vmread(GUEST_ES_SELECTOR);
   4.399      regs->eip = __vmread(GUEST_RIP);
   4.400  }
   4.401 -#endif 
   4.402 +#endif
   4.403  
   4.404  #ifdef XEN_DEBUGGER
   4.405  void save_cpu_user_regs(struct cpu_user_regs *regs)
     5.1 --- a/xen/include/asm-x86/hvm/hvm.h	Fri Nov 17 10:24:22 2006 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Fri Nov 17 10:29:08 2006 +0000
     5.3 @@ -97,6 +97,8 @@ void hvm_domain_destroy(struct domain *d
     5.4  int hvm_vcpu_initialise(struct vcpu *v);
     5.5  void hvm_vcpu_destroy(struct vcpu *v);
     5.6  
     5.7 +void hvm_send_assist_req(struct vcpu *v);
     5.8 +
     5.9  static inline void
    5.10  hvm_store_cpu_guest_regs(
    5.11      struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs)
    5.12 @@ -161,6 +163,7 @@ hvm_get_guest_ctrl_reg(struct vcpu *v, u
    5.13  
    5.14  void hvm_stts(struct vcpu *v);
    5.15  void hvm_set_guest_time(struct vcpu *v, u64 gtime);
    5.16 +void hvm_freeze_time(struct vcpu *v);
    5.17  void hvm_migrate_timers(struct vcpu *v);
    5.18  void hvm_do_resume(struct vcpu *v);
    5.19  
     6.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Fri Nov 17 10:24:22 2006 +0000
     6.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Fri Nov 17 10:29:08 2006 +0000
     6.3 @@ -41,12 +41,12 @@ enum {
     6.4      VMX_INDEX_MSR_SYSCALL_MASK,
     6.5      VMX_INDEX_MSR_EFER,
     6.6  
     6.7 -    VMX_MSR_COUNT,
     6.8 +    VMX_MSR_COUNT
     6.9  };
    6.10  
    6.11  struct vmx_msr_state {
    6.12      unsigned long flags;
    6.13 -    unsigned long msr_items[VMX_MSR_COUNT];
    6.14 +    unsigned long msrs[VMX_MSR_COUNT];
    6.15      unsigned long shadow_gs;
    6.16  };
    6.17  
    6.18 @@ -76,8 +76,8 @@ struct arch_vmx_struct {
    6.19      unsigned long        cpu_shadow_cr4; /* copy of guest read shadow CR4 */
    6.20      unsigned long        cpu_cr2; /* save CR2 */
    6.21      unsigned long        cpu_cr3;
    6.22 -    struct vmx_msr_state msr_content;
    6.23 -    unsigned long        vmxassist_enabled:1; 
    6.24 +    struct vmx_msr_state msr_state;
    6.25 +    unsigned long        vmxassist_enabled:1;
    6.26  };
    6.27  
    6.28  #define vmx_schedule_tail(next)         \
    6.29 @@ -141,10 +141,10 @@ enum vmcs_field {
    6.30      HOST_FS_SELECTOR                = 0x00000c08,
    6.31      HOST_GS_SELECTOR                = 0x00000c0a,
    6.32      HOST_TR_SELECTOR                = 0x00000c0c,
    6.33 -    IO_BITMAP_A                     = 0x00002000, 
    6.34 -    IO_BITMAP_A_HIGH                = 0x00002001, 
    6.35 -    IO_BITMAP_B                     = 0x00002002, 
    6.36 -    IO_BITMAP_B_HIGH                = 0x00002003, 
    6.37 +    IO_BITMAP_A                     = 0x00002000,
    6.38 +    IO_BITMAP_A_HIGH                = 0x00002001,
    6.39 +    IO_BITMAP_B                     = 0x00002002,
    6.40 +    IO_BITMAP_B_HIGH                = 0x00002003,
    6.41      VM_EXIT_MSR_STORE_ADDR          = 0x00002006,
    6.42      VM_EXIT_MSR_STORE_ADDR_HIGH     = 0x00002007,
    6.43      VM_EXIT_MSR_LOAD_ADDR           = 0x00002008,
    6.44 @@ -160,7 +160,7 @@ enum vmcs_field {
    6.45      GUEST_IA32_DEBUGCTL             = 0x00002802,
    6.46      GUEST_IA32_DEBUGCTL_HIGH        = 0x00002803,
    6.47      PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
    6.48 -    CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,   
    6.49 +    CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
    6.50      EXCEPTION_BITMAP                = 0x00004004,
    6.51      PAGE_FAULT_ERROR_CODE_MASK      = 0x00004006,
    6.52      PAGE_FAULT_ERROR_CODE_MATCH     = 0x00004008,
    6.53 @@ -177,7 +177,7 @@ enum vmcs_field {
    6.54      SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
    6.55      VM_INSTRUCTION_ERROR            = 0x00004400,
    6.56      VM_EXIT_REASON                  = 0x00004402,
    6.57 -    VM_EXIT_INTR_INFO               = 0x00004404,   
    6.58 +    VM_EXIT_INTR_INFO               = 0x00004404,
    6.59      VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
    6.60      IDT_VECTORING_INFO_FIELD        = 0x00004408,
    6.61      IDT_VECTORING_ERROR_CODE        = 0x0000440a,
    6.62 @@ -209,10 +209,10 @@ enum vmcs_field {
    6.63      CR4_GUEST_HOST_MASK             = 0x00006002,
    6.64      CR0_READ_SHADOW                 = 0x00006004,
    6.65      CR4_READ_SHADOW                 = 0x00006006,
    6.66 -    CR3_TARGET_VALUE0               = 0x00006008, 
    6.67 -    CR3_TARGET_VALUE1               = 0x0000600a, 
    6.68 -    CR3_TARGET_VALUE2               = 0x0000600c, 
    6.69 -    CR3_TARGET_VALUE3               = 0x0000600e, 
    6.70 +    CR3_TARGET_VALUE0               = 0x00006008,
    6.71 +    CR3_TARGET_VALUE1               = 0x0000600a,
    6.72 +    CR3_TARGET_VALUE2               = 0x0000600c,
    6.73 +    CR3_TARGET_VALUE3               = 0x0000600e,
    6.74      EXIT_QUALIFICATION              = 0x00006400,
    6.75      GUEST_LINEAR_ADDRESS            = 0x0000640a,
    6.76      GUEST_CR0                       = 0x00006800,
    6.77 @@ -226,7 +226,7 @@ enum vmcs_field {
    6.78      GUEST_GS_BASE                   = 0x00006810,
    6.79      GUEST_LDTR_BASE                 = 0x00006812,
    6.80      GUEST_TR_BASE                   = 0x00006814,
    6.81 -    GUEST_GDTR_BASE                 = 0x00006816,    
    6.82 +    GUEST_GDTR_BASE                 = 0x00006816,
    6.83      GUEST_IDTR_BASE                 = 0x00006818,
    6.84      GUEST_DR7                       = 0x0000681a,
    6.85      GUEST_RSP                       = 0x0000681c,
     7.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Fri Nov 17 10:24:22 2006 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Fri Nov 17 10:29:08 2006 +0000
     7.3 @@ -262,13 +262,13 @@ static inline int vmx_paging_enabled(str
     7.4  
     7.5  static inline int vmx_long_mode_enabled(struct vcpu *v)
     7.6  {
     7.7 -    u64 efer = v->arch.hvm_vmx.msr_content.msr_items[VMX_INDEX_MSR_EFER];
     7.8 +    u64 efer = v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER];
     7.9      return efer & EFER_LMA;
    7.10  }
    7.11  
    7.12  static inline int vmx_lme_is_set(struct vcpu *v)
    7.13  {
    7.14 -    u64 efer = v->arch.hvm_vmx.msr_content.msr_items[VMX_INDEX_MSR_EFER];
    7.15 +    u64 efer = v->arch.hvm_vmx.msr_state.msrs[VMX_INDEX_MSR_EFER];
    7.16      return efer & EFER_LME;
    7.17  }
    7.18