[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-ia64-devel] [PATCH] 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. Thanks, Kouya Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx> diff -r 8bdbe88e422f xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Mon Feb 12 10:10:37 2007 -0700 +++ b/xen/arch/ia64/xen/domain.c Tue Feb 13 19:18:19 2007 +0900 @@ -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 8bdbe88e422f xen/arch/ia64/xen/fw_emul.c --- a/xen/arch/ia64/xen/fw_emul.c Mon Feb 12 10:10:37 2007 -0700 +++ b/xen/arch/ia64/xen/fw_emul.c Tue Feb 13 19:19:56 2007 +0900 @@ -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 8bdbe88e422f xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Mon Feb 12 10:10:37 2007 -0700 +++ b/xen/include/asm-ia64/domain.h Tue Feb 13 19:16:46 2007 +0900 @@ -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 8bdbe88e422f xen/include/asm-ia64/linux-xen/asm/pal.h --- a/xen/include/asm-ia64/linux-xen/asm/pal.h Mon Feb 12 10:10:37 2007 -0700 +++ b/xen/include/asm-ia64/linux-xen/asm/pal.h Tue Feb 13 19:16:46 2007 +0900 @@ -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-ia64-devel mailing list Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ia64-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |