mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
thermosphere: fpu register cache
This commit is contained in:
parent
5a445e9394
commit
c7eaf71896
7 changed files with 94 additions and 109 deletions
|
@ -18,8 +18,6 @@
|
|||
#include <stdatomic.h>
|
||||
#include <assert.h>
|
||||
#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");
|
||||
|
|
|
@ -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(...)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
81
thermosphere/src/hvisor_fpu_register_cache.hpp
Normal file
81
thermosphere/src/hvisor_fpu_register_cache.hpp
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue