thermosphere: fpu register cache

This commit is contained in:
TuxSH 2020-02-17 00:00:26 +00:00
parent 5a445e9394
commit c7eaf71896
7 changed files with 94 additions and 109 deletions

View file

@ -18,8 +18,6 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <assert.h> #include <assert.h>
#include "utils.h" #include "utils.h"
#include "barrier.h"
#include "execute_function.h"
struct ExceptionStackFrame; struct ExceptionStackFrame;
typedef struct ALIGN(64) CoreCtx { 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 totalTimeInHypervisor; // @0x50. cntvoff_el2 is updated to that value.
u64 emulPtimerCval; // @0x58. When setting cntp_cval_el0 and on interrupt 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 // Cache stuff
u32 setWayCounter; // @0x7C u32 setWayCounter; // @0x7C
} CoreCtx; } 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, emulPtimerCval) == 0x58, "Wrong definition for CoreCtx");
static_assert(offsetof(CoreCtx, executedFunctionSync) == 0x78, "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]; extern CoreCtx g_coreCtxs[4];
register CoreCtx *currentCoreCtx asm("x18"); register CoreCtx *currentCoreCtx asm("x18");

View file

@ -35,6 +35,14 @@
public:\ public:\
static cl &GetInstance() { return instance; } 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 //FIXME
#ifndef ENSURE #ifndef ENSURE
#define ENSURE(...) #define ENSURE(...)

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<Storage>);
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;
};
}

View file

@ -35,7 +35,7 @@
\op q30, q31, [x0], 0x20 \op q30, q31, [x0], 0x20
.endm .endm
FUNCTION fpuLoadRegistersFromCache FUNCTION _ZN3ams3hyp16FpuRegisterCache15ReloadRegistersEPKNS1_7StorageE
dmb ish dmb ish
LDSTORE_QREGS ldp LDSTORE_QREGS ldp
ldp x1, x2, [x0] ldp x1, x2, [x0]
@ -46,7 +46,7 @@ FUNCTION fpuLoadRegistersFromCache
ret ret
END_FUNCTION END_FUNCTION
FUNCTION fpuStoreRegistersToCache FUNCTION _ZN3ams3hyp16FpuRegisterCache13DumpRegistersEPNS1_7StorageE
dsb ish dsb ish
isb isb
LDSTORE_QREGS stp LDSTORE_QREGS stp

View file

@ -25,7 +25,7 @@
namespace ams::hvisor { namespace ams::hvisor {
class VirtualGic final : public IInterruptTask { class VirtualGic final : public IInterruptTask {
SINGLETON(VirtualGic); SINGLETON_WITH_ATTRS(VirtualGic, TEMPORARY);
private: private:
// For convenience, although they're already defined in irq manager header: // For convenience, although they're already defined in irq manager header: