[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |