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

[Xen-changelog] [xen-unstable] [IA64] Fix I&D cache incoherency after vcpu migration



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1171560333 25200
# Node ID 2b3dd681dbce7a598784b526d232c3c199f46437
# Parent  6c63ff5488888b836ebc9f04c26757716006db40
[IA64] Fix I&D cache incoherency after vcpu migration

Windows on HVM ocasionally crashes with BSOD especially on boot time.
I finally found out the cause is PAL_CACHE_FLUSH(cache_type=4).
The cache_type means an argument of PAL_CACHE_FLUSH and cache_type=4
makes local instruction caches coherent with the data caches.
See SDM vol2 11.10.3, PAL_CACHE_FLUSH.
FYI, Linux never uses cache_type=4.

Currently PAL_CACHE_FLUSH is called on only local cpu and caches on the
other cpus are still incoherent.

Attached patch does:
- When cache_type=1,2,3 that means flushing caches on local cpus,
  caches on the other cpus becomes to be flushed also.
  It might be overkill and not efficient. But I think it's permissive
  since these cache_type are seldom used.

- When cache_type=4, the actual PAL call to the other cpus is deferred
  until the vcpu migration occurs or the cpu becomes idle.
  Since Windows uses cache_type=4 quite often and many vcpus on SMP
  environment call PAL_CACHE_FLUSH simultaneously.

Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/domain.c               |   23 +++++++++++++++
 xen/arch/ia64/xen/fw_emul.c              |   47 +++++++++++++++++++++++++++++++
 xen/include/asm-ia64/domain.h            |    1 
 xen/include/asm-ia64/linux-xen/asm/pal.h |    3 +
 4 files changed, 74 insertions(+)

diff -r 6c63ff548888 -r 2b3dd681dbce xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Wed Feb 14 10:14:37 2007 -0700
+++ b/xen/arch/ia64/xen/domain.c        Thu Feb 15 10:25:33 2007 -0700
@@ -138,6 +138,28 @@ static void flush_vtlb_for_context_switc
        }
 }
 
+static void flush_cache_for_context_switch(struct vcpu *next)
+{
+       extern cpumask_t cpu_cache_coherent_map;
+       int cpu = smp_processor_id();
+
+       if (is_idle_vcpu(next) ||
+           __test_and_clear_bit(cpu, &next->arch.cache_coherent_map)) {
+               if (cpu_test_and_clear(cpu, cpu_cache_coherent_map)) {
+                       unsigned long flags;
+                       u64 progress = 0;
+                       s64 status;
+
+                       local_irq_save(flags);
+                       status = ia64_pal_cache_flush(4, 0, &progress, NULL);
+                       local_irq_restore(flags);
+                       if (status != 0)
+                               panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+                                            "cache_type=4 status %lx", status);
+               }
+       }
+}
+
 static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next)
 {
        /*
@@ -260,6 +282,7 @@ void context_switch(struct vcpu *prev, s
     }
    
     flush_vtlb_for_context_switch(prev, current);
+    flush_cache_for_context_switch(current);
     context_saved(prev);
 }
 
diff -r 6c63ff548888 -r 2b3dd681dbce xen/arch/ia64/xen/fw_emul.c
--- a/xen/arch/ia64/xen/fw_emul.c       Wed Feb 14 10:14:37 2007 -0700
+++ b/xen/arch/ia64/xen/fw_emul.c       Thu Feb 15 10:25:33 2007 -0700
@@ -377,6 +377,28 @@ sal_emulator (long index, unsigned long 
                break;
        }
        return ((struct sal_ret_values) {status, r9, r10, r11});
+}
+
+cpumask_t cpu_cache_coherent_map;
+
+struct cache_flush_args {
+       u64 cache_type;
+       u64 operation;
+       u64 progress;
+       long status;
+};
+
+static void
+remote_pal_cache_flush(void *v)
+{
+       struct cache_flush_args *args = v;
+       long status;
+       u64 progress = args->progress;
+
+       status = ia64_pal_cache_flush(args->cache_type, args->operation,
+                                     &progress, NULL);
+       if (status != 0)
+               args->status = status;
 }
 
 struct ia64_pal_retval
@@ -542,8 +564,26 @@ xen_pal_emulator(unsigned long index, u6
                status = ia64_pal_register_info(in1, &r9, &r10);
                break;
            case PAL_CACHE_FLUSH:
+               if (in3 != 0) /* Initially progress_indicator must be 0 */
+                       panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+                                    "progress_indicator=%lx", in3);
+
                /* Always call Host Pal in int=0 */
                in2 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
+
+               if (in1 != PAL_CACHE_TYPE_COHERENT) {
+                       struct cache_flush_args args = {
+                               .cache_type = in1,
+                               .operation = in2,
+                               .progress = 0,
+                               .status = 0
+                       };
+                       smp_call_function(remote_pal_cache_flush,
+                                         (void *)&args, 1, 1);
+                       if (args.status != 0)
+                               panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+                                            "remote status %lx", args.status);
+               }
 
                /*
                 * Call Host PAL cache flush
@@ -556,6 +596,13 @@ xen_pal_emulator(unsigned long index, u6
                        panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
                                     "status %lx", status);
 
+               if (in1 == PAL_CACHE_TYPE_COHERENT) {
+                       int cpu = current->processor;
+                       cpus_setall(current->arch.cache_coherent_map);
+                       cpu_clear(cpu, current->arch.cache_coherent_map);
+                       cpus_setall(cpu_cache_coherent_map);
+                       cpu_clear(cpu, cpu_cache_coherent_map);
+               }
                break;
            case PAL_PERF_MON_INFO:
                {
diff -r 6c63ff548888 -r 2b3dd681dbce xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Wed Feb 14 10:14:37 2007 -0700
+++ b/xen/include/asm-ia64/domain.h     Thu Feb 15 10:25:33 2007 -0700
@@ -201,6 +201,7 @@ struct arch_vcpu {
 #endif
 #define INVALID_PROCESSOR       INT_MAX
     int last_processor;
+    cpumask_t cache_coherent_map;
 };
 
 #include <asm/uaccess.h> /* for KERNEL_DS */
diff -r 6c63ff548888 -r 2b3dd681dbce xen/include/asm-ia64/linux-xen/asm/pal.h
--- a/xen/include/asm-ia64/linux-xen/asm/pal.h  Wed Feb 14 10:14:37 2007 -0700
+++ b/xen/include/asm-ia64/linux-xen/asm/pal.h  Thu Feb 15 10:25:33 2007 -0700
@@ -112,6 +112,9 @@ typedef u64                         pal_cache_type_t;
 #define PAL_CACHE_TYPE_INSTRUCTION     1       /* Instruction cache */
 #define PAL_CACHE_TYPE_DATA            2       /* Data or unified cache */
 #define PAL_CACHE_TYPE_INSTRUCTION_DATA        3       /* Both Data & 
Instruction */
+#ifdef XEN
+#define PAL_CACHE_TYPE_COHERENT                4       /* Make I&D-cache 
coherent */
+#endif
 
 
 #define PAL_CACHE_FLUSH_INVALIDATE     1       /* Invalidate clean lines */

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


 


Rackspace

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