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 #include <arch/mp.h>
9
10 #include <assert.h>
11 #include <lk/trace.h>
12 #include <lk/err.h>
13 #include <platform/interrupts.h>
14 #include <arch/ops.h>
15
16 #if WITH_DEV_INTERRUPT_ARM_GIC
17 #include <dev/interrupt/arm_gic.h>
18 #elif PLATFORM_BCM28XX
19 /* bcm28xx has a weird custom interrupt controller for MP */
20 extern void bcm28xx_send_ipi(uint irq, uint cpu_mask);
21 #else
22 #error need other implementation of interrupt controller that can ipi
23 #endif
24
25 #define LOCAL_TRACE 0
26
27 #define GIC_IPI_BASE (14)
28
arch_mp_send_ipi(mp_cpu_mask_t target,mp_ipi_t ipi)29 status_t arch_mp_send_ipi(mp_cpu_mask_t target, mp_ipi_t ipi) {
30 LTRACEF("target 0x%x, ipi %u\n", target, ipi);
31
32 #if WITH_DEV_INTERRUPT_ARM_GIC
33 uint gic_ipi_num = ipi + GIC_IPI_BASE;
34
35 /* filter out targets outside of the range of cpus we care about */
36 target &= ((1UL << SMP_MAX_CPUS) - 1);
37 if (target != 0) {
38 LTRACEF("target 0x%x, gic_ipi %u\n", target, gic_ipi_num);
39 u_int flags = 0;
40 #if WITH_LIB_SM
41 flags |= ARM_GIC_SGI_FLAG_NS;
42 #endif
43 arm_gic_sgi(gic_ipi_num, flags, target);
44 }
45 #elif PLATFORM_BCM28XX
46 /* filter out targets outside of the range of cpus we care about */
47 target &= ((1UL << SMP_MAX_CPUS) - 1);
48 if (target != 0) {
49 bcm28xx_send_ipi(ipi, target);
50 }
51 #endif
52
53 return NO_ERROR;
54 }
55
56 enum handler_return arm_ipi_generic_handler(void *arg);
arm_ipi_generic_handler(void * arg)57 enum handler_return arm_ipi_generic_handler(void *arg) {
58 LTRACEF("cpu %u, arg %p\n", arch_curr_cpu_num(), arg);
59
60 return INT_NO_RESCHEDULE;
61 }
62
63 enum handler_return arm_ipi_reschedule_handler(void *arg);
arm_ipi_reschedule_handler(void * arg)64 enum handler_return arm_ipi_reschedule_handler(void *arg) {
65 LTRACEF("cpu %u, arg %p\n", arch_curr_cpu_num(), arg);
66
67 return mp_mbx_reschedule_irq();
68 }
69
arch_mp_init_percpu(void)70 void arch_mp_init_percpu(void) {
71 #if WITH_DEV_INTERRUPT_ARM_GIC
72 register_int_handler(MP_IPI_GENERIC + GIC_IPI_BASE, &arm_ipi_generic_handler, 0);
73 register_int_handler(MP_IPI_RESCHEDULE + GIC_IPI_BASE, &arm_ipi_reschedule_handler, 0);
74 #endif
75 }
76
77