1251881Speter/* 2251881Speter * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3251881Speter * 4251881Speter * SPDX-License-Identifier: GPL-2.0-only 5251881Speter */ 6251881Speter 7251881Speter#include <config.h> 8251881Speter#include <mode/smp/ipi.h> 9251881Speter#include <smp/lock.h> 10251881Speter#include <util.h> 11251881Speter 12251881Speter#ifdef ENABLE_SMP_SUPPORT 13251881Speter 14251881Speter/* the remote call being requested */ 15251881Speterstatic volatile IpiRemoteCall_t remoteCall; 16251881Speterstatic volatile irq_t ipiIrq[CONFIG_MAX_NUM_NODES]; 17251881Speter 18251881Speterstatic inline void init_ipi_args(IpiRemoteCall_t func, 19251881Speter word_t data1, word_t data2, word_t data3, 20251881Speter word_t mask) 21251881Speter{ 22251881Speter remoteCall = func; 23251881Speter ipi_args[0] = data1; 24251881Speter ipi_args[1] = data2; 25251881Speter ipi_args[2] = data3; 26251881Speter 27251881Speter /* get number of cores involved in this IPI */ 28251881Speter totalCoreBarrier = popcountl(mask); 29251881Speter} 30251881Speter 31251881Speterstatic void handleRemoteCall(IpiRemoteCall_t call, word_t arg0, 32251881Speter word_t arg1, word_t arg2, bool_t irqPath) 33251881Speter{ 34251881Speter /* we gets spurious irq_remote_call_ipi calls, e.g. when handling IPI 35251881Speter * in lock while hardware IPI is pending. Guard against spurious IPIs! */ 36251881Speter if (clh_is_ipi_pending(getCurrentCPUIndex())) { 37251881Speter switch ((IpiRemoteCall_t)call) { 38251881Speter case IpiRemoteCall_Stall: 39251881Speter ipiStallCoreCallback(irqPath); 40251881Speter break; 41251881Speter 42251881Speter#ifdef CONFIG_HAVE_FPU 43251881Speter case IpiRemoteCall_switchFpuOwner: 44251881Speter switchLocalFpuOwner((user_fpu_state_t *)arg0); 45251881Speter break; 46251881Speter#endif /* CONFIG_HAVE_FPU */ 47251881Speter 48251881Speter default: 49251881Speter fail("Invalid remote call"); 50251881Speter break; 51251881Speter } 52251881Speter 53251881Speter big_kernel_lock.node_owners[getCurrentCPUIndex()].ipi = 0; 54251881Speter ipiIrq[getCurrentCPUIndex()] = irqInvalid; 55251881Speter ipi_wait(totalCoreBarrier); 56251881Speter } 57251881Speter} 58251881Speter 59251881Spetervoid ipi_send_mask(irq_t ipi, word_t mask, bool_t isBlocking) 60251881Speter{ 61251881Speter 62251881Speter generic_ipi_send_mask(ipi, mask, isBlocking); 63251881Speter} 64251881Speter 65251881Speterirq_t ipi_get_irq(void) 66251881Speter{ 67251881Speter assert(!(ipiIrq[getCurrentCPUIndex()] == irqInvalid && big_kernel_lock.node_owners[getCurrentCPUIndex()].ipi == 1)); 68251881Speter return ipiIrq[getCurrentCPUIndex()]; 69251881Speter} 70251881Speter 71251881Spetervoid ipi_clear_irq(irq_t irq) 72251881Speter{ 73251881Speter ipiIrq[getCurrentCPUIndex()] = irqInvalid; 74251881Speter return; 75251881Speter} 76251881Speter 77251881Speter/* this function is called with a single hart id. */ 78251881Spetervoid ipi_send_target(irq_t irq, word_t hart_id) 79251881Speter{ 80251881Speter unsigned long hart_mask; 81251881Speter word_t core_id = hartIDToCoreID(hart_id); 82251881Speter assert(core_id < CONFIG_MAX_NUM_NODES); 83251881Speter hart_mask = BIT(hart_id); 84251881Speter 85251881Speter assert((ipiIrq[core_id] == irqInvalid) || (ipiIrq[core_id] == irq_reschedule_ipi) || 86251881Speter (ipiIrq[core_id] == irq_remote_call_ipi && big_kernel_lock.node_owners[core_id].ipi == 0)); 87251881Speter 88251881Speter ipiIrq[core_id] = irq; 89251881Speter asm volatile("fence rw,rw"); 90251881Speter sbi_send_ipi(&hart_mask); 91251881Speter} 92251881Speter 93251881Speter#endif 94251881Speter