diff options
Diffstat (limited to 'arch/sparc/kernel/smp_64.c')
| -rw-r--r-- | arch/sparc/kernel/smp_64.c | 43 | 
1 files changed, 39 insertions, 4 deletions
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 537eb66abd0..77539eda928 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -127,6 +127,8 @@ void __cpuinit smp_callin(void)  	/* idle thread is expected to have preempt disabled */  	preempt_disable(); + +	cpu_startup_entry(CPUHP_ONLINE);  }  void cpu_panic(void) @@ -849,7 +851,7 @@ void smp_tsb_sync(struct mm_struct *mm)  }  extern unsigned long xcall_flush_tlb_mm; -extern unsigned long xcall_flush_tlb_pending; +extern unsigned long xcall_flush_tlb_page;  extern unsigned long xcall_flush_tlb_kernel_range;  extern unsigned long xcall_fetch_glob_regs;  extern unsigned long xcall_fetch_glob_pmu; @@ -1074,23 +1076,56 @@ local_flush_and_out:  	put_cpu();  } +struct tlb_pending_info { +	unsigned long ctx; +	unsigned long nr; +	unsigned long *vaddrs; +}; + +static void tlb_pending_func(void *info) +{ +	struct tlb_pending_info *t = info; + +	__flush_tlb_pending(t->ctx, t->nr, t->vaddrs); +} +  void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs)  {  	u32 ctx = CTX_HWBITS(mm->context); +	struct tlb_pending_info info;  	int cpu = get_cpu(); +	info.ctx = ctx; +	info.nr = nr; +	info.vaddrs = vaddrs; +  	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)  		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));  	else -		smp_cross_call_masked(&xcall_flush_tlb_pending, -				      ctx, nr, (unsigned long) vaddrs, -				      mm_cpumask(mm)); +		smp_call_function_many(mm_cpumask(mm), tlb_pending_func, +				       &info, 1);  	__flush_tlb_pending(ctx, nr, vaddrs);  	put_cpu();  } +void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) +{ +	unsigned long context = CTX_HWBITS(mm->context); +	int cpu = get_cpu(); + +	if (mm == current->mm && atomic_read(&mm->mm_users) == 1) +		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); +	else +		smp_cross_call_masked(&xcall_flush_tlb_page, +				      context, vaddr, 0, +				      mm_cpumask(mm)); +	__flush_tlb_page(context, vaddr); + +	put_cpu(); +} +  void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end)  {  	start &= PAGE_MASK;  |