Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2007 MIPS Technologies, Inc.  All rights reserved.
0007  * Copyright (C) 2013 Imagination Technologies Ltd.
0008  *
0009  * Arbitrary Monitor Interface
0010  */
0011 #include <linux/kernel.h>
0012 #include <linux/smp.h>
0013 
0014 #include <asm/addrspace.h>
0015 #include <asm/mipsmtregs.h>
0016 #include <asm/mips-boards/launch.h>
0017 #include <asm/vpe.h>
0018 
0019 int amon_cpu_avail(int cpu)
0020 {
0021     struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
0022 
0023     if (cpu < 0 || cpu >= NCPULAUNCH) {
0024         pr_debug("avail: cpu%d is out of range\n", cpu);
0025         return 0;
0026     }
0027 
0028     launch += cpu;
0029     if (!(launch->flags & LAUNCH_FREADY)) {
0030         pr_debug("avail: cpu%d is not ready\n", cpu);
0031         return 0;
0032     }
0033     if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
0034         pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
0035         return 0;
0036     }
0037 
0038     return 1;
0039 }
0040 
0041 int amon_cpu_start(int cpu,
0042             unsigned long pc, unsigned long sp,
0043             unsigned long gp, unsigned long a0)
0044 {
0045     volatile struct cpulaunch *launch =
0046         (struct cpulaunch  *)CKSEG0ADDR(CPULAUNCH);
0047 
0048     if (!amon_cpu_avail(cpu))
0049         return -1;
0050     if (cpu == smp_processor_id()) {
0051         pr_debug("launch: I am cpu%d!\n", cpu);
0052         return -1;
0053     }
0054     launch += cpu;
0055 
0056     pr_debug("launch: starting cpu%d\n", cpu);
0057 
0058     launch->pc = pc;
0059     launch->gp = gp;
0060     launch->sp = sp;
0061     launch->a0 = a0;
0062 
0063     smp_wmb();      /* Target must see parameters before go */
0064     launch->flags |= LAUNCH_FGO;
0065     smp_wmb();      /* Target must see go before we poll  */
0066 
0067     while ((launch->flags & LAUNCH_FGONE) == 0)
0068         ;
0069     smp_rmb();  /* Target will be updating flags soon */
0070     pr_debug("launch: cpu%d gone!\n", cpu);
0071 
0072     return 0;
0073 }
0074 
0075 #ifdef CONFIG_MIPS_VPE_LOADER_CMP
0076 int vpe_run(struct vpe *v)
0077 {
0078     struct vpe_notifications *n;
0079 
0080     if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
0081         return -1;
0082 
0083     list_for_each_entry(n, &v->notify, list)
0084         n->start(VPE_MODULE_MINOR);
0085 
0086     return 0;
0087 }
0088 #endif