1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13#include <config.h> 14#include <machine/fpu.h> 15#include <api/failures.h> 16#include <model/statedata.h> 17#include <arch/object/structures.h> 18 19#ifdef CONFIG_HAVE_FPU 20/* Switch the owner of the FPU to the given thread on local core. */ 21void switchLocalFpuOwner(user_fpu_state_t *new_owner) 22{ 23 enableFpu(); 24 if (NODE_STATE(ksActiveFPUState)) { 25 saveFpuState(NODE_STATE(ksActiveFPUState)); 26 } 27 if (new_owner) { 28 NODE_STATE(ksFPURestoresSinceSwitch) = 0; 29 loadFpuState(new_owner); 30 } else { 31 disableFpu(); 32 } 33 NODE_STATE(ksActiveFPUState) = new_owner; 34} 35 36void switchFpuOwner(user_fpu_state_t *new_owner, word_t cpu) 37{ 38#ifdef ENABLE_SMP_SUPPORT 39 if (cpu != getCurrentCPUIndex()) { 40 doRemoteswitchFpuOwner(new_owner, cpu); 41 } else 42#endif /* ENABLE_SMP_SUPPORT */ 43 { 44 switchLocalFpuOwner(new_owner); 45 } 46} 47 48/* Handle an FPU fault. 49 * 50 * This CPU exception is thrown when userspace attempts to use the FPU while 51 * it is disabled. We need to save the current state of the FPU, and hand 52 * it over. */ 53exception_t 54handleFPUFault(void) 55{ 56 /* If we have already given the FPU to the user, we should not reach here. 57 * This should only be able to occur on CPUs without an FPU at all, which 58 * we presumably are happy to assume will not be running seL4. */ 59 assert(!nativeThreadUsingFPU(NODE_STATE(ksCurThread))); 60 61 /* Otherwise, lazily switch over the FPU. */ 62 switchLocalFpuOwner(&NODE_STATE(ksCurThread)->tcbArch.tcbContext.fpuState); 63 64 return EXCEPTION_NONE; 65} 66 67/* Prepare for the deletion of the given thread. */ 68void fpuThreadDelete(tcb_t *thread) 69{ 70 /* If the thread being deleted currently owns the FPU, switch away from it 71 * so that 'ksActiveFPUState' doesn't point to invalid memory. */ 72 if (nativeThreadUsingFPU(thread)) { 73 switchFpuOwner(NULL, SMP_TERNARY(thread->tcbAffinity, 0)); 74 } 75} 76#endif /* CONFIG_HAVE_FPU */ 77