1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (c) 2013-2016 Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker *
12*344aa361SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker *
15*344aa361SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker */
23*344aa361SAndroid Build Coastguard Worker
24*344aa361SAndroid Build Coastguard Worker #include <err.h>
25*344aa361SAndroid Build Coastguard Worker #include <kernel/event.h>
26*344aa361SAndroid Build Coastguard Worker #include <kernel/mutex.h>
27*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
28*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
29*344aa361SAndroid Build Coastguard Worker #include <lib/heap.h>
30*344aa361SAndroid Build Coastguard Worker #include <lib/sm.h>
31*344aa361SAndroid Build Coastguard Worker #include <lib/sm/sm_err.h>
32*344aa361SAndroid Build Coastguard Worker #include <lib/sm/smcall.h>
33*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
34*344aa361SAndroid Build Coastguard Worker #include <platform.h>
35*344aa361SAndroid Build Coastguard Worker #include <stdatomic.h>
36*344aa361SAndroid Build Coastguard Worker #include <string.h>
37*344aa361SAndroid Build Coastguard Worker #include <sys/types.h>
38*344aa361SAndroid Build Coastguard Worker #include <trace.h>
39*344aa361SAndroid Build Coastguard Worker #include <version.h>
40*344aa361SAndroid Build Coastguard Worker
41*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE 0
42*344aa361SAndroid Build Coastguard Worker
43*344aa361SAndroid Build Coastguard Worker struct sm_std_call_state {
44*344aa361SAndroid Build Coastguard Worker spin_lock_t lock;
45*344aa361SAndroid Build Coastguard Worker event_t event;
46*344aa361SAndroid Build Coastguard Worker struct smc32_args args;
47*344aa361SAndroid Build Coastguard Worker long ret;
48*344aa361SAndroid Build Coastguard Worker bool done;
49*344aa361SAndroid Build Coastguard Worker int active_cpu; /* cpu that expects stdcall result */
50*344aa361SAndroid Build Coastguard Worker int initial_cpu; /* Debug info: cpu that started stdcall */
51*344aa361SAndroid Build Coastguard Worker int last_cpu; /* Debug info: most recent cpu expecting stdcall result */
52*344aa361SAndroid Build Coastguard Worker int restart_count;
53*344aa361SAndroid Build Coastguard Worker };
54*344aa361SAndroid Build Coastguard Worker
55*344aa361SAndroid Build Coastguard Worker extern unsigned long monitor_vector_table;
56*344aa361SAndroid Build Coastguard Worker extern ulong lk_boot_args[4];
57*344aa361SAndroid Build Coastguard Worker
58*344aa361SAndroid Build Coastguard Worker static void* boot_args;
59*344aa361SAndroid Build Coastguard Worker static int boot_args_refcnt;
60*344aa361SAndroid Build Coastguard Worker static mutex_t boot_args_lock = MUTEX_INITIAL_VALUE(boot_args_lock);
61*344aa361SAndroid Build Coastguard Worker static atomic_uint_fast32_t sm_api_version;
62*344aa361SAndroid Build Coastguard Worker static atomic_uint_fast32_t sm_api_version_min;
63*344aa361SAndroid Build Coastguard Worker static atomic_uint_fast32_t sm_api_version_max = TRUSTY_API_VERSION_CURRENT;
64*344aa361SAndroid Build Coastguard Worker static spin_lock_t sm_api_version_lock;
65*344aa361SAndroid Build Coastguard Worker static atomic_bool platform_halted;
66*344aa361SAndroid Build Coastguard Worker
67*344aa361SAndroid Build Coastguard Worker static event_t nsirqevent[SMP_MAX_CPUS];
68*344aa361SAndroid Build Coastguard Worker static thread_t* nsirqthreads[SMP_MAX_CPUS];
69*344aa361SAndroid Build Coastguard Worker static thread_t* nsidlethreads[SMP_MAX_CPUS];
70*344aa361SAndroid Build Coastguard Worker static thread_t* stdcallthread;
71*344aa361SAndroid Build Coastguard Worker static bool irq_thread_ready[SMP_MAX_CPUS];
72*344aa361SAndroid Build Coastguard Worker struct sm_std_call_state stdcallstate = {
73*344aa361SAndroid Build Coastguard Worker .event = EVENT_INITIAL_VALUE(stdcallstate.event, 0, 0),
74*344aa361SAndroid Build Coastguard Worker .active_cpu = -1,
75*344aa361SAndroid Build Coastguard Worker .initial_cpu = -1,
76*344aa361SAndroid Build Coastguard Worker .last_cpu = -1,
77*344aa361SAndroid Build Coastguard Worker };
78*344aa361SAndroid Build Coastguard Worker
79*344aa361SAndroid Build Coastguard Worker extern smc32_handler_t sm_stdcall_table[];
80*344aa361SAndroid Build Coastguard Worker extern smc32_handler_t sm_nopcall_table[];
81*344aa361SAndroid Build Coastguard Worker extern smc32_handler_t sm_fastcall_table[];
82*344aa361SAndroid Build Coastguard Worker
smc_sm_api_version(struct smc32_args * args)83*344aa361SAndroid Build Coastguard Worker long smc_sm_api_version(struct smc32_args* args) {
84*344aa361SAndroid Build Coastguard Worker uint32_t api_version = args->params[0];
85*344aa361SAndroid Build Coastguard Worker
86*344aa361SAndroid Build Coastguard Worker spin_lock(&sm_api_version_lock);
87*344aa361SAndroid Build Coastguard Worker LTRACEF("request api version %d\n", api_version);
88*344aa361SAndroid Build Coastguard Worker if (api_version > sm_api_version_max) {
89*344aa361SAndroid Build Coastguard Worker api_version = sm_api_version_max;
90*344aa361SAndroid Build Coastguard Worker }
91*344aa361SAndroid Build Coastguard Worker
92*344aa361SAndroid Build Coastguard Worker if (api_version < sm_api_version_min) {
93*344aa361SAndroid Build Coastguard Worker TRACEF("ERROR: Tried to select incompatible api version %d < %d, current version %d\n",
94*344aa361SAndroid Build Coastguard Worker api_version, sm_api_version_min, sm_api_version);
95*344aa361SAndroid Build Coastguard Worker api_version = sm_api_version;
96*344aa361SAndroid Build Coastguard Worker } else {
97*344aa361SAndroid Build Coastguard Worker /* Update and lock the version to prevent downgrade */
98*344aa361SAndroid Build Coastguard Worker sm_api_version = api_version;
99*344aa361SAndroid Build Coastguard Worker sm_api_version_min = api_version;
100*344aa361SAndroid Build Coastguard Worker }
101*344aa361SAndroid Build Coastguard Worker spin_unlock(&sm_api_version_lock);
102*344aa361SAndroid Build Coastguard Worker
103*344aa361SAndroid Build Coastguard Worker LTRACEF("return api version %d\n", api_version);
104*344aa361SAndroid Build Coastguard Worker return api_version;
105*344aa361SAndroid Build Coastguard Worker }
106*344aa361SAndroid Build Coastguard Worker
smc_get_smp_max_cpus(struct smc32_args * args)107*344aa361SAndroid Build Coastguard Worker long smc_get_smp_max_cpus(struct smc32_args* args) {
108*344aa361SAndroid Build Coastguard Worker return SMP_MAX_CPUS;
109*344aa361SAndroid Build Coastguard Worker }
110*344aa361SAndroid Build Coastguard Worker
sm_get_api_version(void)111*344aa361SAndroid Build Coastguard Worker uint32_t sm_get_api_version(void) {
112*344aa361SAndroid Build Coastguard Worker return sm_api_version;
113*344aa361SAndroid Build Coastguard Worker }
114*344aa361SAndroid Build Coastguard Worker
sm_check_and_lock_api_version(uint32_t version_wanted)115*344aa361SAndroid Build Coastguard Worker bool sm_check_and_lock_api_version(uint32_t version_wanted) {
116*344aa361SAndroid Build Coastguard Worker spin_lock_saved_state_t state;
117*344aa361SAndroid Build Coastguard Worker
118*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(version_wanted > 0);
119*344aa361SAndroid Build Coastguard Worker
120*344aa361SAndroid Build Coastguard Worker if (sm_api_version_min >= version_wanted) {
121*344aa361SAndroid Build Coastguard Worker return true;
122*344aa361SAndroid Build Coastguard Worker }
123*344aa361SAndroid Build Coastguard Worker if (sm_api_version_max < version_wanted) {
124*344aa361SAndroid Build Coastguard Worker return false;
125*344aa361SAndroid Build Coastguard Worker }
126*344aa361SAndroid Build Coastguard Worker
127*344aa361SAndroid Build Coastguard Worker spin_lock_save(&sm_api_version_lock, &state, SPIN_LOCK_FLAG_IRQ_FIQ);
128*344aa361SAndroid Build Coastguard Worker if (sm_api_version < version_wanted) {
129*344aa361SAndroid Build Coastguard Worker sm_api_version_max = MIN(sm_api_version_max, version_wanted - 1);
130*344aa361SAndroid Build Coastguard Worker TRACEF("max api version set: %d\n", sm_api_version_max);
131*344aa361SAndroid Build Coastguard Worker } else {
132*344aa361SAndroid Build Coastguard Worker sm_api_version_min = MAX(sm_api_version_min, version_wanted);
133*344aa361SAndroid Build Coastguard Worker TRACEF("min api version set: %d\n", sm_api_version_min);
134*344aa361SAndroid Build Coastguard Worker }
135*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(sm_api_version_min <= sm_api_version_max);
136*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(sm_api_version >= sm_api_version_min);
137*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(sm_api_version <= sm_api_version_max);
138*344aa361SAndroid Build Coastguard Worker
139*344aa361SAndroid Build Coastguard Worker spin_unlock_restore(&sm_api_version_lock, state, SPIN_LOCK_FLAG_IRQ_FIQ);
140*344aa361SAndroid Build Coastguard Worker
141*344aa361SAndroid Build Coastguard Worker return sm_api_version_min >= version_wanted;
142*344aa361SAndroid Build Coastguard Worker }
143*344aa361SAndroid Build Coastguard Worker
sm_stdcall_loop(void * arg)144*344aa361SAndroid Build Coastguard Worker static int __NO_RETURN sm_stdcall_loop(void* arg) {
145*344aa361SAndroid Build Coastguard Worker long ret;
146*344aa361SAndroid Build Coastguard Worker spin_lock_saved_state_t state;
147*344aa361SAndroid Build Coastguard Worker
148*344aa361SAndroid Build Coastguard Worker while (true) {
149*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, wait for stdcall\n", arch_curr_cpu_num());
150*344aa361SAndroid Build Coastguard Worker event_wait(&stdcallstate.event);
151*344aa361SAndroid Build Coastguard Worker
152*344aa361SAndroid Build Coastguard Worker /* Dispatch 'standard call' handler */
153*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, got stdcall: 0x%x, 0x%x, 0x%x, 0x%x\n",
154*344aa361SAndroid Build Coastguard Worker arch_curr_cpu_num(), stdcallstate.args.smc_nr,
155*344aa361SAndroid Build Coastguard Worker stdcallstate.args.params[0], stdcallstate.args.params[1],
156*344aa361SAndroid Build Coastguard Worker stdcallstate.args.params[2]);
157*344aa361SAndroid Build Coastguard Worker ret = sm_stdcall_table[SMC_ENTITY(stdcallstate.args.smc_nr)](
158*344aa361SAndroid Build Coastguard Worker &stdcallstate.args);
159*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, stdcall(0x%x, 0x%x, 0x%x, 0x%x) returned 0x%lx (%ld)\n",
160*344aa361SAndroid Build Coastguard Worker arch_curr_cpu_num(), stdcallstate.args.smc_nr,
161*344aa361SAndroid Build Coastguard Worker stdcallstate.args.params[0], stdcallstate.args.params[1],
162*344aa361SAndroid Build Coastguard Worker stdcallstate.args.params[2], ret, ret);
163*344aa361SAndroid Build Coastguard Worker spin_lock_save(&stdcallstate.lock, &state, SPIN_LOCK_FLAG_IRQ);
164*344aa361SAndroid Build Coastguard Worker stdcallstate.ret = ret;
165*344aa361SAndroid Build Coastguard Worker stdcallstate.done = true;
166*344aa361SAndroid Build Coastguard Worker event_unsignal(&stdcallstate.event);
167*344aa361SAndroid Build Coastguard Worker spin_unlock_restore(&stdcallstate.lock, state, SPIN_LOCK_FLAG_IRQ);
168*344aa361SAndroid Build Coastguard Worker }
169*344aa361SAndroid Build Coastguard Worker }
170*344aa361SAndroid Build Coastguard Worker
171*344aa361SAndroid Build Coastguard Worker /* must be called with irqs disabled */
sm_queue_stdcall(struct smc32_args * args)172*344aa361SAndroid Build Coastguard Worker static long sm_queue_stdcall(struct smc32_args* args) {
173*344aa361SAndroid Build Coastguard Worker long ret;
174*344aa361SAndroid Build Coastguard Worker uint cpu = arch_curr_cpu_num();
175*344aa361SAndroid Build Coastguard Worker
176*344aa361SAndroid Build Coastguard Worker spin_lock(&stdcallstate.lock);
177*344aa361SAndroid Build Coastguard Worker
178*344aa361SAndroid Build Coastguard Worker if (stdcallstate.event.signaled || stdcallstate.done) {
179*344aa361SAndroid Build Coastguard Worker if (args->smc_nr == SMC_SC_RESTART_LAST &&
180*344aa361SAndroid Build Coastguard Worker stdcallstate.args.client_id != args->client_id) {
181*344aa361SAndroid Build Coastguard Worker dprintf(CRITICAL,
182*344aa361SAndroid Build Coastguard Worker "%s: cpu %d, unexpected restart, "
183*344aa361SAndroid Build Coastguard Worker "client %" PRIx64 " != %" PRIx64 "\n",
184*344aa361SAndroid Build Coastguard Worker __func__, cpu, stdcallstate.args.client_id,
185*344aa361SAndroid Build Coastguard Worker args->client_id);
186*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_UNEXPECTED_RESTART;
187*344aa361SAndroid Build Coastguard Worker goto err;
188*344aa361SAndroid Build Coastguard Worker } else if (args->smc_nr == SMC_SC_RESTART_LAST &&
189*344aa361SAndroid Build Coastguard Worker stdcallstate.active_cpu == -1) {
190*344aa361SAndroid Build Coastguard Worker stdcallstate.restart_count++;
191*344aa361SAndroid Build Coastguard Worker LTRACEF_LEVEL(3, "cpu %d, restart std call, restart_count %d\n",
192*344aa361SAndroid Build Coastguard Worker cpu, stdcallstate.restart_count);
193*344aa361SAndroid Build Coastguard Worker goto restart_stdcall;
194*344aa361SAndroid Build Coastguard Worker }
195*344aa361SAndroid Build Coastguard Worker dprintf(CRITICAL, "%s: cpu %d, std call busy\n", __func__, cpu);
196*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_BUSY;
197*344aa361SAndroid Build Coastguard Worker goto err;
198*344aa361SAndroid Build Coastguard Worker } else {
199*344aa361SAndroid Build Coastguard Worker if (args->smc_nr == SMC_SC_RESTART_LAST) {
200*344aa361SAndroid Build Coastguard Worker dprintf(CRITICAL,
201*344aa361SAndroid Build Coastguard Worker "%s: cpu %d, unexpected restart, no std call active\n",
202*344aa361SAndroid Build Coastguard Worker __func__, arch_curr_cpu_num());
203*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_UNEXPECTED_RESTART;
204*344aa361SAndroid Build Coastguard Worker goto err;
205*344aa361SAndroid Build Coastguard Worker }
206*344aa361SAndroid Build Coastguard Worker }
207*344aa361SAndroid Build Coastguard Worker
208*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, queue std call 0x%x\n", cpu, args->smc_nr);
209*344aa361SAndroid Build Coastguard Worker stdcallstate.initial_cpu = cpu;
210*344aa361SAndroid Build Coastguard Worker stdcallstate.ret = SM_ERR_INTERNAL_FAILURE;
211*344aa361SAndroid Build Coastguard Worker stdcallstate.args = *args;
212*344aa361SAndroid Build Coastguard Worker stdcallstate.restart_count = 0;
213*344aa361SAndroid Build Coastguard Worker event_signal(&stdcallstate.event, false);
214*344aa361SAndroid Build Coastguard Worker
215*344aa361SAndroid Build Coastguard Worker restart_stdcall:
216*344aa361SAndroid Build Coastguard Worker stdcallstate.active_cpu = cpu;
217*344aa361SAndroid Build Coastguard Worker ret = 0;
218*344aa361SAndroid Build Coastguard Worker
219*344aa361SAndroid Build Coastguard Worker err:
220*344aa361SAndroid Build Coastguard Worker spin_unlock(&stdcallstate.lock);
221*344aa361SAndroid Build Coastguard Worker
222*344aa361SAndroid Build Coastguard Worker return ret;
223*344aa361SAndroid Build Coastguard Worker }
224*344aa361SAndroid Build Coastguard Worker
sm_sched_nonsecure_fiq_loop(long ret,struct smc32_args * args)225*344aa361SAndroid Build Coastguard Worker static void sm_sched_nonsecure_fiq_loop(long ret, struct smc32_args* args) {
226*344aa361SAndroid Build Coastguard Worker while (true) {
227*344aa361SAndroid Build Coastguard Worker if (atomic_load(&platform_halted)) {
228*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_PANIC;
229*344aa361SAndroid Build Coastguard Worker }
230*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure(ret, args);
231*344aa361SAndroid Build Coastguard Worker if (atomic_load(&platform_halted) && args->smc_nr != SMC_FC_FIQ_ENTER) {
232*344aa361SAndroid Build Coastguard Worker continue;
233*344aa361SAndroid Build Coastguard Worker }
234*344aa361SAndroid Build Coastguard Worker if (SMC_IS_SMC64(args->smc_nr)) {
235*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_NOT_SUPPORTED;
236*344aa361SAndroid Build Coastguard Worker continue;
237*344aa361SAndroid Build Coastguard Worker }
238*344aa361SAndroid Build Coastguard Worker if (!SMC_IS_FASTCALL(args->smc_nr)) {
239*344aa361SAndroid Build Coastguard Worker break;
240*344aa361SAndroid Build Coastguard Worker }
241*344aa361SAndroid Build Coastguard Worker ret = sm_fastcall_table[SMC_ENTITY(args->smc_nr)](args);
242*344aa361SAndroid Build Coastguard Worker }
243*344aa361SAndroid Build Coastguard Worker }
244*344aa361SAndroid Build Coastguard Worker
245*344aa361SAndroid Build Coastguard Worker /* must be called with irqs disabled */
sm_return_and_wait_for_next_stdcall(long ret,int cpu)246*344aa361SAndroid Build Coastguard Worker static enum handler_return sm_return_and_wait_for_next_stdcall(long ret,
247*344aa361SAndroid Build Coastguard Worker int cpu) {
248*344aa361SAndroid Build Coastguard Worker struct smc32_args args = SMC32_ARGS_INITIAL_VALUE(args);
249*344aa361SAndroid Build Coastguard Worker
250*344aa361SAndroid Build Coastguard Worker do {
251*344aa361SAndroid Build Coastguard Worker #if ARCH_HAS_FIQ
252*344aa361SAndroid Build Coastguard Worker arch_disable_fiqs();
253*344aa361SAndroid Build Coastguard Worker #endif
254*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure_fiq_loop(ret, &args);
255*344aa361SAndroid Build Coastguard Worker #if ARCH_HAS_FIQ
256*344aa361SAndroid Build Coastguard Worker arch_enable_fiqs();
257*344aa361SAndroid Build Coastguard Worker #endif
258*344aa361SAndroid Build Coastguard Worker
259*344aa361SAndroid Build Coastguard Worker /* Allow concurrent SMC_SC_NOP calls on multiple cpus */
260*344aa361SAndroid Build Coastguard Worker if (args.smc_nr == SMC_SC_NOP) {
261*344aa361SAndroid Build Coastguard Worker LTRACEF_LEVEL(3, "cpu %d, got nop\n", cpu);
262*344aa361SAndroid Build Coastguard Worker ret = sm_nopcall_table[SMC_ENTITY(args.params[0])](&args);
263*344aa361SAndroid Build Coastguard Worker } else {
264*344aa361SAndroid Build Coastguard Worker ret = sm_queue_stdcall(&args);
265*344aa361SAndroid Build Coastguard Worker }
266*344aa361SAndroid Build Coastguard Worker } while (ret);
267*344aa361SAndroid Build Coastguard Worker
268*344aa361SAndroid Build Coastguard Worker return sm_intc_enable_interrupts();
269*344aa361SAndroid Build Coastguard Worker }
270*344aa361SAndroid Build Coastguard Worker
sm_irq_return_ns(void)271*344aa361SAndroid Build Coastguard Worker static void sm_irq_return_ns(void) {
272*344aa361SAndroid Build Coastguard Worker long ret;
273*344aa361SAndroid Build Coastguard Worker int cpu;
274*344aa361SAndroid Build Coastguard Worker
275*344aa361SAndroid Build Coastguard Worker cpu = arch_curr_cpu_num();
276*344aa361SAndroid Build Coastguard Worker
277*344aa361SAndroid Build Coastguard Worker spin_lock(&stdcallstate.lock); /* TODO: remove? */
278*344aa361SAndroid Build Coastguard Worker LTRACEF_LEVEL(2, "got irq on cpu %d, stdcallcpu %d\n", cpu,
279*344aa361SAndroid Build Coastguard Worker stdcallstate.active_cpu);
280*344aa361SAndroid Build Coastguard Worker if (stdcallstate.active_cpu == cpu) {
281*344aa361SAndroid Build Coastguard Worker stdcallstate.last_cpu = stdcallstate.active_cpu;
282*344aa361SAndroid Build Coastguard Worker stdcallstate.active_cpu = -1;
283*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERRUPTED;
284*344aa361SAndroid Build Coastguard Worker } else {
285*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_NOP_INTERRUPTED;
286*344aa361SAndroid Build Coastguard Worker }
287*344aa361SAndroid Build Coastguard Worker LTRACEF_LEVEL(2, "got irq on cpu %d, return %ld\n", cpu, ret);
288*344aa361SAndroid Build Coastguard Worker spin_unlock(&stdcallstate.lock);
289*344aa361SAndroid Build Coastguard Worker sm_return_and_wait_for_next_stdcall(ret, cpu);
290*344aa361SAndroid Build Coastguard Worker }
291*344aa361SAndroid Build Coastguard Worker
sm_irq_loop(void * arg)292*344aa361SAndroid Build Coastguard Worker static int __NO_RETURN sm_irq_loop(void* arg) {
293*344aa361SAndroid Build Coastguard Worker int cpu;
294*344aa361SAndroid Build Coastguard Worker /* cpu that requested this thread, the current cpu could be different */
295*344aa361SAndroid Build Coastguard Worker int eventcpu = (uintptr_t)arg;
296*344aa361SAndroid Build Coastguard Worker
297*344aa361SAndroid Build Coastguard Worker /*
298*344aa361SAndroid Build Coastguard Worker * Run this thread with interrupts masked, so we don't reenter the
299*344aa361SAndroid Build Coastguard Worker * interrupt handler. The interrupt handler for non-secure interrupts
300*344aa361SAndroid Build Coastguard Worker * returns to this thread with the interrupt still pending.
301*344aa361SAndroid Build Coastguard Worker */
302*344aa361SAndroid Build Coastguard Worker arch_disable_ints();
303*344aa361SAndroid Build Coastguard Worker irq_thread_ready[eventcpu] = true;
304*344aa361SAndroid Build Coastguard Worker
305*344aa361SAndroid Build Coastguard Worker cpu = arch_curr_cpu_num();
306*344aa361SAndroid Build Coastguard Worker LTRACEF("wait for irqs for cpu %d, on cpu %d\n", eventcpu, cpu);
307*344aa361SAndroid Build Coastguard Worker while (true) {
308*344aa361SAndroid Build Coastguard Worker event_wait(&nsirqevent[eventcpu]);
309*344aa361SAndroid Build Coastguard Worker sm_irq_return_ns();
310*344aa361SAndroid Build Coastguard Worker }
311*344aa361SAndroid Build Coastguard Worker }
312*344aa361SAndroid Build Coastguard Worker
313*344aa361SAndroid Build Coastguard Worker /* must be called with irqs disabled */
sm_get_stdcall_ret(void)314*344aa361SAndroid Build Coastguard Worker static long sm_get_stdcall_ret(void) {
315*344aa361SAndroid Build Coastguard Worker long ret;
316*344aa361SAndroid Build Coastguard Worker uint cpu = arch_curr_cpu_num();
317*344aa361SAndroid Build Coastguard Worker
318*344aa361SAndroid Build Coastguard Worker spin_lock(&stdcallstate.lock);
319*344aa361SAndroid Build Coastguard Worker
320*344aa361SAndroid Build Coastguard Worker if (stdcallstate.active_cpu != (int)cpu) {
321*344aa361SAndroid Build Coastguard Worker dprintf(CRITICAL, "%s: stdcallcpu, a%d != curr-cpu %d, l%d, i%d\n",
322*344aa361SAndroid Build Coastguard Worker __func__, stdcallstate.active_cpu, cpu, stdcallstate.last_cpu,
323*344aa361SAndroid Build Coastguard Worker stdcallstate.initial_cpu);
324*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERNAL_FAILURE;
325*344aa361SAndroid Build Coastguard Worker goto err;
326*344aa361SAndroid Build Coastguard Worker }
327*344aa361SAndroid Build Coastguard Worker stdcallstate.last_cpu = stdcallstate.active_cpu;
328*344aa361SAndroid Build Coastguard Worker stdcallstate.active_cpu = -1;
329*344aa361SAndroid Build Coastguard Worker
330*344aa361SAndroid Build Coastguard Worker if (stdcallstate.done) {
331*344aa361SAndroid Build Coastguard Worker stdcallstate.done = false;
332*344aa361SAndroid Build Coastguard Worker ret = stdcallstate.ret;
333*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, return stdcall result, %ld, initial cpu %d\n", cpu,
334*344aa361SAndroid Build Coastguard Worker stdcallstate.ret, stdcallstate.initial_cpu);
335*344aa361SAndroid Build Coastguard Worker } else {
336*344aa361SAndroid Build Coastguard Worker if (sm_check_and_lock_api_version(TRUSTY_API_VERSION_SMP))
337*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_CPU_IDLE; /* ns using smp api */
338*344aa361SAndroid Build Coastguard Worker else if (stdcallstate.restart_count)
339*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_BUSY;
340*344aa361SAndroid Build Coastguard Worker else
341*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERRUPTED;
342*344aa361SAndroid Build Coastguard Worker LTRACEF("cpu %d, initial cpu %d, restart_count %d, std call not finished, return %ld\n",
343*344aa361SAndroid Build Coastguard Worker cpu, stdcallstate.initial_cpu, stdcallstate.restart_count, ret);
344*344aa361SAndroid Build Coastguard Worker }
345*344aa361SAndroid Build Coastguard Worker err:
346*344aa361SAndroid Build Coastguard Worker spin_unlock(&stdcallstate.lock);
347*344aa361SAndroid Build Coastguard Worker
348*344aa361SAndroid Build Coastguard Worker return ret;
349*344aa361SAndroid Build Coastguard Worker }
350*344aa361SAndroid Build Coastguard Worker
enter_smcall_critical_section(void)351*344aa361SAndroid Build Coastguard Worker static uint enter_smcall_critical_section(void) {
352*344aa361SAndroid Build Coastguard Worker /*
353*344aa361SAndroid Build Coastguard Worker * Disable interrupts so stdcallstate.active_cpu does not
354*344aa361SAndroid Build Coastguard Worker * change to or from this cpu after checking it in the critical
355*344aa361SAndroid Build Coastguard Worker * section.
356*344aa361SAndroid Build Coastguard Worker */
357*344aa361SAndroid Build Coastguard Worker arch_disable_ints();
358*344aa361SAndroid Build Coastguard Worker
359*344aa361SAndroid Build Coastguard Worker /* Switch to sm-stdcall if sm_queue_stdcall woke it up */
360*344aa361SAndroid Build Coastguard Worker thread_yield();
361*344aa361SAndroid Build Coastguard Worker
362*344aa361SAndroid Build Coastguard Worker return arch_curr_cpu_num();
363*344aa361SAndroid Build Coastguard Worker }
364*344aa361SAndroid Build Coastguard Worker
exit_smcall_critical_section(long ret,uint cpu)365*344aa361SAndroid Build Coastguard Worker static void exit_smcall_critical_section(long ret, uint cpu) {
366*344aa361SAndroid Build Coastguard Worker enum handler_return resched;
367*344aa361SAndroid Build Coastguard Worker
368*344aa361SAndroid Build Coastguard Worker resched = sm_return_and_wait_for_next_stdcall(ret, cpu);
369*344aa361SAndroid Build Coastguard Worker if (resched == INT_RESCHEDULE)
370*344aa361SAndroid Build Coastguard Worker thread_preempt();
371*344aa361SAndroid Build Coastguard Worker
372*344aa361SAndroid Build Coastguard Worker /* Re-enable interrupts (needed for SMC_SC_NOP) */
373*344aa361SAndroid Build Coastguard Worker arch_enable_ints();
374*344aa361SAndroid Build Coastguard Worker }
375*344aa361SAndroid Build Coastguard Worker
sm_wait_for_smcall(void * arg)376*344aa361SAndroid Build Coastguard Worker static int sm_wait_for_smcall(void* arg) {
377*344aa361SAndroid Build Coastguard Worker int cpu;
378*344aa361SAndroid Build Coastguard Worker long ret = 0;
379*344aa361SAndroid Build Coastguard Worker
380*344aa361SAndroid Build Coastguard Worker LTRACEF("wait for stdcalls, on cpu %d\n", arch_curr_cpu_num());
381*344aa361SAndroid Build Coastguard Worker
382*344aa361SAndroid Build Coastguard Worker while (true) {
383*344aa361SAndroid Build Coastguard Worker cpu = enter_smcall_critical_section();
384*344aa361SAndroid Build Coastguard Worker
385*344aa361SAndroid Build Coastguard Worker if (cpu == stdcallstate.active_cpu)
386*344aa361SAndroid Build Coastguard Worker ret = sm_get_stdcall_ret();
387*344aa361SAndroid Build Coastguard Worker else
388*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_NOP_DONE;
389*344aa361SAndroid Build Coastguard Worker
390*344aa361SAndroid Build Coastguard Worker exit_smcall_critical_section(ret, cpu);
391*344aa361SAndroid Build Coastguard Worker }
392*344aa361SAndroid Build Coastguard Worker }
393*344aa361SAndroid Build Coastguard Worker
394*344aa361SAndroid Build Coastguard Worker #if WITH_LIB_SM_MONITOR
395*344aa361SAndroid Build Coastguard Worker /* per-cpu secure monitor initialization */
sm_mon_percpu_init(uint level)396*344aa361SAndroid Build Coastguard Worker static void sm_mon_percpu_init(uint level) {
397*344aa361SAndroid Build Coastguard Worker /* let normal world enable SMP, lock TLB, access CP10/11 */
398*344aa361SAndroid Build Coastguard Worker __asm__ volatile(
399*344aa361SAndroid Build Coastguard Worker "mrc p15, 0, r1, c1, c1, 2 \n"
400*344aa361SAndroid Build Coastguard Worker "orr r1, r1, #0xC00 \n"
401*344aa361SAndroid Build Coastguard Worker "orr r1, r1, #0x60000 \n"
402*344aa361SAndroid Build Coastguard Worker "mcr p15, 0, r1, c1, c1, 2 @ NSACR \n"
403*344aa361SAndroid Build Coastguard Worker :
404*344aa361SAndroid Build Coastguard Worker :
405*344aa361SAndroid Build Coastguard Worker : "r1");
406*344aa361SAndroid Build Coastguard Worker
407*344aa361SAndroid Build Coastguard Worker __asm__ volatile("mcr p15, 0, %0, c12, c0, 1 \n"
408*344aa361SAndroid Build Coastguard Worker :
409*344aa361SAndroid Build Coastguard Worker : "r"(&monitor_vector_table));
410*344aa361SAndroid Build Coastguard Worker }
411*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK_FLAGS(libsm_mon_perrcpu,
412*344aa361SAndroid Build Coastguard Worker sm_mon_percpu_init,
413*344aa361SAndroid Build Coastguard Worker LK_INIT_LEVEL_PLATFORM - 3,
414*344aa361SAndroid Build Coastguard Worker LK_INIT_FLAG_ALL_CPUS);
415*344aa361SAndroid Build Coastguard Worker #endif
416*344aa361SAndroid Build Coastguard Worker
sm_init(uint level)417*344aa361SAndroid Build Coastguard Worker static void sm_init(uint level) {
418*344aa361SAndroid Build Coastguard Worker status_t err;
419*344aa361SAndroid Build Coastguard Worker char name[32];
420*344aa361SAndroid Build Coastguard Worker
421*344aa361SAndroid Build Coastguard Worker mutex_acquire(&boot_args_lock);
422*344aa361SAndroid Build Coastguard Worker
423*344aa361SAndroid Build Coastguard Worker /* Map the boot arguments if supplied by the bootloader */
424*344aa361SAndroid Build Coastguard Worker if (lk_boot_args[1] && lk_boot_args[2]) {
425*344aa361SAndroid Build Coastguard Worker ulong offset = lk_boot_args[1] & (PAGE_SIZE - 1);
426*344aa361SAndroid Build Coastguard Worker paddr_t paddr = round_down(lk_boot_args[1], PAGE_SIZE);
427*344aa361SAndroid Build Coastguard Worker size_t size = round_up(lk_boot_args[2] + offset, PAGE_SIZE);
428*344aa361SAndroid Build Coastguard Worker void* vptr;
429*344aa361SAndroid Build Coastguard Worker
430*344aa361SAndroid Build Coastguard Worker err = vmm_alloc_physical(vmm_get_kernel_aspace(), "sm", size, &vptr,
431*344aa361SAndroid Build Coastguard Worker PAGE_SIZE_SHIFT, paddr, 0,
432*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS |
433*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE |
434*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_CACHED);
435*344aa361SAndroid Build Coastguard Worker if (!err) {
436*344aa361SAndroid Build Coastguard Worker boot_args = (uint8_t*)vptr + offset;
437*344aa361SAndroid Build Coastguard Worker boot_args_refcnt++;
438*344aa361SAndroid Build Coastguard Worker } else {
439*344aa361SAndroid Build Coastguard Worker boot_args = NULL;
440*344aa361SAndroid Build Coastguard Worker TRACEF("Error mapping boot parameter block: %d\n", err);
441*344aa361SAndroid Build Coastguard Worker }
442*344aa361SAndroid Build Coastguard Worker }
443*344aa361SAndroid Build Coastguard Worker
444*344aa361SAndroid Build Coastguard Worker mutex_release(&boot_args_lock);
445*344aa361SAndroid Build Coastguard Worker
446*344aa361SAndroid Build Coastguard Worker for (int cpu = 0; cpu < SMP_MAX_CPUS; cpu++) {
447*344aa361SAndroid Build Coastguard Worker event_init(&nsirqevent[cpu], false, EVENT_FLAG_AUTOUNSIGNAL);
448*344aa361SAndroid Build Coastguard Worker
449*344aa361SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "irq-ns-switch-%d", cpu);
450*344aa361SAndroid Build Coastguard Worker nsirqthreads[cpu] =
451*344aa361SAndroid Build Coastguard Worker thread_create(name, sm_irq_loop, (void*)(uintptr_t)cpu,
452*344aa361SAndroid Build Coastguard Worker HIGHEST_PRIORITY, DEFAULT_STACK_SIZE);
453*344aa361SAndroid Build Coastguard Worker if (!nsirqthreads[cpu]) {
454*344aa361SAndroid Build Coastguard Worker panic("failed to create irq NS switcher thread for cpu %d!\n", cpu);
455*344aa361SAndroid Build Coastguard Worker }
456*344aa361SAndroid Build Coastguard Worker thread_set_pinned_cpu(nsirqthreads[cpu], cpu);
457*344aa361SAndroid Build Coastguard Worker thread_set_real_time(nsirqthreads[cpu]);
458*344aa361SAndroid Build Coastguard Worker
459*344aa361SAndroid Build Coastguard Worker snprintf(name, sizeof(name), "idle-ns-switch-%d", cpu);
460*344aa361SAndroid Build Coastguard Worker nsidlethreads[cpu] =
461*344aa361SAndroid Build Coastguard Worker thread_create(name, sm_wait_for_smcall, NULL,
462*344aa361SAndroid Build Coastguard Worker LOWEST_PRIORITY + 1, DEFAULT_STACK_SIZE);
463*344aa361SAndroid Build Coastguard Worker if (!nsidlethreads[cpu]) {
464*344aa361SAndroid Build Coastguard Worker panic("failed to create idle NS switcher thread for cpu %d!\n",
465*344aa361SAndroid Build Coastguard Worker cpu);
466*344aa361SAndroid Build Coastguard Worker }
467*344aa361SAndroid Build Coastguard Worker thread_set_pinned_cpu(nsidlethreads[cpu], cpu);
468*344aa361SAndroid Build Coastguard Worker thread_set_real_time(nsidlethreads[cpu]);
469*344aa361SAndroid Build Coastguard Worker }
470*344aa361SAndroid Build Coastguard Worker
471*344aa361SAndroid Build Coastguard Worker stdcallthread = thread_create("sm-stdcall", sm_stdcall_loop, NULL,
472*344aa361SAndroid Build Coastguard Worker LOWEST_PRIORITY + 2, DEFAULT_STACK_SIZE);
473*344aa361SAndroid Build Coastguard Worker if (!stdcallthread) {
474*344aa361SAndroid Build Coastguard Worker panic("failed to create sm-stdcall thread!\n");
475*344aa361SAndroid Build Coastguard Worker }
476*344aa361SAndroid Build Coastguard Worker thread_set_real_time(stdcallthread);
477*344aa361SAndroid Build Coastguard Worker thread_resume(stdcallthread);
478*344aa361SAndroid Build Coastguard Worker }
479*344aa361SAndroid Build Coastguard Worker
480*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(libsm, sm_init, LK_INIT_LEVEL_PLATFORM - 1);
481*344aa361SAndroid Build Coastguard Worker
sm_handle_irq(void)482*344aa361SAndroid Build Coastguard Worker enum handler_return sm_handle_irq(void) {
483*344aa361SAndroid Build Coastguard Worker int cpu = arch_curr_cpu_num();
484*344aa361SAndroid Build Coastguard Worker if (irq_thread_ready[cpu]) {
485*344aa361SAndroid Build Coastguard Worker event_signal(&nsirqevent[cpu], false);
486*344aa361SAndroid Build Coastguard Worker } else {
487*344aa361SAndroid Build Coastguard Worker TRACEF("warning: got ns irq before irq thread is ready\n");
488*344aa361SAndroid Build Coastguard Worker sm_irq_return_ns();
489*344aa361SAndroid Build Coastguard Worker }
490*344aa361SAndroid Build Coastguard Worker
491*344aa361SAndroid Build Coastguard Worker return INT_RESCHEDULE;
492*344aa361SAndroid Build Coastguard Worker }
493*344aa361SAndroid Build Coastguard Worker
sm_handle_fiq(void)494*344aa361SAndroid Build Coastguard Worker void sm_handle_fiq(void) {
495*344aa361SAndroid Build Coastguard Worker uint32_t expected_return;
496*344aa361SAndroid Build Coastguard Worker struct smc32_args args = SMC32_ARGS_INITIAL_VALUE(args);
497*344aa361SAndroid Build Coastguard Worker if (sm_check_and_lock_api_version(TRUSTY_API_VERSION_RESTART_FIQ)) {
498*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure_fiq_loop(SM_ERR_FIQ_INTERRUPTED, &args);
499*344aa361SAndroid Build Coastguard Worker expected_return = SMC_SC_RESTART_FIQ;
500*344aa361SAndroid Build Coastguard Worker } else {
501*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure_fiq_loop(SM_ERR_INTERRUPTED, &args);
502*344aa361SAndroid Build Coastguard Worker expected_return = SMC_SC_RESTART_LAST;
503*344aa361SAndroid Build Coastguard Worker }
504*344aa361SAndroid Build Coastguard Worker if (args.smc_nr != expected_return) {
505*344aa361SAndroid Build Coastguard Worker TRACEF("got bad restart smc %x, expected %x\n", args.smc_nr,
506*344aa361SAndroid Build Coastguard Worker expected_return);
507*344aa361SAndroid Build Coastguard Worker while (args.smc_nr != expected_return)
508*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure_fiq_loop(SM_ERR_INTERLEAVED_SMC, &args);
509*344aa361SAndroid Build Coastguard Worker }
510*344aa361SAndroid Build Coastguard Worker }
511*344aa361SAndroid Build Coastguard Worker
platform_halt(platform_halt_action suggested_action,platform_halt_reason reason)512*344aa361SAndroid Build Coastguard Worker void platform_halt(platform_halt_action suggested_action,
513*344aa361SAndroid Build Coastguard Worker platform_halt_reason reason) {
514*344aa361SAndroid Build Coastguard Worker bool already_halted;
515*344aa361SAndroid Build Coastguard Worker struct smc32_args args = SMC32_ARGS_INITIAL_VALUE(args);
516*344aa361SAndroid Build Coastguard Worker
517*344aa361SAndroid Build Coastguard Worker arch_disable_ints();
518*344aa361SAndroid Build Coastguard Worker already_halted = atomic_exchange(&platform_halted, true);
519*344aa361SAndroid Build Coastguard Worker if (!already_halted) {
520*344aa361SAndroid Build Coastguard Worker for (int cpu = 0; cpu < SMP_MAX_CPUS; cpu++) {
521*344aa361SAndroid Build Coastguard Worker if (nsirqthreads[cpu]) {
522*344aa361SAndroid Build Coastguard Worker event_signal(&nsirqevent[cpu], false);
523*344aa361SAndroid Build Coastguard Worker }
524*344aa361SAndroid Build Coastguard Worker }
525*344aa361SAndroid Build Coastguard Worker dprintf(ALWAYS, "%s\n", lk_version);
526*344aa361SAndroid Build Coastguard Worker dprintf(ALWAYS, "HALT: (reason = %d)\n", reason);
527*344aa361SAndroid Build Coastguard Worker }
528*344aa361SAndroid Build Coastguard Worker
529*344aa361SAndroid Build Coastguard Worker #if ARCH_HAS_FIQ
530*344aa361SAndroid Build Coastguard Worker arch_disable_fiqs();
531*344aa361SAndroid Build Coastguard Worker #endif
532*344aa361SAndroid Build Coastguard Worker while (true)
533*344aa361SAndroid Build Coastguard Worker sm_sched_nonsecure_fiq_loop(SM_ERR_PANIC, &args);
534*344aa361SAndroid Build Coastguard Worker }
535*344aa361SAndroid Build Coastguard Worker
sm_get_boot_args(void ** boot_argsp,size_t * args_sizep)536*344aa361SAndroid Build Coastguard Worker status_t sm_get_boot_args(void** boot_argsp, size_t* args_sizep) {
537*344aa361SAndroid Build Coastguard Worker status_t err = NO_ERROR;
538*344aa361SAndroid Build Coastguard Worker
539*344aa361SAndroid Build Coastguard Worker if (!boot_argsp || !args_sizep)
540*344aa361SAndroid Build Coastguard Worker return ERR_INVALID_ARGS;
541*344aa361SAndroid Build Coastguard Worker
542*344aa361SAndroid Build Coastguard Worker mutex_acquire(&boot_args_lock);
543*344aa361SAndroid Build Coastguard Worker
544*344aa361SAndroid Build Coastguard Worker if (!boot_args) {
545*344aa361SAndroid Build Coastguard Worker err = ERR_NOT_CONFIGURED;
546*344aa361SAndroid Build Coastguard Worker goto unlock;
547*344aa361SAndroid Build Coastguard Worker }
548*344aa361SAndroid Build Coastguard Worker
549*344aa361SAndroid Build Coastguard Worker boot_args_refcnt++;
550*344aa361SAndroid Build Coastguard Worker *boot_argsp = boot_args;
551*344aa361SAndroid Build Coastguard Worker *args_sizep = lk_boot_args[2];
552*344aa361SAndroid Build Coastguard Worker unlock:
553*344aa361SAndroid Build Coastguard Worker mutex_release(&boot_args_lock);
554*344aa361SAndroid Build Coastguard Worker return err;
555*344aa361SAndroid Build Coastguard Worker }
556*344aa361SAndroid Build Coastguard Worker
resume_nsthreads(void)557*344aa361SAndroid Build Coastguard Worker static void resume_nsthreads(void) {
558*344aa361SAndroid Build Coastguard Worker int i;
559*344aa361SAndroid Build Coastguard Worker
560*344aa361SAndroid Build Coastguard Worker for (i = 0; i < SMP_MAX_CPUS; i++) {
561*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(nsirqthreads[i]);
562*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(nsidlethreads[i]);
563*344aa361SAndroid Build Coastguard Worker
564*344aa361SAndroid Build Coastguard Worker thread_resume(nsirqthreads[i]);
565*344aa361SAndroid Build Coastguard Worker thread_resume(nsidlethreads[i]);
566*344aa361SAndroid Build Coastguard Worker }
567*344aa361SAndroid Build Coastguard Worker }
568*344aa361SAndroid Build Coastguard Worker
sm_put_boot_args(void)569*344aa361SAndroid Build Coastguard Worker void sm_put_boot_args(void) {
570*344aa361SAndroid Build Coastguard Worker mutex_acquire(&boot_args_lock);
571*344aa361SAndroid Build Coastguard Worker
572*344aa361SAndroid Build Coastguard Worker if (!boot_args) {
573*344aa361SAndroid Build Coastguard Worker TRACEF("WARNING: caller does not own "
574*344aa361SAndroid Build Coastguard Worker "a reference to boot parameters\n");
575*344aa361SAndroid Build Coastguard Worker goto unlock;
576*344aa361SAndroid Build Coastguard Worker }
577*344aa361SAndroid Build Coastguard Worker
578*344aa361SAndroid Build Coastguard Worker boot_args_refcnt--;
579*344aa361SAndroid Build Coastguard Worker if (boot_args_refcnt == 0) {
580*344aa361SAndroid Build Coastguard Worker vmm_free_region(vmm_get_kernel_aspace(), (vaddr_t)boot_args);
581*344aa361SAndroid Build Coastguard Worker boot_args = NULL;
582*344aa361SAndroid Build Coastguard Worker resume_nsthreads();
583*344aa361SAndroid Build Coastguard Worker }
584*344aa361SAndroid Build Coastguard Worker unlock:
585*344aa361SAndroid Build Coastguard Worker mutex_release(&boot_args_lock);
586*344aa361SAndroid Build Coastguard Worker }
587*344aa361SAndroid Build Coastguard Worker
sm_release_boot_args(uint level)588*344aa361SAndroid Build Coastguard Worker static void sm_release_boot_args(uint level) {
589*344aa361SAndroid Build Coastguard Worker if (boot_args) {
590*344aa361SAndroid Build Coastguard Worker sm_put_boot_args();
591*344aa361SAndroid Build Coastguard Worker } else {
592*344aa361SAndroid Build Coastguard Worker /* we need to resume the ns-switcher here if
593*344aa361SAndroid Build Coastguard Worker * the boot loader didn't pass bootargs
594*344aa361SAndroid Build Coastguard Worker */
595*344aa361SAndroid Build Coastguard Worker resume_nsthreads();
596*344aa361SAndroid Build Coastguard Worker }
597*344aa361SAndroid Build Coastguard Worker
598*344aa361SAndroid Build Coastguard Worker if (boot_args)
599*344aa361SAndroid Build Coastguard Worker TRACEF("WARNING: outstanding reference to boot args"
600*344aa361SAndroid Build Coastguard Worker "at the end of initialzation!\n");
601*344aa361SAndroid Build Coastguard Worker }
602*344aa361SAndroid Build Coastguard Worker
603*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(libsm_bootargs, sm_release_boot_args, LK_INIT_LEVEL_LAST);
604