199040Sbenno/* 299040Sbenno * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 399040Sbenno * 4139825Simp * SPDX-License-Identifier: GPL-2.0-only 599040Sbenno */ 699040Sbenno 799040Sbenno#pragma once 899040Sbenno 999040Sbenno#include <util.h> 1099040Sbenno#include <arch/machine/registerset.h> 1199040Sbenno#include <arch/machine/hardware.h> 1299040Sbenno#include <arch/smp/ipi_inline.h> 1399040Sbenno 1499040Sbennostatic inline void set_fs_off(void) 1599040Sbenno{ 1699040Sbenno asm volatile("csrc sstatus, %0" :: "rK"(SSTATUS_FS)); 1799040Sbenno} 1899040Sbenno 1999040Sbenno#ifdef CONFIG_HAVE_FPU 2099040Sbenno#if defined(CONFIG_RISCV_EXT_D) 2199040Sbenno 2299040Sbenno#define FL "fld" 2399040Sbenno#define FS "fsd" 2499040Sbenno#define FP_REG_BYTES "8" 2599040Sbenno 2699040Sbenno#elif defined(CONFIG_RISCV_EXT_F) 2799040Sbenno 2899040Sbenno#define FL "flw" 2999040Sbenno#define FS "fsw" 3099040Sbenno#define FP_REG_TYPES "4" 3199040Sbenno 3299040Sbenno#endif 3399040Sbenno 3499040Sbennoextern bool_t isFPUEnabledCached[CONFIG_MAX_NUM_NODES]; 3599040Sbenno 3699040Sbennostatic inline void set_fs_clean(void) 3799040Sbenno{ 3899040Sbenno asm volatile("csrs sstatus, %0" :: "rK"(SSTATUS_FS_CLEAN)); 3999040Sbenno} 4099040Sbenno 4199040Sbennostatic inline void set_fs_initial(void) 4299040Sbenno{ 4399040Sbenno asm volatile("csrs sstatus, %0" :: "rK"(SSTATUS_FS_INITIAL)); 4499040Sbenno} 4599040Sbenno 4699040Sbennostatic inline void set_fs_dirty(void) 4799040Sbenno{ 4899040Sbenno asm volatile("csrs sstatus, %0" :: "rK"(SSTATUS_FS_DIRTY)); 4999040Sbenno} 5099040Sbenno 5199040Sbennostatic inline word_t read_sstatus_fs(void) 5299040Sbenno{ 5399040Sbenno return (read_sstatus() & SSTATUS_FS); 5499040Sbenno} 5599040Sbenno 5699040Sbenno/* We unconditionally enable FPU accesses in kernel 5799040Sbenno * mode for save and store functions. The field 5899040Sbenno * we be set again before returning to user-mode 5999040Sbenno * to actually enable/disable FPU accesses in 6099040Sbenno * user mode. 6199040Sbenno */ 6299040Sbennostatic inline void saveFpuState(user_fpu_state_t *dest) 6399040Sbenno{ 6499040Sbenno set_fs_clean(); 6599040Sbenno 6699040Sbenno asm volatile( 6799040Sbenno FS " f0, 0*" FP_REG_BYTES "(%0)\n\t" 6899040Sbenno FS " f1, 1*" FP_REG_BYTES "(%0)\n\t" 6999040Sbenno FS " f2, 2*" FP_REG_BYTES "(%0)\n\t" 7099040Sbenno FS " f3, 3*" FP_REG_BYTES "(%0)\n\t" 7199040Sbenno FS " f4, 4*" FP_REG_BYTES "(%0)\n\t" 7299040Sbenno FS " f5, 5*" FP_REG_BYTES "(%0)\n\t" 7399040Sbenno FS " f6, 6*" FP_REG_BYTES "(%0)\n\t" 7499040Sbenno FS " f7, 7*" FP_REG_BYTES "(%0)\n\t" 7599040Sbenno FS " f8, 8*" FP_REG_BYTES "(%0)\n\t" 7699040Sbenno FS " f9, 9*" FP_REG_BYTES "(%0)\n\t" 7799040Sbenno FS " f10, 10*" FP_REG_BYTES "(%0)\n\t" 7899040Sbenno FS " f11, 11*" FP_REG_BYTES "(%0)\n\t" 7999040Sbenno FS " f12, 12*" FP_REG_BYTES "(%0)\n\t" 8099040Sbenno FS " f13, 13*" FP_REG_BYTES "(%0)\n\t" 8199040Sbenno FS " f14, 14*" FP_REG_BYTES "(%0)\n\t" 8299040Sbenno FS " f15, 15*" FP_REG_BYTES "(%0)\n\t" 8399040Sbenno FS " f16, 16*" FP_REG_BYTES "(%0)\n\t" 8499040Sbenno FS " f17, 17*" FP_REG_BYTES "(%0)\n\t" 8599040Sbenno FS " f18, 18*" FP_REG_BYTES "(%0)\n\t" 8699040Sbenno FS " f19, 19*" FP_REG_BYTES "(%0)\n\t" 8799040Sbenno FS " f20, 20*" FP_REG_BYTES "(%0)\n\t" 8899040Sbenno FS " f21, 21*" FP_REG_BYTES "(%0)\n\t" 8999040Sbenno FS " f22, 22*" FP_REG_BYTES "(%0)\n\t" 9099040Sbenno FS " f23, 23*" FP_REG_BYTES "(%0)\n\t" 9199040Sbenno FS " f24, 24*" FP_REG_BYTES "(%0)\n\t" 9299040Sbenno FS " f25, 25*" FP_REG_BYTES "(%0)\n\t" 9399040Sbenno FS " f26, 26*" FP_REG_BYTES "(%0)\n\t" 9499040Sbenno FS " f27, 27*" FP_REG_BYTES "(%0)\n\t" 9599040Sbenno FS " f28, 28*" FP_REG_BYTES "(%0)\n\t" 9699040Sbenno FS " f29, 29*" FP_REG_BYTES "(%0)\n\t" 9799040Sbenno FS " f30, 30*" FP_REG_BYTES "(%0)\n\t" 9899040Sbenno FS " f31, 31*" FP_REG_BYTES "(%0)\n\t" 9999040Sbenno : 10099040Sbenno : "r"(&dest->regs[0]) 10199040Sbenno : "memory" 10299040Sbenno ); 10399040Sbenno 10499040Sbenno dest->fcsr = read_fcsr(); 10599040Sbenno} 10699040Sbenno 10799040Sbennostatic inline void loadFpuState(user_fpu_state_t *src) 10899040Sbenno{ 10999040Sbenno set_fs_clean(); 11099040Sbenno 11199040Sbenno asm volatile( 11299040Sbenno FL " f0, 0*" FP_REG_BYTES "(%0)\n\t" 11399040Sbenno FL " f1, 1*" FP_REG_BYTES "(%0)\n\t" 11499040Sbenno FL " f2, 2*" FP_REG_BYTES "(%0)\n\t" 11599040Sbenno FL " f3, 3*" FP_REG_BYTES "(%0)\n\t" 11699040Sbenno FL " f4, 4*" FP_REG_BYTES "(%0)\n\t" 11799040Sbenno FL " f5, 5*" FP_REG_BYTES "(%0)\n\t" 11899040Sbenno FL " f6, 6*" FP_REG_BYTES "(%0)\n\t" 11999040Sbenno FL " f7, 7*" FP_REG_BYTES "(%0)\n\t" 12099040Sbenno FL " f8, 8*" FP_REG_BYTES "(%0)\n\t" 12199040Sbenno FL " f9, 9*" FP_REG_BYTES "(%0)\n\t" 12299040Sbenno FL " f10, 10*" FP_REG_BYTES "(%0)\n\t" 12399040Sbenno FL " f11, 11*" FP_REG_BYTES "(%0)\n\t" 12499040Sbenno FL " f12, 12*" FP_REG_BYTES "(%0)\n\t" 12599040Sbenno FL " f13, 13*" FP_REG_BYTES "(%0)\n\t" 12699040Sbenno FL " f14, 14*" FP_REG_BYTES "(%0)\n\t" 12799040Sbenno FL " f15, 15*" FP_REG_BYTES "(%0)\n\t" 12899040Sbenno FL " f16, 16*" FP_REG_BYTES "(%0)\n\t" 12999040Sbenno FL " f17, 17*" FP_REG_BYTES "(%0)\n\t" 13099040Sbenno FL " f18, 18*" FP_REG_BYTES "(%0)\n\t" 13199040Sbenno FL " f19, 19*" FP_REG_BYTES "(%0)\n\t" 13299040Sbenno FL " f20, 20*" FP_REG_BYTES "(%0)\n\t" 13399040Sbenno FL " f21, 21*" FP_REG_BYTES "(%0)\n\t" 13499040Sbenno FL " f22, 22*" FP_REG_BYTES "(%0)\n\t" 13599040Sbenno FL " f23, 23*" FP_REG_BYTES "(%0)\n\t" 13699040Sbenno FL " f24, 24*" FP_REG_BYTES "(%0)\n\t" 13799040Sbenno FL " f25, 25*" FP_REG_BYTES "(%0)\n\t" 13899040Sbenno FL " f26, 26*" FP_REG_BYTES "(%0)\n\t" 13999040Sbenno FL " f27, 27*" FP_REG_BYTES "(%0)\n\t" 14099040Sbenno FL " f28, 28*" FP_REG_BYTES "(%0)\n\t" 14199040Sbenno FL " f29, 29*" FP_REG_BYTES "(%0)\n\t" 14299040Sbenno FL " f30, 30*" FP_REG_BYTES "(%0)\n\t" 14399040Sbenno FL " f31, 31*" FP_REG_BYTES "(%0)\n\t" 14499040Sbenno : 14599040Sbenno : "r"(&src->regs[0]) 14699040Sbenno ); 14799040Sbenno 14899040Sbenno write_fcsr(src->fcsr); 14999040Sbenno} 15099040Sbenno 15199040Sbennostatic inline void enableFpu(void) 15299040Sbenno{ 15399040Sbenno isFPUEnabledCached[SMP_TERNARY(getCurrentCPUIndex(), 0)] = true; 15499040Sbenno} 15599040Sbenno 15699040Sbennostatic inline void disableFpu(void) 15799040Sbenno{ 15899040Sbenno isFPUEnabledCached[SMP_TERNARY(getCurrentCPUIndex(), 0)] = false; 15999040Sbenno} 16099040Sbenno 16199040Sbennostatic inline bool_t isFpuEnable(void) 16299040Sbenno{ 16399040Sbenno return isFPUEnabledCached[SMP_TERNARY(getCurrentCPUIndex(), 0)]; 16499040Sbenno} 16599040Sbenno 16699040Sbennostatic inline void set_tcb_fs_state(tcb_t *tcb, bool_t enabled) 16799040Sbenno{ 16899040Sbenno word_t sstatus = getRegister(tcb, SSTATUS); 16999040Sbenno sstatus &= ~SSTATUS_FS; 17099040Sbenno if (enabled) { 17199040Sbenno sstatus |= SSTATUS_FS_CLEAN; 17299040Sbenno } 17399040Sbenno setRegister(tcb, SSTATUS, sstatus); 17499040Sbenno} 17599040Sbenno 17699040Sbenno#endif /* end of CONFIG_HAVE_FPU */ 17799040Sbenno