ia64/xen-unstable

changeset 13905:2b3dd681dbce

[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@jp.fujitsu.com>
author awilliam@xenbuild2.aw
date Thu Feb 15 10:25:33 2007 -0700 (2007-02-15)
parents 6c63ff548888
children eb6c19ed6e67
files xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/fw_emul.c xen/include/asm-ia64/domain.h xen/include/asm-ia64/linux-xen/asm/pal.h
line diff
     1.1 --- a/xen/arch/ia64/xen/domain.c	Wed Feb 14 10:14:37 2007 -0700
     1.2 +++ b/xen/arch/ia64/xen/domain.c	Thu Feb 15 10:25:33 2007 -0700
     1.3 @@ -138,6 +138,28 @@ static void flush_vtlb_for_context_switc
     1.4  	}
     1.5  }
     1.6  
     1.7 +static void flush_cache_for_context_switch(struct vcpu *next)
     1.8 +{
     1.9 +	extern cpumask_t cpu_cache_coherent_map;
    1.10 +	int cpu = smp_processor_id();
    1.11 +
    1.12 +	if (is_idle_vcpu(next) ||
    1.13 +	    __test_and_clear_bit(cpu, &next->arch.cache_coherent_map)) {
    1.14 +		if (cpu_test_and_clear(cpu, cpu_cache_coherent_map)) {
    1.15 +			unsigned long flags;
    1.16 +			u64 progress = 0;
    1.17 +			s64 status;
    1.18 +
    1.19 +			local_irq_save(flags);
    1.20 +			status = ia64_pal_cache_flush(4, 0, &progress, NULL);
    1.21 +			local_irq_restore(flags);
    1.22 +			if (status != 0)
    1.23 +				panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
    1.24 +					     "cache_type=4 status %lx", status);
    1.25 +		}
    1.26 +	}
    1.27 +}
    1.28 +
    1.29  static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next)
    1.30  {
    1.31  	/*
    1.32 @@ -260,6 +282,7 @@ void context_switch(struct vcpu *prev, s
    1.33      }
    1.34     
    1.35      flush_vtlb_for_context_switch(prev, current);
    1.36 +    flush_cache_for_context_switch(current);
    1.37      context_saved(prev);
    1.38  }
    1.39  
     2.1 --- a/xen/arch/ia64/xen/fw_emul.c	Wed Feb 14 10:14:37 2007 -0700
     2.2 +++ b/xen/arch/ia64/xen/fw_emul.c	Thu Feb 15 10:25:33 2007 -0700
     2.3 @@ -379,6 +379,28 @@ sal_emulator (long index, unsigned long 
     2.4  	return ((struct sal_ret_values) {status, r9, r10, r11});
     2.5  }
     2.6  
     2.7 +cpumask_t cpu_cache_coherent_map;
     2.8 +
     2.9 +struct cache_flush_args {
    2.10 +	u64 cache_type;
    2.11 +	u64 operation;
    2.12 +	u64 progress;
    2.13 +	long status;
    2.14 +};
    2.15 +
    2.16 +static void
    2.17 +remote_pal_cache_flush(void *v)
    2.18 +{
    2.19 +	struct cache_flush_args *args = v;
    2.20 +	long status;
    2.21 +	u64 progress = args->progress;
    2.22 +
    2.23 +	status = ia64_pal_cache_flush(args->cache_type, args->operation,
    2.24 +				      &progress, NULL);
    2.25 +	if (status != 0)
    2.26 +		args->status = status;
    2.27 +}
    2.28 +
    2.29  struct ia64_pal_retval
    2.30  xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
    2.31  {
    2.32 @@ -542,9 +564,27 @@ xen_pal_emulator(unsigned long index, u6
    2.33  		status = ia64_pal_register_info(in1, &r9, &r10);
    2.34  		break;
    2.35  	    case PAL_CACHE_FLUSH:
    2.36 +		if (in3 != 0) /* Initially progress_indicator must be 0 */
    2.37 +			panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
    2.38 +				     "progress_indicator=%lx", in3);
    2.39 +
    2.40  		/* Always call Host Pal in int=0 */
    2.41  		in2 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
    2.42  
    2.43 +		if (in1 != PAL_CACHE_TYPE_COHERENT) {
    2.44 +			struct cache_flush_args args = {
    2.45 +				.cache_type = in1,
    2.46 +				.operation = in2,
    2.47 +				.progress = 0,
    2.48 +				.status = 0
    2.49 +			};
    2.50 +			smp_call_function(remote_pal_cache_flush,
    2.51 +					  (void *)&args, 1, 1);
    2.52 +			if (args.status != 0)
    2.53 +				panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
    2.54 +					     "remote status %lx", args.status);
    2.55 +		}
    2.56 +
    2.57  		/*
    2.58  		 * Call Host PAL cache flush
    2.59  		 * Clear psr.ic when call PAL_CACHE_FLUSH
    2.60 @@ -556,6 +596,13 @@ xen_pal_emulator(unsigned long index, u6
    2.61  			panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
    2.62  			             "status %lx", status);
    2.63  
    2.64 +		if (in1 == PAL_CACHE_TYPE_COHERENT) {
    2.65 +			int cpu = current->processor;
    2.66 +			cpus_setall(current->arch.cache_coherent_map);
    2.67 +			cpu_clear(cpu, current->arch.cache_coherent_map);
    2.68 +			cpus_setall(cpu_cache_coherent_map);
    2.69 +			cpu_clear(cpu, cpu_cache_coherent_map);
    2.70 +		}
    2.71  		break;
    2.72  	    case PAL_PERF_MON_INFO:
    2.73  		{
     3.1 --- a/xen/include/asm-ia64/domain.h	Wed Feb 14 10:14:37 2007 -0700
     3.2 +++ b/xen/include/asm-ia64/domain.h	Thu Feb 15 10:25:33 2007 -0700
     3.3 @@ -201,6 +201,7 @@ struct arch_vcpu {
     3.4  #endif
     3.5  #define INVALID_PROCESSOR       INT_MAX
     3.6      int last_processor;
     3.7 +    cpumask_t cache_coherent_map;
     3.8  };
     3.9  
    3.10  #include <asm/uaccess.h> /* for KERNEL_DS */
     4.1 --- a/xen/include/asm-ia64/linux-xen/asm/pal.h	Wed Feb 14 10:14:37 2007 -0700
     4.2 +++ b/xen/include/asm-ia64/linux-xen/asm/pal.h	Thu Feb 15 10:25:33 2007 -0700
     4.3 @@ -112,6 +112,9 @@ typedef u64				pal_cache_type_t;
     4.4  #define PAL_CACHE_TYPE_INSTRUCTION	1	/* Instruction cache */
     4.5  #define PAL_CACHE_TYPE_DATA		2	/* Data or unified cache */
     4.6  #define PAL_CACHE_TYPE_INSTRUCTION_DATA	3	/* Both Data & Instruction */
     4.7 +#ifdef XEN
     4.8 +#define PAL_CACHE_TYPE_COHERENT		4	/* Make I&D-cache coherent */
     4.9 +#endif
    4.10  
    4.11  
    4.12  #define PAL_CACHE_FLUSH_INVALIDATE	1	/* Invalidate clean lines */