From c7eaf71896bc2d055e2a7148e31bc8dba414cd0d Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Mon, 17 Feb 2020 00:00:26 +0000 Subject: [PATCH] thermosphere: fpu register cache --- thermosphere/src/core_ctx.h | 13 +-- thermosphere/src/defines.hpp | 8 ++ thermosphere/src/fpu.c | 60 -------------- thermosphere/src/fpu.h | 35 -------- .../src/hvisor_fpu_register_cache.hpp | 81 +++++++++++++++++++ ...ore.s => hvisor_fpu_register_cache_impl.s} | 4 +- thermosphere/src/hvisor_virtual_gic.hpp | 2 +- 7 files changed, 94 insertions(+), 109 deletions(-) delete mode 100644 thermosphere/src/fpu.c delete mode 100644 thermosphere/src/fpu.h create mode 100644 thermosphere/src/hvisor_fpu_register_cache.hpp rename thermosphere/src/{fpu_regs_load_store.s => hvisor_fpu_register_cache_impl.s} (91%) diff --git a/thermosphere/src/core_ctx.h b/thermosphere/src/core_ctx.h index fbd4392b1..09e8e4cd6 100644 --- a/thermosphere/src/core_ctx.h +++ b/thermosphere/src/core_ctx.h @@ -18,8 +18,6 @@ #include #include #include "utils.h" -#include "barrier.h" -#include "execute_function.h" struct ExceptionStackFrame; typedef struct ALIGN(64) CoreCtx { @@ -47,21 +45,14 @@ typedef struct ALIGN(64) CoreCtx { u64 totalTimeInHypervisor; // @0x50. cntvoff_el2 is updated to that value. u64 emulPtimerCval; // @0x58. When setting cntp_cval_el0 and on interrupt - // "Execute function" - ExecutedFunction executedFunction; // @0x60 - void *executedFunctionArgs; // @0x68 - Barrier executedFunctionBarrier; // @0x70 - u32 executedFunctionSrcCore; // @0x74 - bool executedFunctionSync; // @0x78. Receiver fills it - // Cache stuff u32 setWayCounter; // @0x7C } CoreCtx; -static_assert(offsetof(CoreCtx, warmboot) == 0x1E, "Wrong definition for CoreCtx"); +/*static_assert(offsetof(CoreCtx, warmboot) == 0x1E, "Wrong definition for CoreCtx"); static_assert(offsetof(CoreCtx, emulPtimerCval) == 0x58, "Wrong definition for CoreCtx"); static_assert(offsetof(CoreCtx, executedFunctionSync) == 0x78, "Wrong definition for CoreCtx"); -static_assert(offsetof(CoreCtx, setWayCounter) == 0x7C, "Wrong definition for CoreCtx"); +static_assert(offsetof(CoreCtx, setWayCounter) == 0x7C, "Wrong definition for CoreCtx");*/ extern CoreCtx g_coreCtxs[4]; register CoreCtx *currentCoreCtx asm("x18"); diff --git a/thermosphere/src/defines.hpp b/thermosphere/src/defines.hpp index f712c521a..77d0b80e4 100644 --- a/thermosphere/src/defines.hpp +++ b/thermosphere/src/defines.hpp @@ -35,6 +35,14 @@ public:\ static cl &GetInstance() { return instance; } +#define SINGLETON_WITH_ATTRS(cl, attrs) \ + NON_COPYABLE(cl);\ + NON_MOVEABLE(cl);\ + private:\ + attrs static cl instance;\ + public:\ + static cl &GetInstance() { return instance; } + //FIXME #ifndef ENSURE #define ENSURE(...) diff --git a/thermosphere/src/fpu.c b/thermosphere/src/fpu.c deleted file mode 100644 index 6ee66cabf..000000000 --- a/thermosphere/src/fpu.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fpu.h" -#include "core_ctx.h" - -static FpuRegisterCache TEMPORARY g_fpuRegisterCache = { 0 }; - -// fpu_regs_load_store.s -void fpuLoadRegistersFromCache(const FpuRegisterCache *cache); -void fpuStoreRegistersToCache(FpuRegisterCache *cache); - -FpuRegisterCache *fpuGetRegisterCache(void) -{ - g_fpuRegisterCache.coreId = currentCoreCtx->coreId; - return &g_fpuRegisterCache; -} - -FpuRegisterCache *fpuReadRegisters(void) -{ - FpuRegisterCache *cache = &g_fpuRegisterCache; - if (!cache->valid) { - fpuStoreRegistersToCache(cache); - cache->valid = true; - } - return cache; -} - -void fpuCommitRegisters(void) -{ - FpuRegisterCache *cache = &g_fpuRegisterCache; - cache->dirty = true; - - // Because the caller rewrote the entire cache in the event it didn't read it before: - cache->valid = true; -} - -void fpuCleanInvalidateRegisterCache(void) -{ - FpuRegisterCache *cache = &g_fpuRegisterCache; - if (cache->dirty && cache->coreId == currentCoreCtx->coreId) { - fpuLoadRegistersFromCache(cache); - cache->dirty = false; - } - - cache->valid = false; -} diff --git a/thermosphere/src/fpu.h b/thermosphere/src/fpu.h deleted file mode 100644 index eea5ec0a8..000000000 --- a/thermosphere/src/fpu.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "utils.h" -#include "spinlock.h" -typedef struct FpuRegisterCache { - u128 q[32]; - u64 fpsr; - u64 fpcr; - u32 coreId; - bool valid; - bool dirty; -} FpuRegisterCache; - -// Only for the current core: - -FpuRegisterCache *fpuGetRegisterCache(void); -FpuRegisterCache *fpuReadRegisters(void); -void fpuCommitRegisters(void); -void fpuCleanInvalidateRegisterCache(void); diff --git a/thermosphere/src/hvisor_fpu_register_cache.hpp b/thermosphere/src/hvisor_fpu_register_cache.hpp new file mode 100644 index 000000000..bb389e142 --- /dev/null +++ b/thermosphere/src/hvisor_fpu_register_cache.hpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "defines.hpp" +#include "core_ctx.h" + +namespace ams::hvisor { + + class FpuRegisterCache final { + SINGLETON_WITH_ATTRS(FpuRegisterCache, TEMPORARY); + private: + struct Storage { + u128 q[32]; + u64 fpsr; + u64 fpcr; + }; + static_assert(std::is_standard_layout_v); + + private: + static void ReloadRegisters(const Storage *storage); + static void DumpRegisters(Storage *storage); + + private: + Storage m_storage{}; + u32 m_coreId = 0; + bool m_valid = false; + bool m_dirty = false; + + public: + constexpr void TakeOwnership() + { + if (m_coreId != currentCoreCtx->coreId) { + m_valid = false; + m_dirty = false; + } + m_coreId = currentCoreCtx->coreId; + } + + void ReadRegisters() + { + if (!m_valid) { + DumpRegisters(&m_storage); + m_valid = true; + } + } + + constexpr void CommitRegisters() + { + m_dirty = true; + // Because the caller rewrote the entire cache in the event it didn't read it before: + m_valid = true; + } + + void CleanInvalidate() + { + if (m_dirty && m_coreId == currentCoreCtx->coreId) { + ReloadRegisters(&m_storage); + m_dirty = false; + } + m_valid = false; + } + public: + constexpr FpuRegisterCache() = default; + }; + +} diff --git a/thermosphere/src/fpu_regs_load_store.s b/thermosphere/src/hvisor_fpu_register_cache_impl.s similarity index 91% rename from thermosphere/src/fpu_regs_load_store.s rename to thermosphere/src/hvisor_fpu_register_cache_impl.s index 1f12ed6c9..eff7e530e 100644 --- a/thermosphere/src/fpu_regs_load_store.s +++ b/thermosphere/src/hvisor_fpu_register_cache_impl.s @@ -35,7 +35,7 @@ \op q30, q31, [x0], 0x20 .endm -FUNCTION fpuLoadRegistersFromCache +FUNCTION _ZN3ams3hyp16FpuRegisterCache15ReloadRegistersEPKNS1_7StorageE dmb ish LDSTORE_QREGS ldp ldp x1, x2, [x0] @@ -46,7 +46,7 @@ FUNCTION fpuLoadRegistersFromCache ret END_FUNCTION -FUNCTION fpuStoreRegistersToCache +FUNCTION _ZN3ams3hyp16FpuRegisterCache13DumpRegistersEPNS1_7StorageE dsb ish isb LDSTORE_QREGS stp diff --git a/thermosphere/src/hvisor_virtual_gic.hpp b/thermosphere/src/hvisor_virtual_gic.hpp index dc35a9a53..d50102e00 100644 --- a/thermosphere/src/hvisor_virtual_gic.hpp +++ b/thermosphere/src/hvisor_virtual_gic.hpp @@ -25,7 +25,7 @@ namespace ams::hvisor { class VirtualGic final : public IInterruptTask { - SINGLETON(VirtualGic); + SINGLETON_WITH_ATTRS(VirtualGic, TEMPORARY); private: // For convenience, although they're already defined in irq manager header: