mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 09:36:35 +00:00
thermosphere: rework fpu register handling
This commit is contained in:
parent
5b545f89f5
commit
97c4595a3a
5 changed files with 45 additions and 21 deletions
|
@ -27,6 +27,8 @@
|
||||||
#include "debug_pause.h"
|
#include "debug_pause.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include "fpu.h"
|
||||||
|
|
||||||
bool spsrEvaluateConditionCode(u64 spsr, u32 conditionCode)
|
bool spsrEvaluateConditionCode(u64 spsr, u32 conditionCode)
|
||||||
{
|
{
|
||||||
if (conditionCode == 14) {
|
if (conditionCode == 14) {
|
||||||
|
@ -121,6 +123,7 @@ void exceptionReturnPreprocess(ExceptionStackFrame *frame)
|
||||||
// Were we paused & are we about to return to the guest?
|
// Were we paused & are we about to return to the guest?
|
||||||
exceptionEnterInterruptibleHypervisorCode();
|
exceptionEnterInterruptibleHypervisorCode();
|
||||||
debugPauseWaitAndUpdateSingleStep();
|
debugPauseWaitAndUpdateSingleStep();
|
||||||
|
fpuCleanInvalidateRegisterCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update virtual counter
|
// Update virtual counter
|
||||||
|
|
|
@ -15,33 +15,45 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fpu.h"
|
#include "fpu.h"
|
||||||
#include "execute_function.h"
|
|
||||||
#include "core_ctx.h"
|
#include "core_ctx.h"
|
||||||
|
|
||||||
FpuRegisterStorage TEMPORARY g_fpuRegisterStorage[4] = { 0 };
|
static FpuRegisterCache TEMPORARY g_fpuRegisterCache[4] = { 0 };
|
||||||
|
|
||||||
// fpu_regs_load_store.s
|
// fpu_regs_load_store.s
|
||||||
void fpuLoadRegistersFromStorage(const FpuRegisterStorage *storage);
|
void fpuLoadRegistersFromCache(const FpuRegisterCache *cache);
|
||||||
void fpuStoreRegistersToStorage(FpuRegisterStorage *storage);
|
void fpuStoreRegistersToCache(FpuRegisterCache *cache);
|
||||||
|
|
||||||
static void fpuDumpRegistersImpl(void *p)
|
FpuRegisterCache *fpuGetRegisterCache(void)
|
||||||
{
|
{
|
||||||
(void)p;
|
return &g_fpuRegisterCache[currentCoreCtx->coreId];
|
||||||
fpuStoreRegistersToStorage(&g_fpuRegisterStorage[currentCoreCtx->coreId]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fpuRestoreRegistersImpl(void *p)
|
FpuRegisterCache *fpuReadRegisters(void)
|
||||||
{
|
{
|
||||||
(void)p;
|
FpuRegisterCache *cache = &g_fpuRegisterCache[currentCoreCtx->coreId];
|
||||||
fpuLoadRegistersFromStorage(&g_fpuRegisterStorage[currentCoreCtx->coreId]);
|
if (!cache->valid) {
|
||||||
|
fpuStoreRegistersToCache(cache);
|
||||||
|
cache->valid = true;
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpuDumpRegisters(u32 coreList)
|
void fpuCommitRegisters(void)
|
||||||
{
|
{
|
||||||
executeFunctionOnCores(fpuDumpRegistersImpl, NULL, true, coreList);
|
FpuRegisterCache *cache = &g_fpuRegisterCache[currentCoreCtx->coreId];
|
||||||
|
cache->dirty = true;
|
||||||
|
|
||||||
|
// Because the caller rewrote the entire cache in the event it didn't read it before:
|
||||||
|
cache->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpuRestoreRegisters(u32 coreList)
|
void fpuCleanInvalidateRegisterCache(void)
|
||||||
{
|
{
|
||||||
executeFunctionOnCores(fpuRestoreRegistersImpl, NULL, true, coreList);
|
FpuRegisterCache *cache = &g_fpuRegisterCache[currentCoreCtx->coreId];
|
||||||
|
if (cache->dirty) {
|
||||||
|
fpuLoadRegistersFromCache(cache);
|
||||||
|
cache->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->valid = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,17 @@
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
typedef struct FpuRegisterStorage {
|
typedef struct FpuRegisterCache {
|
||||||
u128 q[32];
|
u128 q[32];
|
||||||
u64 fpsr;
|
u64 fpsr;
|
||||||
u64 fpcr;
|
u64 fpcr;
|
||||||
} FpuRegisterStorage;
|
bool valid;
|
||||||
|
bool dirty;
|
||||||
|
} FpuRegisterCache;
|
||||||
|
|
||||||
extern FpuRegisterStorage g_fpuRegisterStorage[4];
|
// Only for the current core:
|
||||||
|
|
||||||
void fpuDumpRegisters(u32 coreList);
|
FpuRegisterCache *fpuGetRegisterCache(void);
|
||||||
void fpuRestoreRegisters(u32 coreList);
|
FpuRegisterCache *fpuReadRegisters(void);
|
||||||
|
void fpuCommitRegisters(void);
|
||||||
|
void fpuCleanInvalidateRegisterCache(void);
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
\op q30, q31, [x0], 0x20
|
\op q30, q31, [x0], 0x20
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
FUNCTION fpuLoadRegistersFromStorage
|
FUNCTION fpuLoadRegistersFromCache
|
||||||
dmb ish
|
dmb ish
|
||||||
LDSTORE_QREGS ldp
|
LDSTORE_QREGS ldp
|
||||||
ldp x1, x2, [x0]
|
ldp x1, x2, [x0]
|
||||||
|
@ -46,7 +46,7 @@ FUNCTION fpuLoadRegistersFromStorage
|
||||||
ret
|
ret
|
||||||
END_FUNCTION
|
END_FUNCTION
|
||||||
|
|
||||||
FUNCTION fpuStoreRegistersToStorage
|
FUNCTION fpuStoreRegistersToCache
|
||||||
dsb ish
|
dsb ish
|
||||||
isb
|
isb
|
||||||
LDSTORE_QREGS stp
|
LDSTORE_QREGS stp
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "transport_interface.h"
|
#include "transport_interface.h"
|
||||||
#include "guest_memory.h"
|
#include "guest_memory.h"
|
||||||
|
#include "fpu.h"
|
||||||
|
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
@ -128,4 +129,8 @@ void thermosphereMain(ExceptionStackFrame *frame, u64 pct)
|
||||||
frame->elr_el2 = currentCoreCtx->kernelEntrypoint;
|
frame->elr_el2 = currentCoreCtx->kernelEntrypoint;
|
||||||
frame->x[0] = currentCoreCtx->kernelArgument;
|
frame->x[0] = currentCoreCtx->kernelArgument;
|
||||||
frame->cntpct_el0 = pct;
|
frame->cntpct_el0 = pct;
|
||||||
|
|
||||||
|
// Initialize FPU registers -- no need to memset, the regcaches are in .tempbss
|
||||||
|
fpuCommitRegisters();
|
||||||
|
fpuCleanInvalidateRegisterCache();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue