1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #include <config.h>
8 #include <mode/smp/ipi.h>
9 #include <smp/lock.h>
10 #include <util.h>
11
12 #ifdef ENABLE_SMP_SUPPORT
13
14 static IpiModeRemoteCall_t remoteCall; /* the remote call being requested */
15
init_ipi_args(IpiRemoteCall_t func,word_t data1,word_t data2,word_t data3,word_t mask)16 static inline void init_ipi_args(IpiRemoteCall_t func,
17 word_t data1, word_t data2, word_t data3,
18 word_t mask)
19 {
20 remoteCall = (IpiModeRemoteCall_t)func;
21 ipi_args[0] = data1;
22 ipi_args[1] = data2;
23 ipi_args[2] = data3;
24
25 /* get number of cores involved in this IPI */
26 totalCoreBarrier = popcountl(mask);
27 }
28
handleRemoteCall(IpiModeRemoteCall_t call,word_t arg0,word_t arg1,word_t arg2,bool_t irqPath)29 static void handleRemoteCall(IpiModeRemoteCall_t call, word_t arg0,
30 word_t arg1, word_t arg2, bool_t irqPath)
31 {
32 /* we gets spurious irq_remote_call_ipi calls, e.g. when handling IPI
33 * in lock while hardware IPI is pending. Guard against spurious IPIs! */
34 if (clh_is_ipi_pending(getCurrentCPUIndex())) {
35 switch ((IpiRemoteCall_t)call) {
36 case IpiRemoteCall_Stall:
37 ipiStallCoreCallback(irqPath);
38 break;
39
40 #ifdef CONFIG_HAVE_FPU
41 case IpiRemoteCall_switchFpuOwner:
42 switchLocalFpuOwner((user_fpu_state_t *)arg0);
43 break;
44 #endif /* CONFIG_HAVE_FPU */
45
46 case IpiRemoteCall_InvalidateTranslationSingle:
47 invalidateTranslationSingleLocal(arg0);
48 break;
49
50 case IpiRemoteCall_InvalidateTranslationASID:
51 invalidateTranslationASIDLocal(arg0);
52 break;
53
54 case IpiRemoteCall_InvalidateTranslationAll:
55 invalidateTranslationAllLocal();
56 break;
57
58 case IpiRemoteCall_MaskPrivateInterrupt:
59 maskInterrupt(arg0, IDX_TO_IRQT(arg1));
60 break;
61
62 #if defined CONFIG_ARM_HYPERVISOR_SUPPORT && defined ENABLE_SMP_SUPPORT
63 case IpiRemoteCall_VCPUInjectInterrupt: {
64 virq_t virq;
65 virq.words[0] = arg2;
66 handleVCPUInjectInterruptIPI((vcpu_t *) arg0, arg1, virq);
67 break;
68 }
69 #endif
70
71 default:
72 fail("Invalid remote call");
73 break;
74 }
75
76 big_kernel_lock.node_owners[getCurrentCPUIndex()].ipi = 0;
77 ipi_wait(totalCoreBarrier);
78 }
79 }
80
ipi_send_mask(irq_t ipi,word_t mask,bool_t isBlocking)81 void ipi_send_mask(irq_t ipi, word_t mask, bool_t isBlocking)
82 {
83 generic_ipi_send_mask(ipi, mask, isBlocking);
84 }
85 #endif /* ENABLE_SMP_SUPPORT */
86