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

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

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

Xen patchbot-unstable
# HG changeset patch
# User [hidden email]
# 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 <[hidden email]>
---
 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
[hidden email]
http://lists.xensource.com/xen-changelog