x86: Remove invlpg_works_ok and invlpg only single-page regions.
authorKeir Fraser <keir@xensource.com>
Wed, 17 Oct 2007 10:12:32 +0000 (11:12 +0100)
committerKeir Fraser <keir@xensource.com>
Wed, 17 Oct 2007 10:12:32 +0000 (11:12 +0100)
The flush_area_local() interface was unclear about whether a
multi-page region (2M/4M/1G) had to be mapped by a superpage, and
indeed some callers (map_pages_to_xen()) already would specify
FLUSH_LEVEL(2) for a region actually mapped by 4kB PTEs.

The safest fix is to relax the interface and do a full TLB flush in
these cases. My suspicion is that these cases are rare enough that the
cost of INVLPG versus full flush will be unimportant.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/cpu/amd.c
xen/arch/x86/cpu/common.c
xen/arch/x86/cpu/intel.c
xen/arch/x86/flushtlb.c
xen/arch/x86/setup.c
xen/include/asm-x86/flushtlb.h
xen/include/asm-x86/processor.h

index 4ed95ea6a7d16dbc3e1be6316c897d251089440f..13fec06717dd5840032e41c53487704cfab9d401 100644 (file)
@@ -373,11 +373,6 @@ static void __init init_amd(struct cpuinfo_x86 *c)
        if ((smp_processor_id() == 1) && c1_ramping_may_cause_clock_drift(c))
                disable_c1_ramping();
 
-       /* Support INVLPG of superpages? */
-       __set_bit(2, &c->invlpg_works_ok);
-       if ( cpu_has(c, X86_FEATURE_PAGE1GB) )
-               __set_bit(3, &c->invlpg_works_ok);
-
        start_svm(c);
 }
 
index a578a7b108fe6224d3071f138405516ef305dc42..c333ac36f2e724888fb5ee270e62d66e6a69e53c 100644 (file)
@@ -314,7 +314,6 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
        c->x86_vendor_id[0] = '\0'; /* Unset */
        c->x86_model_id[0] = '\0';  /* Unset */
        c->x86_max_cores = 1;
-       c->invlpg_works_ok = 1; /* no superpage INVLPG by default */
        c->x86_clflush_size = 0;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
index c3daf2987da406dbc6e8ff0cdd7ec30a73fccccc..5fcad2403ad204dee881f6664dbde80ba0a7e914 100644 (file)
@@ -123,18 +123,6 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
        if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
                clear_bit(X86_FEATURE_SEP, c->x86_capability);
 
-       /* Supports INVLPG of superpages? */
-       __set_bit(2, &c->invlpg_works_ok);
-       if (/* PentiumPro erratum 30 */
-           (c->x86 == 6 && c->x86_model == 1 && c->x86_mask < 9) ||
-           /* Dual-Core Intel Xeon 3000/5100 series erratum 89/90 */
-           /* Quad-Core Intel Xeon 3200/5300 series erratum 89/88 */
-           /* Intel Core2 erratum 89 */
-           (c->x86 == 6 && c->x86_model == 15 ) ||
-           /* Dual-Core Intel Xeon LV/ULV erratum 75 */
-           (c->x86 == 6 && c->x86_model == 14 ))
-               __clear_bit(2, &c->invlpg_works_ok);
-
        /* Names for the Pentium II/Celeron processors 
           detectable only by also checking the cache size.
           Dixon is NOT a Celeron. */
index 69aa7fa21dbf98e39d9fcd6a8fc3b828e7d90ed3..808b848de508d2921339a64c000f24a9f760e912 100644 (file)
@@ -108,8 +108,14 @@ void flush_area_local(const void *va, unsigned int flags)
 
     if ( flags & (FLUSH_TLB|FLUSH_TLB_GLOBAL) )
     {
-        if ( (level != 0) && test_bit(level, &c->invlpg_works_ok) )
+        if ( level == 1 )
         {
+            /*
+             * We don't INVLPG multi-page regions because the 2M/4M/1G
+             * region may not have been mapped with a superpage. Also there
+             * are various errata surrounding INVLPG usage on superpages, and
+             * a full flush is in any case not *that* expensive.
+             */
             asm volatile ( "invlpg %0"
                            : : "m" (*(const char *)(va)) : "memory" );
         }
index c0e62fdada8a9f1f9b83d99d9d8fe7d49b036962..c2247918d9f92ed4934234ba6db2619859c920f8 100644 (file)
@@ -114,7 +114,7 @@ struct tss_struct init_tss[NR_CPUS];
 
 char __attribute__ ((__section__(".bss.stack_aligned"))) cpu0_stack[STACK_SIZE];
 
-struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, 1, -1 };
+struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1 };
 
 #if CONFIG_PAGING_LEVELS > 2
 unsigned long mmu_cr4_features = X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE;
index 7e67ec23b448e26ff695047e5d5eed250abe592b..7dff2e74bd4787c673d4def1d170a698b48a9c98 100644 (file)
@@ -78,6 +78,7 @@ void write_cr3(unsigned long cr3);
   *  1 -> 4kB area containing specified virtual address
   *  2 -> 4MB/2MB area containing specified virtual address
   *  3 -> 1GB area containing specified virtual address (x86/64 only)
+  * NB. Multi-page areas do not need to have been mapped with a superpage.
   */
 #define FLUSH_LEVEL_MASK 0x0f
 #define FLUSH_LEVEL(x)   (x)
index 8ed9ecb67c4ff239a8cc7e25f970673314bba9ae..0af78e21c1af6ce4fcecc0d64a7a0af8e4e20e63 100644 (file)
@@ -164,7 +164,6 @@ struct cpuinfo_x86 {
     __u8 x86_vendor;     /* CPU vendor */
     __u8 x86_model;
     __u8 x86_mask;
-    __u8 invlpg_works_ok;
     int  cpuid_level;    /* Maximum supported CPUID level, -1=no CPUID */
     unsigned int x86_capability[NCAPINTS];
     char x86_vendor_id[16];