Commit | Line | Data |
---|---|---|
39b8d525 | 1 | /* |
5792bf64 SH |
2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
39b8d525 | 5 | * |
5792bf64 SH |
6 | * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved. |
7 | * Copyright (C) 2013 Imagination Technologies Ltd. | |
39b8d525 | 8 | * |
5792bf64 | 9 | * Arbitrary Monitor Interface |
39b8d525 | 10 | */ |
39b8d525 | 11 | #include <linux/kernel.h> |
39b8d525 RB |
12 | #include <linux/smp.h> |
13 | ||
9e86786a | 14 | #include <asm/addrspace.h> |
9e86786a | 15 | #include <asm/mipsmtregs.h> |
5792bf64 | 16 | #include <asm/mips-boards/launch.h> |
1336113a | 17 | #include <asm/vpe.h> |
39b8d525 RB |
18 | |
19 | int amon_cpu_avail(int cpu) | |
20 | { | |
938b2b14 | 21 | struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); |
39b8d525 RB |
22 | |
23 | if (cpu < 0 || cpu >= NCPULAUNCH) { | |
24 | pr_debug("avail: cpu%d is out of range\n", cpu); | |
25 | return 0; | |
26 | } | |
27 | ||
28 | launch += cpu; | |
29 | if (!(launch->flags & LAUNCH_FREADY)) { | |
30 | pr_debug("avail: cpu%d is not ready\n", cpu); | |
31 | return 0; | |
32 | } | |
33 | if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) { | |
34 | pr_debug("avail: too late.. cpu%d is already gone\n", cpu); | |
35 | return 0; | |
36 | } | |
37 | ||
38 | return 1; | |
39 | } | |
40 | ||
1336113a | 41 | int amon_cpu_start(int cpu, |
39b8d525 RB |
42 | unsigned long pc, unsigned long sp, |
43 | unsigned long gp, unsigned long a0) | |
44 | { | |
45 | volatile struct cpulaunch *launch = | |
938b2b14 | 46 | (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); |
39b8d525 RB |
47 | |
48 | if (!amon_cpu_avail(cpu)) | |
1336113a | 49 | return -1; |
39b8d525 RB |
50 | if (cpu == smp_processor_id()) { |
51 | pr_debug("launch: I am cpu%d!\n", cpu); | |
1336113a | 52 | return -1; |
39b8d525 RB |
53 | } |
54 | launch += cpu; | |
55 | ||
56 | pr_debug("launch: starting cpu%d\n", cpu); | |
57 | ||
58 | launch->pc = pc; | |
59 | launch->gp = gp; | |
60 | launch->sp = sp; | |
61 | launch->a0 = a0; | |
62 | ||
70342287 | 63 | smp_wmb(); /* Target must see parameters before go */ |
39b8d525 | 64 | launch->flags |= LAUNCH_FGO; |
70342287 | 65 | smp_wmb(); /* Target must see go before we poll */ |
2ee0a429 | 66 | |
39b8d525 RB |
67 | while ((launch->flags & LAUNCH_FGONE) == 0) |
68 | ; | |
70342287 | 69 | smp_rmb(); /* Target will be updating flags soon */ |
39b8d525 | 70 | pr_debug("launch: cpu%d gone!\n", cpu); |
1336113a DCZ |
71 | |
72 | return 0; | |
73 | } | |
74 | ||
031365b4 | 75 | #ifdef CONFIG_MIPS_VPE_LOADER_CMP |
1336113a DCZ |
76 | int vpe_run(struct vpe *v) |
77 | { | |
78 | struct vpe_notifications *n; | |
79 | ||
80 | if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0) | |
81 | return -1; | |
82 | ||
83 | list_for_each_entry(n, &v->notify, list) | |
84 | n->start(VPE_MODULE_MINOR); | |
85 | ||
86 | return 0; | |
39b8d525 | 87 | } |
1336113a | 88 | #endif |