[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [Xen-devel] [Patch] Enable SMEP CPU feature support for XEN itself



> > --- a/xen/arch/x86/cpu/common.c     Wed Jun 01 11:11:43 2011 +0100
> > +++ b/xen/arch/x86/cpu/common.c     Wed Jun 01 19:53:52 2011 +0800
> > @@ -28,6 +28,9 @@
> >  integer_param("cpuid_mask_ext_ecx", opt_cpuid_mask_ext_ecx);
> >  unsigned int __devinitdata opt_cpuid_mask_ext_edx = ~0u;
> >  integer_param("cpuid_mask_ext_edx", opt_cpuid_mask_ext_edx);
> > +/* nosmep: if true, Intel SMEP is disabled. */
> > +static bool_t __initdata disable_smep;
> 
> An __initdata variable used in ...

a mistake copied from native patch :) we'll change it to __cpuinitdata

> 
> > +boolean_param("nosmep", disable_smep);
> >
> >  struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
> >
> > @@ -222,6 +225,17 @@
> >     c->x86_capability[4] = cap4;
> >  }
> >
> > +static void __cpuinit setup_smep(struct cpuinfo_x86 *c)
> > +{
> > +   if ( cpu_has(c, X86_FEATURE_SMEP) ) {
> > +           if( unlikely(disable_smep) ) {
> 
> ... a __cpuinit function?

If change disable_smep to __cpuinitdata, this should be ok.


> 
> > +                   setup_clear_cpu_cap(X86_FEATURE_SMEP);
> > +                   clear_in_cr4(X86_CR4_SMEP);
> > +           } else
> > +                   set_in_cr4(X86_CR4_SMEP);
> 
> Anyway, the whole thing is overkill - {set,clear}_in_cr4() write
> the updated bits to mmu_cr4_features, and these get loaded
> on secondary CPUs *before* you have any chance of looking
> at the CPUID bits. As with everything else, it's assumed that
> APs don't have less features than the BP, and hence you only
> need to set_in_cr4() once (on the BP). And then the function
> can be __init.
>

Do you mean? 
        if ( cpu_has(c, X86_FEATURE_SMEP) )
                if( likely(!disable_smep) ) {
                        mmu_cr4_features |= X86_CR4_SMEP;
                        set_in_cr4(0);
                } else
                        setup_clear_cpu_cap(X86_FEATURE_SMEP);

Sounds good ... but the code will be harder to read, as it implicitly set smep?
Also where to put setup_smep thus it's only called in BP?

> > +   }
> > +}
> > +
> >  void __cpuinit generic_identify(struct cpuinfo_x86 * c)
> >  {
> >     u32 tfms, xlvl, capability, excap, ebx;
> > @@ -268,6 +282,8 @@
> 
> Would also be really helpful if you patch was generated with -p.
> 
> >             c->x86_capability[X86_FEATURE_FSGSBASE / 32] = ebx;
> >     }
> >
> > +   setup_smep(c);
> > +
> >     early_intel_workaround(c);
> >
> >  #ifdef CONFIG_X86_HT
> > diff -r d4f6310f1ef5 xen/arch/x86/traps.c
> > --- a/xen/arch/x86/traps.c  Wed Jun 01 11:11:43 2011 +0100
> > +++ b/xen/arch/x86/traps.c  Wed Jun 01 19:53:52 2011 +0800
> > @@ -1195,8 +1195,16 @@
> >      if ( ((l3e_get_flags(l3e) & required_flags) != required_flags) ||
> >           (l3e_get_flags(l3e) & disallowed_flags) )
> >          return 0;
> > -    if ( l3e_get_flags(l3e) & _PAGE_PSE )
> > +    if ( l3e_get_flags(l3e) & _PAGE_PSE ) {
> > +        /* SMEP fault error code 10001b */
> > +        if ( (error_code & PFEC_insn_fetch) &&
> > +             !(error_code & PFEC_user_mode) &&
> > +             cpu_has_smep &&
> > +             (_PAGE_USER & l4e_get_flags(l4e) & l3e_get_flags(l3e)) )
> > +            return 2;
> > +
> >          return 1;
> > +    }
> >  #endif
> >  #endif
> >
> > @@ -1207,8 +1215,21 @@
> >      if ( ((l2e_get_flags(l2e) & required_flags) != required_flags) ||
> >           (l2e_get_flags(l2e) & disallowed_flags) )
> >          return 0;
> > -    if ( l2e_get_flags(l2e) & _PAGE_PSE )
> > +    if ( l2e_get_flags(l2e) & _PAGE_PSE ) {
> > +        /* SMEP fault error code 10001b */
> > +        if ( (error_code & PFEC_insn_fetch) &&
> > +             !(error_code & PFEC_user_mode) &&
> > +             cpu_has_smep &&
> > +             (_PAGE_USER &
> > +#if CONFIG_PAGING_LEVELS >= 4
> > +              l4e_get_flags(l4e) &
> > +              l3e_get_flags(l3e) &
> > +#endif
> > +              l2e_get_flags(l2e)) )
> > +            return 2;
> > +
> >          return 1;
> > +    }
> >
> >      l1t = map_domain_page(mfn);
> >      l1e = l1e_read_atomic(&l1t[l1_table_offset(addr)]);
> > @@ -1218,6 +1239,18 @@
> >           (l1e_get_flags(l1e) & disallowed_flags) )
> >          return 0;
> >
> > +    /* SMEP fault error code 10001b */
> > +    if ( (error_code & PFEC_insn_fetch) &&
> > +         !(error_code & PFEC_user_mode) &&
> > +         cpu_has_smep &&
> > +         (_PAGE_USER &
> > +#if CONFIG_PAGING_LEVELS >= 4
> > +          l4e_get_flags(l4e) &
> > +          l3e_get_flags(l3e) &
> > +#endif
> > +          l2e_get_flags(l2e) & l1e_get_flags(l1e)) )
> > +        return 2;
> 
> The further down I get the uglier this looks. Can't you simply
> accumulate the user bit into a separate variable? That way the
> compiler also doesn't need to keep around all the l[1234]e
> variables.

At the beginning we did accumulate the user bit into a separate variable. 
However
SMEP faults hardly happen while we keep accumulating user bit no matter it's a
spurious fault or not, and even spurious faults are rare I guess.
Thanks!
-Xin


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.