ia64/xen-unstable

changeset 16346:00db9ec39831

x86: Fix PV guest CR4 handling. We should not leak hidden CR4 bits
into guest CR4 value.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Wed Nov 07 14:15:44 2007 +0000 (2007-11-07)
parents c982fe8a9f91
children 644e7577f6ee
files xen/arch/x86/domain.c xen/arch/x86/traps.c xen/include/asm-x86/domain.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Wed Nov 07 13:41:29 2007 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Wed Nov 07 14:15:44 2007 +0000
     1.3 @@ -415,7 +415,8 @@ int vcpu_initialise(struct vcpu *v)
     1.4              v->arch.cr3           = __pa(idle_pg_table);
     1.5          }
     1.6  
     1.7 -        v->arch.guest_context.ctrlreg[4] = mmu_cr4_features;
     1.8 +        v->arch.guest_context.ctrlreg[4] =
     1.9 +            real_cr4_to_pv_guest_cr4(mmu_cr4_features);
    1.10      }
    1.11  
    1.12      v->arch.perdomain_ptes =
    1.13 @@ -573,17 +574,18 @@ void arch_domain_destroy(struct domain *
    1.14  
    1.15  unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4)
    1.16  {
    1.17 -    unsigned long hv_cr4 = read_cr4(), hv_cr4_mask = ~X86_CR4_TSD;
    1.18 +    unsigned long hv_cr4_mask, hv_cr4 = real_cr4_to_pv_guest_cr4(read_cr4());
    1.19 +
    1.20 +    hv_cr4_mask = ~X86_CR4_TSD;
    1.21      if ( cpu_has_de )
    1.22          hv_cr4_mask &= ~X86_CR4_DE;
    1.23  
    1.24 -    if ( (guest_cr4 & hv_cr4_mask) !=
    1.25 -         (hv_cr4 & hv_cr4_mask & ~(X86_CR4_PGE|X86_CR4_PSE)) )
    1.26 +    if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) )
    1.27          gdprintk(XENLOG_WARNING,
    1.28                   "Attempt to change CR4 flags %08lx -> %08lx\n",
    1.29                   hv_cr4 & ~(X86_CR4_PGE|X86_CR4_PSE), guest_cr4);
    1.30  
    1.31 -    return  (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask);
    1.32 +    return (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask);
    1.33  }
    1.34  
    1.35  /* This is called by arch_final_setup_guest and do_boot_vcpu */
    1.36 @@ -684,8 +686,8 @@ int arch_set_info_guest(
    1.37      v->arch.guest_context.user_regs.eflags |= EF_IE;
    1.38  
    1.39      cr4 = v->arch.guest_context.ctrlreg[4];
    1.40 -    v->arch.guest_context.ctrlreg[4] =
    1.41 -        (cr4 == 0) ? mmu_cr4_features : pv_guest_cr4_fixup(cr4);
    1.42 +    v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(cr4) :
    1.43 +        real_cr4_to_pv_guest_cr4(mmu_cr4_features);
    1.44  
    1.45      memset(v->arch.guest_context.debugreg, 0,
    1.46             sizeof(v->arch.guest_context.debugreg));
    1.47 @@ -1223,11 +1225,14 @@ static void paravirt_ctxt_switch_from(st
    1.48  
    1.49  static void paravirt_ctxt_switch_to(struct vcpu *v)
    1.50  {
    1.51 +    unsigned long cr4;
    1.52 +
    1.53      set_int80_direct_trap(v);
    1.54      switch_kernel_stack(v);
    1.55  
    1.56 -    if ( unlikely(read_cr4() != v->arch.guest_context.ctrlreg[4]) )
    1.57 -        write_cr4(v->arch.guest_context.ctrlreg[4]);
    1.58 +    cr4 = pv_guest_cr4_to_real_cr4(v->arch.guest_context.ctrlreg[4]);
    1.59 +    if ( unlikely(cr4 != read_cr4()) )
    1.60 +        write_cr4(cr4);
    1.61  
    1.62      if ( unlikely(v->arch.guest_context.debugreg[7]) )
    1.63      {
     2.1 --- a/xen/arch/x86/traps.c	Wed Nov 07 13:41:29 2007 +0000
     2.2 +++ b/xen/arch/x86/traps.c	Wed Nov 07 14:15:44 2007 +0000
     2.3 @@ -1797,7 +1797,8 @@ static int emulate_privileged_op(struct 
     2.4  
     2.5          case 4: /* Write CR4 */
     2.6              v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(*reg);
     2.7 -            write_cr4(v->arch.guest_context.ctrlreg[4]);
     2.8 +            write_cr4(pv_guest_cr4_to_real_cr4(
     2.9 +                v->arch.guest_context.ctrlreg[4]));
    2.10              break;
    2.11  
    2.12          default:
     3.1 --- a/xen/include/asm-x86/domain.h	Wed Nov 07 13:41:29 2007 +0000
     3.2 +++ b/xen/include/asm-x86/domain.h	Wed Nov 07 14:15:44 2007 +0000
     3.3 @@ -350,8 +350,15 @@ struct arch_vcpu
     3.4  /* Continue the current hypercall via func(data) on specified cpu. */
     3.5  int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data);
     3.6  
     3.7 +/* Clean up CR4 bits that are not under guest control. */
     3.8  unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4);
     3.9  
    3.10 +/* Convert between guest-visible and real CR4 values. */
    3.11 +#define pv_guest_cr4_to_real_cr4(c) \
    3.12 +    ((c) | (mmu_cr4_features & (X86_CR4_PGE | X86_CR4_PSE)))
    3.13 +#define real_cr4_to_pv_guest_cr4(c) \
    3.14 +    ((c) & ~(X86_CR4_PGE | X86_CR4_PSE))
    3.15 +
    3.16  #endif /* __ASM_DOMAIN_H__ */
    3.17  
    3.18  /*