cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smp.c (16683B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *	linux/arch/alpha/kernel/smp.c
      4 *
      5 *      2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com)
      6 *            Renamed modified smp_call_function to smp_call_function_on_cpu()
      7 *            Created an function that conforms to the old calling convention
      8 *            of smp_call_function().
      9 *
     10 *            This is helpful for DCPI.
     11 *
     12 */
     13
     14#include <linux/errno.h>
     15#include <linux/kernel.h>
     16#include <linux/kernel_stat.h>
     17#include <linux/module.h>
     18#include <linux/sched/mm.h>
     19#include <linux/mm.h>
     20#include <linux/err.h>
     21#include <linux/threads.h>
     22#include <linux/smp.h>
     23#include <linux/interrupt.h>
     24#include <linux/init.h>
     25#include <linux/delay.h>
     26#include <linux/spinlock.h>
     27#include <linux/irq.h>
     28#include <linux/cache.h>
     29#include <linux/profile.h>
     30#include <linux/bitops.h>
     31#include <linux/cpu.h>
     32
     33#include <asm/hwrpb.h>
     34#include <asm/ptrace.h>
     35#include <linux/atomic.h>
     36
     37#include <asm/io.h>
     38#include <asm/irq.h>
     39#include <asm/mmu_context.h>
     40#include <asm/tlbflush.h>
     41
     42#include "proto.h"
     43#include "irq_impl.h"
     44
     45
     46#define DEBUG_SMP 0
     47#if DEBUG_SMP
     48#define DBGS(args)	printk args
     49#else
     50#define DBGS(args)
     51#endif
     52
     53/* A collection of per-processor data.  */
     54struct cpuinfo_alpha cpu_data[NR_CPUS];
     55EXPORT_SYMBOL(cpu_data);
     56
     57/* A collection of single bit ipi messages.  */
     58static struct {
     59	unsigned long bits ____cacheline_aligned;
     60} ipi_data[NR_CPUS] __cacheline_aligned;
     61
     62enum ipi_message_type {
     63	IPI_RESCHEDULE,
     64	IPI_CALL_FUNC,
     65	IPI_CPU_STOP,
     66};
     67
     68/* Set to a secondary's cpuid when it comes online.  */
     69static int smp_secondary_alive = 0;
     70
     71int smp_num_probed;		/* Internal processor count */
     72int smp_num_cpus = 1;		/* Number that came online.  */
     73EXPORT_SYMBOL(smp_num_cpus);
     74
     75/*
     76 * Called by both boot and secondaries to move global data into
     77 *  per-processor storage.
     78 */
     79static inline void __init
     80smp_store_cpu_info(int cpuid)
     81{
     82	cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
     83	cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
     84	cpu_data[cpuid].need_new_asn = 0;
     85	cpu_data[cpuid].asn_lock = 0;
     86}
     87
     88/*
     89 * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
     90 */
     91static inline void __init
     92smp_setup_percpu_timer(int cpuid)
     93{
     94	cpu_data[cpuid].prof_counter = 1;
     95	cpu_data[cpuid].prof_multiplier = 1;
     96}
     97
     98static void __init
     99wait_boot_cpu_to_stop(int cpuid)
    100{
    101	unsigned long stop = jiffies + 10*HZ;
    102
    103	while (time_before(jiffies, stop)) {
    104	        if (!smp_secondary_alive)
    105			return;
    106		barrier();
    107	}
    108
    109	printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid);
    110	for (;;)
    111		barrier();
    112}
    113
    114/*
    115 * Where secondaries begin a life of C.
    116 */
    117void __init
    118smp_callin(void)
    119{
    120	int cpuid = hard_smp_processor_id();
    121
    122	if (cpu_online(cpuid)) {
    123		printk("??, cpu 0x%x already present??\n", cpuid);
    124		BUG();
    125	}
    126	set_cpu_online(cpuid, true);
    127
    128	/* Turn on machine checks.  */
    129	wrmces(7);
    130
    131	/* Set trap vectors.  */
    132	trap_init();
    133
    134	/* Set interrupt vector.  */
    135	wrent(entInt, 0);
    136
    137	/* Get our local ticker going. */
    138	smp_setup_percpu_timer(cpuid);
    139	init_clockevent();
    140
    141	/* Call platform-specific callin, if specified */
    142	if (alpha_mv.smp_callin)
    143		alpha_mv.smp_callin();
    144
    145	/* All kernel threads share the same mm context.  */
    146	mmgrab(&init_mm);
    147	current->active_mm = &init_mm;
    148
    149	/* inform the notifiers about the new cpu */
    150	notify_cpu_starting(cpuid);
    151
    152	/* Must have completely accurate bogos.  */
    153	local_irq_enable();
    154
    155	/* Wait boot CPU to stop with irq enabled before running
    156	   calibrate_delay. */
    157	wait_boot_cpu_to_stop(cpuid);
    158	mb();
    159	calibrate_delay();
    160
    161	smp_store_cpu_info(cpuid);
    162	/* Allow master to continue only after we written loops_per_jiffy.  */
    163	wmb();
    164	smp_secondary_alive = 1;
    165
    166	DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
    167	      cpuid, current, current->active_mm));
    168
    169	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
    170}
    171
    172/* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
    173static int
    174wait_for_txrdy (unsigned long cpumask)
    175{
    176	unsigned long timeout;
    177
    178	if (!(hwrpb->txrdy & cpumask))
    179		return 0;
    180
    181	timeout = jiffies + 10*HZ;
    182	while (time_before(jiffies, timeout)) {
    183		if (!(hwrpb->txrdy & cpumask))
    184			return 0;
    185		udelay(10);
    186		barrier();
    187	}
    188
    189	return -1;
    190}
    191
    192/*
    193 * Send a message to a secondary's console.  "START" is one such
    194 * interesting message.  ;-)
    195 */
    196static void
    197send_secondary_console_msg(char *str, int cpuid)
    198{
    199	struct percpu_struct *cpu;
    200	register char *cp1, *cp2;
    201	unsigned long cpumask;
    202	size_t len;
    203
    204	cpu = (struct percpu_struct *)
    205		((char*)hwrpb
    206		 + hwrpb->processor_offset
    207		 + cpuid * hwrpb->processor_size);
    208
    209	cpumask = (1UL << cpuid);
    210	if (wait_for_txrdy(cpumask))
    211		goto timeout;
    212
    213	cp2 = str;
    214	len = strlen(cp2);
    215	*(unsigned int *)&cpu->ipc_buffer[0] = len;
    216	cp1 = (char *) &cpu->ipc_buffer[1];
    217	memcpy(cp1, cp2, len);
    218
    219	/* atomic test and set */
    220	wmb();
    221	set_bit(cpuid, &hwrpb->rxrdy);
    222
    223	if (wait_for_txrdy(cpumask))
    224		goto timeout;
    225	return;
    226
    227 timeout:
    228	printk("Processor %x not ready\n", cpuid);
    229}
    230
    231/*
    232 * A secondary console wants to send a message.  Receive it.
    233 */
    234static void
    235recv_secondary_console_msg(void)
    236{
    237	int mycpu, i, cnt;
    238	unsigned long txrdy = hwrpb->txrdy;
    239	char *cp1, *cp2, buf[80];
    240	struct percpu_struct *cpu;
    241
    242	DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy));
    243
    244	mycpu = hard_smp_processor_id();
    245
    246	for (i = 0; i < NR_CPUS; i++) {
    247		if (!(txrdy & (1UL << i)))
    248			continue;
    249
    250		DBGS(("recv_secondary_console_msg: "
    251		      "TXRDY contains CPU %d.\n", i));
    252
    253		cpu = (struct percpu_struct *)
    254		  ((char*)hwrpb
    255		   + hwrpb->processor_offset
    256		   + i * hwrpb->processor_size);
    257
    258 		DBGS(("recv_secondary_console_msg: on %d from %d"
    259		      " HALT_REASON 0x%lx FLAGS 0x%lx\n",
    260		      mycpu, i, cpu->halt_reason, cpu->flags));
    261
    262		cnt = cpu->ipc_buffer[0] >> 32;
    263		if (cnt <= 0 || cnt >= 80)
    264			strcpy(buf, "<<< BOGUS MSG >>>");
    265		else {
    266			cp1 = (char *) &cpu->ipc_buffer[1];
    267			cp2 = buf;
    268			memcpy(cp2, cp1, cnt);
    269			cp2[cnt] = '\0';
    270			
    271			while ((cp2 = strchr(cp2, '\r')) != 0) {
    272				*cp2 = ' ';
    273				if (cp2[1] == '\n')
    274					cp2[1] = ' ';
    275			}
    276		}
    277
    278		DBGS((KERN_INFO "recv_secondary_console_msg: on %d "
    279		      "message is '%s'\n", mycpu, buf));
    280	}
    281
    282	hwrpb->txrdy = 0;
    283}
    284
    285/*
    286 * Convince the console to have a secondary cpu begin execution.
    287 */
    288static int
    289secondary_cpu_start(int cpuid, struct task_struct *idle)
    290{
    291	struct percpu_struct *cpu;
    292	struct pcb_struct *hwpcb, *ipcb;
    293	unsigned long timeout;
    294	  
    295	cpu = (struct percpu_struct *)
    296		((char*)hwrpb
    297		 + hwrpb->processor_offset
    298		 + cpuid * hwrpb->processor_size);
    299	hwpcb = (struct pcb_struct *) cpu->hwpcb;
    300	ipcb = &task_thread_info(idle)->pcb;
    301
    302	/* Initialize the CPU's HWPCB to something just good enough for
    303	   us to get started.  Immediately after starting, we'll swpctx
    304	   to the target idle task's pcb.  Reuse the stack in the mean
    305	   time.  Precalculate the target PCBB.  */
    306	hwpcb->ksp = (unsigned long)ipcb + sizeof(union thread_union) - 16;
    307	hwpcb->usp = 0;
    308	hwpcb->ptbr = ipcb->ptbr;
    309	hwpcb->pcc = 0;
    310	hwpcb->asn = 0;
    311	hwpcb->unique = virt_to_phys(ipcb);
    312	hwpcb->flags = ipcb->flags;
    313	hwpcb->res1 = hwpcb->res2 = 0;
    314
    315#if 0
    316	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
    317	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique));
    318#endif
    319	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
    320	      cpuid, idle->state, ipcb->flags));
    321
    322	/* Setup HWRPB fields that SRM uses to activate secondary CPU */
    323	hwrpb->CPU_restart = __smp_callin;
    324	hwrpb->CPU_restart_data = (unsigned long) __smp_callin;
    325
    326	/* Recalculate and update the HWRPB checksum */
    327	hwrpb_update_checksum(hwrpb);
    328
    329	/*
    330	 * Send a "start" command to the specified processor.
    331	 */
    332
    333	/* SRM III 3.4.1.3 */
    334	cpu->flags |= 0x22;	/* turn on Context Valid and Restart Capable */
    335	cpu->flags &= ~1;	/* turn off Bootstrap In Progress */
    336	wmb();
    337
    338	send_secondary_console_msg("START\r\n", cpuid);
    339
    340	/* Wait 10 seconds for an ACK from the console.  */
    341	timeout = jiffies + 10*HZ;
    342	while (time_before(jiffies, timeout)) {
    343		if (cpu->flags & 1)
    344			goto started;
    345		udelay(10);
    346		barrier();
    347	}
    348	printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid);
    349	return -1;
    350
    351 started:
    352	DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
    353	return 0;
    354}
    355
    356/*
    357 * Bring one cpu online.
    358 */
    359static int
    360smp_boot_one_cpu(int cpuid, struct task_struct *idle)
    361{
    362	unsigned long timeout;
    363
    364	/* Signal the secondary to wait a moment.  */
    365	smp_secondary_alive = -1;
    366
    367	/* Whirrr, whirrr, whirrrrrrrrr... */
    368	if (secondary_cpu_start(cpuid, idle))
    369		return -1;
    370
    371	/* Notify the secondary CPU it can run calibrate_delay.  */
    372	mb();
    373	smp_secondary_alive = 0;
    374
    375	/* We've been acked by the console; wait one second for
    376	   the task to start up for real.  */
    377	timeout = jiffies + 1*HZ;
    378	while (time_before(jiffies, timeout)) {
    379		if (smp_secondary_alive == 1)
    380			goto alive;
    381		udelay(10);
    382		barrier();
    383	}
    384
    385	/* We failed to boot the CPU.  */
    386
    387	printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
    388	return -1;
    389
    390 alive:
    391	/* Another "Red Snapper". */
    392	return 0;
    393}
    394
    395/*
    396 * Called from setup_arch.  Detect an SMP system and which processors
    397 * are present.
    398 */
    399void __init
    400setup_smp(void)
    401{
    402	struct percpu_struct *cpubase, *cpu;
    403	unsigned long i;
    404
    405	if (boot_cpuid != 0) {
    406		printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n",
    407		       boot_cpuid);
    408	}
    409
    410	if (hwrpb->nr_processors > 1) {
    411		int boot_cpu_palrev;
    412
    413		DBGS(("setup_smp: nr_processors %ld\n",
    414		      hwrpb->nr_processors));
    415
    416		cpubase = (struct percpu_struct *)
    417			((char*)hwrpb + hwrpb->processor_offset);
    418		boot_cpu_palrev = cpubase->pal_revision;
    419
    420		for (i = 0; i < hwrpb->nr_processors; i++) {
    421			cpu = (struct percpu_struct *)
    422				((char *)cpubase + i*hwrpb->processor_size);
    423			if ((cpu->flags & 0x1cc) == 0x1cc) {
    424				smp_num_probed++;
    425				set_cpu_possible(i, true);
    426				set_cpu_present(i, true);
    427				cpu->pal_revision = boot_cpu_palrev;
    428			}
    429
    430			DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
    431			      i, cpu->flags, cpu->type));
    432			DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
    433			      i, cpu->pal_revision));
    434		}
    435	} else {
    436		smp_num_probed = 1;
    437	}
    438
    439	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
    440	       smp_num_probed, cpumask_bits(cpu_present_mask)[0]);
    441}
    442
    443/*
    444 * Called by smp_init prepare the secondaries
    445 */
    446void __init
    447smp_prepare_cpus(unsigned int max_cpus)
    448{
    449	/* Take care of some initial bookkeeping.  */
    450	memset(ipi_data, 0, sizeof(ipi_data));
    451
    452	current_thread_info()->cpu = boot_cpuid;
    453
    454	smp_store_cpu_info(boot_cpuid);
    455	smp_setup_percpu_timer(boot_cpuid);
    456
    457	/* Nothing to do on a UP box, or when told not to.  */
    458	if (smp_num_probed == 1 || max_cpus == 0) {
    459		init_cpu_possible(cpumask_of(boot_cpuid));
    460		init_cpu_present(cpumask_of(boot_cpuid));
    461		printk(KERN_INFO "SMP mode deactivated.\n");
    462		return;
    463	}
    464
    465	printk(KERN_INFO "SMP starting up secondaries.\n");
    466
    467	smp_num_cpus = smp_num_probed;
    468}
    469
    470void
    471smp_prepare_boot_cpu(void)
    472{
    473}
    474
    475int
    476__cpu_up(unsigned int cpu, struct task_struct *tidle)
    477{
    478	smp_boot_one_cpu(cpu, tidle);
    479
    480	return cpu_online(cpu) ? 0 : -ENOSYS;
    481}
    482
    483void __init
    484smp_cpus_done(unsigned int max_cpus)
    485{
    486	int cpu;
    487	unsigned long bogosum = 0;
    488
    489	for(cpu = 0; cpu < NR_CPUS; cpu++) 
    490		if (cpu_online(cpu))
    491			bogosum += cpu_data[cpu].loops_per_jiffy;
    492	
    493	printk(KERN_INFO "SMP: Total of %d processors activated "
    494	       "(%lu.%02lu BogoMIPS).\n",
    495	       num_online_cpus(), 
    496	       (bogosum + 2500) / (500000/HZ),
    497	       ((bogosum + 2500) / (5000/HZ)) % 100);
    498}
    499
    500int
    501setup_profiling_timer(unsigned int multiplier)
    502{
    503	return -EINVAL;
    504}
    505
    506static void
    507send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
    508{
    509	int i;
    510
    511	mb();
    512	for_each_cpu(i, to_whom)
    513		set_bit(operation, &ipi_data[i].bits);
    514
    515	mb();
    516	for_each_cpu(i, to_whom)
    517		wripir(i);
    518}
    519
    520void
    521handle_ipi(struct pt_regs *regs)
    522{
    523	int this_cpu = smp_processor_id();
    524	unsigned long *pending_ipis = &ipi_data[this_cpu].bits;
    525	unsigned long ops;
    526
    527#if 0
    528	DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
    529	      this_cpu, *pending_ipis, regs->pc));
    530#endif
    531
    532	mb();	/* Order interrupt and bit testing. */
    533	while ((ops = xchg(pending_ipis, 0)) != 0) {
    534	  mb();	/* Order bit clearing and data access. */
    535	  do {
    536		unsigned long which;
    537
    538		which = ops & -ops;
    539		ops &= ~which;
    540		which = __ffs(which);
    541
    542		switch (which) {
    543		case IPI_RESCHEDULE:
    544			scheduler_ipi();
    545			break;
    546
    547		case IPI_CALL_FUNC:
    548			generic_smp_call_function_interrupt();
    549			break;
    550
    551		case IPI_CPU_STOP:
    552			halt();
    553
    554		default:
    555			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
    556			       this_cpu, which);
    557			break;
    558		}
    559	  } while (ops);
    560
    561	  mb();	/* Order data access and bit testing. */
    562	}
    563
    564	cpu_data[this_cpu].ipi_count++;
    565
    566	if (hwrpb->txrdy)
    567		recv_secondary_console_msg();
    568}
    569
    570void
    571smp_send_reschedule(int cpu)
    572{
    573#ifdef DEBUG_IPI_MSG
    574	if (cpu == hard_smp_processor_id())
    575		printk(KERN_WARNING
    576		       "smp_send_reschedule: Sending IPI to self.\n");
    577#endif
    578	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
    579}
    580
    581void
    582smp_send_stop(void)
    583{
    584	cpumask_t to_whom;
    585	cpumask_copy(&to_whom, cpu_online_mask);
    586	cpumask_clear_cpu(smp_processor_id(), &to_whom);
    587#ifdef DEBUG_IPI_MSG
    588	if (hard_smp_processor_id() != boot_cpu_id)
    589		printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n");
    590#endif
    591	send_ipi_message(&to_whom, IPI_CPU_STOP);
    592}
    593
    594void arch_send_call_function_ipi_mask(const struct cpumask *mask)
    595{
    596	send_ipi_message(mask, IPI_CALL_FUNC);
    597}
    598
    599void arch_send_call_function_single_ipi(int cpu)
    600{
    601	send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
    602}
    603
    604static void
    605ipi_imb(void *ignored)
    606{
    607	imb();
    608}
    609
    610void
    611smp_imb(void)
    612{
    613	/* Must wait other processors to flush their icache before continue. */
    614	on_each_cpu(ipi_imb, NULL, 1);
    615}
    616EXPORT_SYMBOL(smp_imb);
    617
    618static void
    619ipi_flush_tlb_all(void *ignored)
    620{
    621	tbia();
    622}
    623
    624void
    625flush_tlb_all(void)
    626{
    627	/* Although we don't have any data to pass, we do want to
    628	   synchronize with the other processors.  */
    629	on_each_cpu(ipi_flush_tlb_all, NULL, 1);
    630}
    631
    632#define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
    633
    634static void
    635ipi_flush_tlb_mm(void *x)
    636{
    637	struct mm_struct *mm = (struct mm_struct *) x;
    638	if (mm == current->active_mm && !asn_locked())
    639		flush_tlb_current(mm);
    640	else
    641		flush_tlb_other(mm);
    642}
    643
    644void
    645flush_tlb_mm(struct mm_struct *mm)
    646{
    647	preempt_disable();
    648
    649	if (mm == current->active_mm) {
    650		flush_tlb_current(mm);
    651		if (atomic_read(&mm->mm_users) <= 1) {
    652			int cpu, this_cpu = smp_processor_id();
    653			for (cpu = 0; cpu < NR_CPUS; cpu++) {
    654				if (!cpu_online(cpu) || cpu == this_cpu)
    655					continue;
    656				if (mm->context[cpu])
    657					mm->context[cpu] = 0;
    658			}
    659			preempt_enable();
    660			return;
    661		}
    662	}
    663
    664	smp_call_function(ipi_flush_tlb_mm, mm, 1);
    665
    666	preempt_enable();
    667}
    668EXPORT_SYMBOL(flush_tlb_mm);
    669
    670struct flush_tlb_page_struct {
    671	struct vm_area_struct *vma;
    672	struct mm_struct *mm;
    673	unsigned long addr;
    674};
    675
    676static void
    677ipi_flush_tlb_page(void *x)
    678{
    679	struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
    680	struct mm_struct * mm = data->mm;
    681
    682	if (mm == current->active_mm && !asn_locked())
    683		flush_tlb_current_page(mm, data->vma, data->addr);
    684	else
    685		flush_tlb_other(mm);
    686}
    687
    688void
    689flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
    690{
    691	struct flush_tlb_page_struct data;
    692	struct mm_struct *mm = vma->vm_mm;
    693
    694	preempt_disable();
    695
    696	if (mm == current->active_mm) {
    697		flush_tlb_current_page(mm, vma, addr);
    698		if (atomic_read(&mm->mm_users) <= 1) {
    699			int cpu, this_cpu = smp_processor_id();
    700			for (cpu = 0; cpu < NR_CPUS; cpu++) {
    701				if (!cpu_online(cpu) || cpu == this_cpu)
    702					continue;
    703				if (mm->context[cpu])
    704					mm->context[cpu] = 0;
    705			}
    706			preempt_enable();
    707			return;
    708		}
    709	}
    710
    711	data.vma = vma;
    712	data.mm = mm;
    713	data.addr = addr;
    714
    715	smp_call_function(ipi_flush_tlb_page, &data, 1);
    716
    717	preempt_enable();
    718}
    719EXPORT_SYMBOL(flush_tlb_page);
    720
    721void
    722flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
    723{
    724	/* On the Alpha we always flush the whole user tlb.  */
    725	flush_tlb_mm(vma->vm_mm);
    726}
    727EXPORT_SYMBOL(flush_tlb_range);
    728
    729static void
    730ipi_flush_icache_page(void *x)
    731{
    732	struct mm_struct *mm = (struct mm_struct *) x;
    733	if (mm == current->active_mm && !asn_locked())
    734		__load_new_mm_context(mm);
    735	else
    736		flush_tlb_other(mm);
    737}
    738
    739void
    740flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
    741			unsigned long addr, int len)
    742{
    743	struct mm_struct *mm = vma->vm_mm;
    744
    745	if ((vma->vm_flags & VM_EXEC) == 0)
    746		return;
    747
    748	preempt_disable();
    749
    750	if (mm == current->active_mm) {
    751		__load_new_mm_context(mm);
    752		if (atomic_read(&mm->mm_users) <= 1) {
    753			int cpu, this_cpu = smp_processor_id();
    754			for (cpu = 0; cpu < NR_CPUS; cpu++) {
    755				if (!cpu_online(cpu) || cpu == this_cpu)
    756					continue;
    757				if (mm->context[cpu])
    758					mm->context[cpu] = 0;
    759			}
    760			preempt_enable();
    761			return;
    762		}
    763	}
    764
    765	smp_call_function(ipi_flush_icache_page, mm, 1);
    766
    767	preempt_enable();
    768}