ia64/xen-unstable

changeset 15377:c20bc60f9243

[IA64] sn2 global_tlb_purge implementation

Very simple global tlb purge implementation for SN2. ptcga isn't
propagated between nodes so IPI a CPU on each node to get the job
done. This is _slow_ and inefficient, but it works for now.

Signed-off-by: Jes Sorensen <jes@sgi.com>
author Alex Williamson <alex.williamson@hp.com>
date Wed Jun 20 12:47:52 2007 -0600 (2007-06-20)
parents 39a95178edbf
children 810885428743
files xen/arch/ia64/linux-xen/sn/kernel/sn2_smp.c
line diff
     1.1 --- a/xen/arch/ia64/linux-xen/sn/kernel/sn2_smp.c	Tue Jun 19 15:17:20 2007 -0600
     1.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/sn2_smp.c	Wed Jun 20 12:47:52 2007 -0600
     1.3 @@ -160,21 +160,97 @@ void sn_tlb_migrate_finish(struct mm_str
     1.4  // static cpumask_t mask_all = CPU_MASK_ALL;
     1.5  #endif
     1.6  
     1.7 +#ifdef XEN
     1.8 +static DEFINE_SPINLOCK(sn2_ptcg_lock);
     1.9 +
    1.10 +struct sn_flush_struct {
    1.11 +	unsigned long start;
    1.12 +	unsigned long end;
    1.13 +	unsigned long nbits;
    1.14 +};
    1.15 +
    1.16 +static void sn_flush_ptcga_cpu(void *ptr)
    1.17 +{
    1.18 +	struct sn_flush_struct *sn_flush = ptr;
    1.19 +	unsigned long start, end, nbits;
    1.20 +
    1.21 +	start = sn_flush->start;
    1.22 +	end = sn_flush->end;
    1.23 +	nbits = sn_flush->nbits;
    1.24 +
    1.25 +	/*
    1.26 +	 * Contention me harder!!!
    1.27 +	 */
    1.28 +	/* HW requires global serialization of ptc.ga.  */
    1.29 +	spin_lock(&sn2_ptcg_lock);
    1.30 +	{
    1.31 +		do {
    1.32 +			/*
    1.33 +			 * Flush ALAT entries also.
    1.34 +			 */
    1.35 +			ia64_ptcga(start, (nbits<<2));
    1.36 +			ia64_srlz_i();
    1.37 +			start += (1UL << nbits);
    1.38 +		} while (start < end);
    1.39 +	}
    1.40 +	spin_unlock(&sn2_ptcg_lock);
    1.41 +}
    1.42 +
    1.43  void
    1.44 -#ifndef XEN
    1.45 +sn2_global_tlb_purge(unsigned long start,
    1.46 +		     unsigned long end, unsigned long nbits)
    1.47 +{
    1.48 +	nodemask_t nodes_flushed;
    1.49 +	cpumask_t selected_cpus;
    1.50 +	int cpu, cnode, i;
    1.51 +	static DEFINE_SPINLOCK(sn2_ptcg_lock2);
    1.52 +
    1.53 +	nodes_clear(nodes_flushed);
    1.54 +	cpus_clear(selected_cpus);
    1.55 +
    1.56 +	spin_lock(&sn2_ptcg_lock2);
    1.57 +	node_set(cpu_to_node(smp_processor_id()), nodes_flushed);
    1.58 +	i = 0;
    1.59 +	for_each_cpu(cpu) {
    1.60 +		cnode = cpu_to_node(cpu);
    1.61 +		if (!node_isset(cnode, nodes_flushed)) {
    1.62 +			cpu_set(cpu, selected_cpus);
    1.63 +			i++;
    1.64 +		}
    1.65 +		node_set(cnode, nodes_flushed);
    1.66 +	}
    1.67 +
    1.68 +	/* HW requires global serialization of ptc.ga.  */
    1.69 +	spin_lock(&sn2_ptcg_lock);
    1.70 +	{
    1.71 +		do {
    1.72 +			/*
    1.73 +			 * Flush ALAT entries also.
    1.74 +			 */
    1.75 +			ia64_ptcga(start, (nbits<<2));
    1.76 +			ia64_srlz_i();
    1.77 +			start += (1UL << nbits);
    1.78 +		} while (start < end);
    1.79 +	}
    1.80 +	spin_unlock(&sn2_ptcg_lock);
    1.81 +
    1.82 +	if (i) {
    1.83 +		struct sn_flush_struct flush_data;
    1.84 +		flush_data.start = start;
    1.85 +		flush_data.end = end;
    1.86 +		flush_data.nbits = nbits;
    1.87 +		on_selected_cpus(selected_cpus, sn_flush_ptcga_cpu,
    1.88 +				 &flush_data, 1, 1);
    1.89 +	}
    1.90 +	spin_unlock(&sn2_ptcg_lock2);
    1.91 +}
    1.92 +#else
    1.93 +void
    1.94  sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
    1.95 -#else
    1.96 -sn2_global_tlb_purge(unsigned long start,
    1.97 -#endif
    1.98  		     unsigned long end, unsigned long nbits)
    1.99  {
   1.100  	int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid;
   1.101 -#ifndef XEN
   1.102  	int mymm = (mm == current->active_mm && mm == current->mm);
   1.103 -#else
   1.104 -	// struct mm_struct *mm;
   1.105 -	int mymm = 0;
   1.106 -#endif
   1.107  	int use_cpu_ptcga;
   1.108  	volatile unsigned long *ptc0, *ptc1;
   1.109  	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
   1.110 @@ -206,6 +282,7 @@ sn2_global_tlb_purge(unsigned long start
   1.111  
   1.112  	preempt_disable();
   1.113  
   1.114 +#ifndef XEN
   1.115  	if (likely(i == 1 && lcpu == smp_processor_id() && mymm)) {
   1.116  		do {
   1.117  			ia64_ptcl(start, nbits << 2);
   1.118 @@ -217,13 +294,8 @@ sn2_global_tlb_purge(unsigned long start
   1.119  		return;
   1.120  	}
   1.121  
   1.122 -#ifndef XEN
   1.123  	if (atomic_read(&mm->mm_users) == 1 && mymm) {
   1.124 -#ifndef XEN  /* I hate Xen! */
   1.125  		flush_tlb_mm(mm);
   1.126 -#else
   1.127 -		flush_tlb_mask(mask_all);
   1.128 -#endif
   1.129  		__get_cpu_var(ptcstats).change_rid++;
   1.130  		preempt_enable();
   1.131  		return;
   1.132 @@ -335,6 +407,7 @@ sn2_global_tlb_purge(unsigned long start
   1.133  
   1.134  	preempt_enable();
   1.135  }
   1.136 +#endif
   1.137  
   1.138  /*
   1.139   * sn2_ptc_deadlock_recovery