diff --git a/thermosphere/src/core_ctx.c b/thermosphere/src/core_ctx.c deleted file mode 100644 index 47d74d2f5..000000000 --- a/thermosphere/src/core_ctx.c +++ /dev/null @@ -1,53 +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 "core_ctx.h" -#include "memory_map.h" - -// start.s -extern uintptr_t g_initialKernelEntrypoint; - -static atomic_uint g_activeCoreMask = 0; - -// Prevents it from being put in BSS -CoreCtx g_coreCtxs[4] = { - { .coreId = 0 }, - { .coreId = 1 }, - { .coreId = 2 }, - { .coreId = 3 }, -}; - -void coreCtxInit(u32 coreId, bool isBootCore, u64 argument) -{ - size_t crashStackSize = 0x1000 / 4; - currentCoreCtx = &g_coreCtxs[coreId]; - currentCoreCtx->isBootCore = isBootCore; - currentCoreCtx->kernelArgument = argument; - currentCoreCtx->crashStack = (u8 *)(MEMORY_MAP_VA_CRASH_STACKS_TOP - crashStackSize * coreId); - if (isBootCore && currentCoreCtx->kernelEntrypoint == 0) { - currentCoreCtx->kernelEntrypoint = g_initialKernelEntrypoint; - } -} - -void setCurrentCoreActive(void) -{ - atomic_fetch_or(&g_activeCoreMask, BIT(currentCoreCtx->coreId)); -} - -u32 getActiveCoreMask(void) -{ - return (u32)atomic_load(&g_activeCoreMask); -} diff --git a/thermosphere/src/guest_timers.h b/thermosphere/src/guest_timers.h deleted file mode 100644 index 70a352065..000000000 --- a/thermosphere/src/guest_timers.h +++ /dev/null @@ -1,34 +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 "exceptions.h" -#include "sysreg.h" - -static inline u64 computeCntvct(const ExceptionStackFrame *frame) -{ - return frame->cntpct_el0 - currentCoreCtx->totalTimeInHypervisor; -} - -static inline void writeEmulatedPhysicalCompareValue(ExceptionStackFrame *frame, u64 val) -{ - // We lied about the value of cntpct, so we need to compute the time delta - // the guest actually intended to use... - u64 vct = computeCntvct(frame); - currentCoreCtx->emulPtimerCval = val; - SET_SYSREG(cntp_cval_el0, frame->cntpct_el0 + (val - vct)); -} diff --git a/thermosphere/src/hvisor_guest_timers.hpp b/thermosphere/src/hvisor_guest_timers.hpp new file mode 100644 index 000000000..42a517f4a --- /dev/null +++ b/thermosphere/src/hvisor_guest_timers.hpp @@ -0,0 +1,63 @@ +/* + * 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 "hvisor_core_context.hpp" +#include "hvisor_exception_stack_frame.hpp" +#include "cpu/hvisor_cpu_sysreg_general.hpp" + +namespace ams::hvisor { + + static inline u64 ComputeCntvct(const ExceptionStackFrame *frame) + { + return frame->cntpct_el0 - currentCoreCtx->GetTotalTimeInHypervisor(); + } + + static inline void WriteEmulatedPhysicalCompareValue(ExceptionStackFrame *frame, u64 val) + { + // We lied about the value of cntpct, so we need to compute the time delta + // the guest actually intended to use... + u64 vct = ComputeCntvct(frame); + currentCoreCtx->SetEmulPtimerCval(val); + THERMOSPHERE_SET_SYSREG(cntp_cval_el0, frame->cntpct_el0 + (val - vct)); + } + + static inline bool CheckRescheduleEmulatedPtimer(ExceptionStackFrame *frame) + { + // Evaluate if the timer has really expired in the PoV of the guest kernel. + // If not, reschedule (add missed time delta) it & exit early + u64 cval = currentCoreCtx->GetEmulPtimerCval(); + u64 vct = ComputeCntvct(frame); + + if (cval > vct) { + // It has not: reschedule the timer + // Note: this isn't 100% precise esp. on QEMU so it may take a few tries... + WriteEmulatedPhysicalCompareValue(frame, cval); + return false; + } + + return true; + } + + static inline void EnableGuestTimerTraps(void) + { + // Disable event streams, trap everything + u64 cnthctl = 0; + THERMOSPHERE_SET_SYSREG(cnthctl_el2, cnthctl); + } + +} diff --git a/thermosphere/src/hvisor_irq_manager.cpp b/thermosphere/src/hvisor_irq_manager.cpp index 7baef2fc9..0efbd60bd 100644 --- a/thermosphere/src/hvisor_irq_manager.cpp +++ b/thermosphere/src/hvisor_irq_manager.cpp @@ -19,10 +19,10 @@ #include "hvisor_irq_manager.hpp" #include "hvisor_virtual_gic.hpp" #include "hvisor_core_context.hpp" +#include "hvisor_guest_timers.hpp" #include "cpu/hvisor_cpu_interrupt_mask_guard.hpp" #include "platform/interrupt_config.h" -#include "guest_timers.h" #include "transport_interface.h" #include "timer.h" @@ -30,32 +30,15 @@ namespace { - inline bool checkRescheduleEmulatedPtimer(ExceptionStackFrame *frame) - { - // Evaluate if the timer has really expired in the PoV of the guest kernel. - // If not, reschedule (add missed time delta) it & exit early - u64 cval = currentCoreCtx->emulPtimerCval; - u64 vct = computeCntvct(frame); - - if (cval > vct) { - // It has not: reschedule the timer - // Note: this isn't 100% precise esp. on QEMU so it may take a few tries... - writeEmulatedPhysicalCompareValue(frame, cval); - return false; - } - - return true; - } - - inline bool checkGuestTimerInterrupts(ExceptionStackFrame *frame, u32 irqId) + inline bool CheckGuestTimerInterrupts(ams::hvisor::ExceptionStackFrame *frame, u32 irqId) { // A thing that might have happened is losing the race vs disabling the guest interrupts // Another thing is that the virtual timer might have fired before us updating voff when executing a top half? if (irqId == TIMER_IRQID(NS_VIRT_TIMER)) { u64 cval = THERMOSPHERE_GET_SYSREG(cntp_cval_el0); - return cval <= computeCntvct(frame); + return cval <= ams::hvisor::ComputeCntvct(frame); } else if (irqId == TIMER_IRQID(NS_PHYS_TIMER)) { - return checkRescheduleEmulatedPtimer(frame); + return ams::hvisor::CheckRescheduleEmulatedPtimer(frame); } else { return true; } @@ -198,7 +181,7 @@ namespace ams::hvisor { if (irqId == GicV2Distributor::spuriousIrqId) { // Spurious interrupt received return; - } else if (!checkGuestTimerInterrupts(frame, irqId)) { + } else if (!CheckGuestTimerInterrupts(frame, irqId)) { // Deactivate the interrupt, return ASAP DropCurrentInterruptPriority(iar); DeactivateCurrentInterrupt(iar);