1 /*
2  * Copyright (c) 2014 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <kernel/mp.h>
10 
11 #include <arch/atomic.h>
12 #include <arch/mp.h>
13 #include <assert.h>
14 #include <kernel/spinlock.h>
15 #include <lk/debug.h>
16 #include <lk/trace.h>
17 #include <stdlib.h>
18 
19 #define LOCAL_TRACE 0
20 
21 #if WITH_SMP
22 /* a global state structure, aligned on cpu cache line to minimize aliasing */
23 struct mp_state mp __CPU_ALIGN;
24 
mp_init(void)25 void mp_init(void) {
26 }
27 
mp_reschedule(mp_cpu_mask_t target,uint flags)28 void mp_reschedule(mp_cpu_mask_t target, uint flags) {
29     uint local_cpu = arch_curr_cpu_num();
30 
31     LTRACEF("local %d, target 0x%x\n", local_cpu, target);
32 
33     /* mask out cpus that are not active and the local cpu */
34     target &= mp.active_cpus;
35 
36     /* mask out cpus that are currently running realtime code */
37     if ((flags & MP_RESCHEDULE_FLAG_REALTIME) == 0) {
38         target &= ~mp.realtime_cpus;
39     }
40     target &= ~(1U << local_cpu);
41 
42     LTRACEF("local %d, post mask target now 0x%x\n", local_cpu, target);
43 
44     arch_mp_send_ipi(target, MP_IPI_RESCHEDULE);
45 }
46 
mp_set_curr_cpu_active(bool active)47 void mp_set_curr_cpu_active(bool active) {
48     atomic_or((volatile int *)&mp.active_cpus, 1U << arch_curr_cpu_num());
49 }
50 
mp_mbx_reschedule_irq(void)51 enum handler_return mp_mbx_reschedule_irq(void) {
52     uint cpu = arch_curr_cpu_num();
53 
54     LTRACEF("cpu %u\n", cpu);
55 
56     THREAD_STATS_INC(reschedule_ipis);
57 
58     return (mp.active_cpus & (1U << cpu)) ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
59 }
60 #endif
61