ia64/xen-unstable

changeset 15750:08e962b8597c

hvm: Cleanups to state-restore paths (including vmxassist world restore).
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Aug 13 18:18:22 2007 +0100 (2007-08-13)
parents d8b5b02c52cf
children fdffab15499d
files xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c
line diff
     1.1 --- a/xen/arch/x86/hvm/hvm.c	Mon Aug 13 16:47:11 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Mon Aug 13 18:18:22 2007 +0100
     1.3 @@ -587,7 +587,7 @@ int hvm_set_cr0(unsigned long value)
     1.4              hvm_update_guest_efer(v);
     1.5          }
     1.6  
     1.7 -        if ( !paging_mode_hap(v->domain) && v->arch.hvm_vcpu.guest_cr[3] )
     1.8 +        if ( !paging_mode_hap(v->domain) )
     1.9          {
    1.10              put_page(mfn_to_page(get_mfn_from_gpfn(
    1.11                  v->arch.hvm_vcpu.guest_cr[3] >> PAGE_SHIFT)));
     2.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Aug 13 16:47:11 2007 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Aug 13 18:18:22 2007 +0100
     2.3 @@ -345,14 +345,13 @@ int svm_vmcb_restore(struct vcpu *v, str
     2.4      vmcb->rflags = c->rflags;
     2.5  
     2.6      v->arch.hvm_vcpu.guest_cr[0] = c->cr0 | X86_CR0_ET;
     2.7 +    v->arch.hvm_vcpu.guest_cr[2] = c->cr2;
     2.8 +    v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
     2.9 +    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
    2.10      svm_update_guest_cr(v, 0);
    2.11 -
    2.12 -    v->arch.hvm_vcpu.guest_cr[2] = c->cr2;
    2.13      svm_update_guest_cr(v, 2);
    2.14 +    svm_update_guest_cr(v, 4);
    2.15  
    2.16 -    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
    2.17 -    svm_update_guest_cr(v, 4);
    2.18 -    
    2.19  #ifdef HVM_DEBUG_SUSPEND
    2.20      printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
    2.21             __func__, c->cr3, c->cr0, c->cr4);
    2.22 @@ -360,15 +359,14 @@ int svm_vmcb_restore(struct vcpu *v, str
    2.23  
    2.24      if ( hvm_paging_enabled(v) && !paging_mode_hap(v->domain) )
    2.25      {
    2.26 -        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64, c->cr3);
    2.27 +        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 = %"PRIx64, c->cr3);
    2.28          mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
    2.29          if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) 
    2.30              goto bad_cr3;
    2.31          old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
    2.32          v->arch.guest_table = pagetable_from_pfn(mfn);
    2.33 -        if (old_base_mfn)
    2.34 +        if ( old_base_mfn )
    2.35               put_page(mfn_to_page(old_base_mfn));
    2.36 -        v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
    2.37      }
    2.38  
    2.39      vmcb->idtr.limit = c->idtr_limit;
     3.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Mon Aug 13 16:47:11 2007 +0100
     3.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Mon Aug 13 18:18:22 2007 +0100
     3.3 @@ -61,6 +61,7 @@ static void vmx_ctxt_switch_to(struct vc
     3.4  static int  vmx_alloc_vlapic_mapping(struct domain *d);
     3.5  static void vmx_free_vlapic_mapping(struct domain *d);
     3.6  static void vmx_install_vlapic_mapping(struct vcpu *v);
     3.7 +static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr);
     3.8  static void vmx_update_guest_efer(struct vcpu *v);
     3.9  
    3.10  static int vmx_domain_initialise(struct domain *d)
    3.11 @@ -572,51 +573,34 @@ int vmx_vmcs_restore(struct vcpu *v, str
    3.12      __vmwrite(GUEST_RSP, c->rsp);
    3.13      __vmwrite(GUEST_RFLAGS, c->rflags);
    3.14  
    3.15 -    v->arch.hvm_vcpu.hw_cr[0] = (c->cr0 | X86_CR0_PE | X86_CR0_PG |
    3.16 -                                 X86_CR0_NE | X86_CR0_WP | X86_CR0_ET);
    3.17 -    __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
    3.18 -    v->arch.hvm_vcpu.guest_cr[0] = c->cr0;
    3.19 -    __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
    3.20 -
    3.21 +    v->arch.hvm_vcpu.guest_cr[0] = c->cr0 | X86_CR0_ET;
    3.22      v->arch.hvm_vcpu.guest_cr[2] = c->cr2;
    3.23 -
    3.24 -    v->arch.hvm_vcpu.guest_efer = c->msr_efer;
    3.25 +    v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
    3.26 +    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
    3.27 +    vmx_update_guest_cr(v, 0);
    3.28 +    vmx_update_guest_cr(v, 2);
    3.29 +    vmx_update_guest_cr(v, 4);
    3.30  
    3.31  #ifdef HVM_DEBUG_SUSPEND
    3.32      printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
    3.33             __func__, c->cr3, c->cr0, c->cr4);
    3.34  #endif
    3.35  
    3.36 -    if ( !hvm_paging_enabled(v) )
    3.37 -    {
    3.38 -        HVM_DBG_LOG(DBG_LEVEL_VMMU, "%s: paging not enabled.", __func__);
    3.39 -        goto skip_cr3;
    3.40 -    }
    3.41 -
    3.42 -    HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 = %"PRIx64, c->cr3);
    3.43 -    /* current!=vcpu as not called by arch_vmx_do_launch */
    3.44 -    mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
    3.45 -    if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
    3.46 +    if ( hvm_paging_enabled(v) )
    3.47      {
    3.48 -        gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64".\n", c->cr3);
    3.49 -        vmx_vmcs_exit(v);
    3.50 -        return -EINVAL;
    3.51 +        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 = %"PRIx64, c->cr3);
    3.52 +        mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
    3.53 +        if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
    3.54 +            goto bad_cr3;
    3.55 +        old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
    3.56 +        v->arch.guest_table = pagetable_from_pfn(mfn);
    3.57 +        if ( old_base_mfn )
    3.58 +            put_page(mfn_to_page(old_base_mfn));
    3.59      }
    3.60  
    3.61 -    old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
    3.62 -    v->arch.guest_table = pagetable_from_pfn(mfn);
    3.63 -    if ( old_base_mfn )
    3.64 -        put_page(mfn_to_page(old_base_mfn));
    3.65 -
    3.66 - skip_cr3:
    3.67 -    v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
    3.68 -
    3.69 +    v->arch.hvm_vcpu.guest_efer = c->msr_efer;
    3.70      vmx_update_guest_efer(v);
    3.71  
    3.72 -    __vmwrite(GUEST_CR4, (c->cr4 | HVM_CR4_HOST_MASK));
    3.73 -    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
    3.74 -    __vmwrite(CR4_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[4]);
    3.75 -
    3.76      __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit);
    3.77      __vmwrite(GUEST_IDTR_BASE, c->idtr_base);
    3.78  
    3.79 @@ -696,6 +680,11 @@ int vmx_vmcs_restore(struct vcpu *v, str
    3.80      }
    3.81  
    3.82      return 0;
    3.83 +
    3.84 + bad_cr3:
    3.85 +    gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n", c->cr3);
    3.86 +    vmx_vmcs_exit(v);
    3.87 +    return -EINVAL;
    3.88  }
    3.89  
    3.90  #if defined(__x86_64__) && defined(HVM_DEBUG_SUSPEND)
    3.91 @@ -1923,29 +1912,14 @@ static int vmx_world_restore(struct vcpu
    3.92      __vmwrite(GUEST_RFLAGS, c->eflags);
    3.93  
    3.94      v->arch.hvm_vcpu.guest_cr[0] = c->cr0;
    3.95 -    __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
    3.96 -
    3.97 -    if ( !hvm_paging_enabled(v) )
    3.98 -        goto skip_cr3;
    3.99 -
   3.100 -    if ( c->cr3 == v->arch.hvm_vcpu.guest_cr[3] )
   3.101 +    v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
   3.102 +    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
   3.103 +    vmx_update_guest_cr(v, 0);
   3.104 +    vmx_update_guest_cr(v, 4);
   3.105 +
   3.106 +    if ( hvm_paging_enabled(v) )
   3.107      {
   3.108 -        /*
   3.109 -         * This is simple TLB flush, implying the guest has
   3.110 -         * removed some translation or changed page attributes.
   3.111 -         * We simply invalidate the shadow.
   3.112 -         */
   3.113 -        mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
   3.114 -        if ( mfn != pagetable_get_pfn(v->arch.guest_table) )
   3.115 -            goto bad_cr3;
   3.116 -    }
   3.117 -    else
   3.118 -    {
   3.119 -        /*
   3.120 -         * If different, make a shadow. Check if the PDBR is valid
   3.121 -         * first.
   3.122 -         */
   3.123 -        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3);
   3.124 +        HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 = %x", c->cr3);
   3.125          mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
   3.126          if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
   3.127              goto bad_cr3;
   3.128 @@ -1953,19 +1927,8 @@ static int vmx_world_restore(struct vcpu
   3.129          v->arch.guest_table = pagetable_from_pfn(mfn);
   3.130          if ( old_base_mfn )
   3.131               put_page(mfn_to_page(old_base_mfn));
   3.132 -        v->arch.hvm_vcpu.guest_cr[3] = c->cr3;
   3.133      }
   3.134  
   3.135 - skip_cr3:
   3.136 -    if ( !hvm_paging_enabled(v) )
   3.137 -        HVM_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
   3.138 -    else
   3.139 -        HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %x", c->cr3);
   3.140 -
   3.141 -    __vmwrite(GUEST_CR4, (c->cr4 | HVM_CR4_HOST_MASK));
   3.142 -    v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
   3.143 -    __vmwrite(CR4_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[4]);
   3.144 -
   3.145      __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit);
   3.146      __vmwrite(GUEST_IDTR_BASE, c->idtr_base);
   3.147