From c99a77a0c39c4819f78610e44cbdd9e03f9dac31 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Tue, 11 Feb 2020 21:41:14 +0000 Subject: [PATCH] thermosphere: interrupt mask guard --- .../cpu/hvisor_cpu_interrupt_mask_guard.hpp | 54 +++++++++++++++++++ thermosphere/src/hvisor_irq_manager.cpp | 23 ++++---- thermosphere/src/hvisor_irq_manager.hpp | 20 ------- 3 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 thermosphere/src/cpu/hvisor_cpu_interrupt_mask_guard.hpp diff --git a/thermosphere/src/cpu/hvisor_cpu_interrupt_mask_guard.hpp b/thermosphere/src/cpu/hvisor_cpu_interrupt_mask_guard.hpp new file mode 100644 index 000000000..c75dc7f23 --- /dev/null +++ b/thermosphere/src/cpu/hvisor_cpu_interrupt_mask_guard.hpp @@ -0,0 +1,54 @@ +/* + * 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_cpu_sysreg_general.hpp" + +namespace ams::hvisor::cpu { + + static inline u64 MaskIrq() + { + u64 daif = THERMOSPHERE_GET_SYSREG(daif); + THERMOSPHERE_SET_SYSREG_IMM(daifset, BIT(1)); + return daif; + } + + static inline u64 UnmaskIrq() + { + u64 daif = THERMOSPHERE_GET_SYSREG(daif); + THERMOSPHERE_SET_SYSREG_IMM(daifclr, BIT(1)); + return daif; + } + + static inline void RestoreInterruptFlags(u64 flags) + { + THERMOSPHERE_SET_SYSREG(daif, flags); + } + + class InterruptMaskGuard final { + NON_COPYABLE(InterruptMaskGuard); + NON_MOVEABLE(InterruptMaskGuard); + private: + u64 m_flags; + public: + ALWAYS_INLINE InterruptMaskGuard() : m_flags(MaskIrq()) {} + ALWAYS_INLINE ~InterruptMaskGuard() + { + RestoreInterruptFlags(m_flags); + } + }; +} diff --git a/thermosphere/src/hvisor_irq_manager.cpp b/thermosphere/src/hvisor_irq_manager.cpp index bb5d761ab..d0b30f8b9 100644 --- a/thermosphere/src/hvisor_irq_manager.cpp +++ b/thermosphere/src/hvisor_irq_manager.cpp @@ -17,7 +17,7 @@ #include #include "hvisor_irq_manager.hpp" - +#include "cpu/hvisor_cpu_interrupt_mask_guard.hpp" #include "platform/interrupt_config.h" #include "core_ctx.h" #include "guest_timers.h" @@ -159,8 +159,8 @@ namespace ams::hvisor { void IrqManager::Initialize() { - u64 flags = MaskIrq(); - m_lock.lock(); + cpu::InterruptMaskGuard mg{}; + std::scoped_lock lk{m_lock}; InitializeGic(); for (u32 i = 0; i < MaxSgi; i++) { @@ -170,27 +170,22 @@ namespace ams::hvisor { DoConfigureInterrupt(GIC_IRQID_MAINTENANCE, hostPriority, true); vgicInit(); - - m_lock.unlock(); - RestoreInterruptFlags(flags); } void IrqManager::ConfigureInterrupt(u32 id, u8 prio, bool isLevelSensitive) { - u64 flags = MaskIrq(); - m_lock.lock(); + cpu::InterruptMaskGuard mg{}; + std::scoped_lock lk{m_lock}; + DoConfigureInterrupt(id, prio, isLevelSensitive); - m_lock.unlock(); - RestoreInterruptFlags(flags); } void IrqManager::SetInterruptAffinity(u32 id, u8 affinity) { - u64 flags = MaskIrq(); - m_lock.lock(); + cpu::InterruptMaskGuard mg{}; + std::scoped_lock lk{m_lock}; + DoSetInterruptAffinity(id, affinity); - m_lock.unlock(); - RestoreInterruptFlags(flags); } void IrqManager::HandleInterrupt(ExceptionStackFrame *frame) diff --git a/thermosphere/src/hvisor_irq_manager.hpp b/thermosphere/src/hvisor_irq_manager.hpp index 2f37200f0..4099a8c66 100644 --- a/thermosphere/src/hvisor_irq_manager.hpp +++ b/thermosphere/src/hvisor_irq_manager.hpp @@ -18,7 +18,6 @@ #include "hvisor_gicv2.hpp" #include "hvisor_synchronization.hpp" -#include "cpu/hvisor_cpu_sysreg_general.hpp" #include "memory_map.h" #include "exceptions.h" // TODO @@ -93,25 +92,6 @@ namespace ams::hvisor { gicd->sgir = GicV2Distributor::ForwardToAllOthers << 24 | id; } - static u64 MaskIrq() - { - u64 daif = THERMOSPHERE_GET_SYSREG(daif); - THERMOSPHERE_SET_SYSREG_IMM(daifset, BIT(1)); - return daif; - } - - static u64 UnmaskIrq() - { - u64 daif = THERMOSPHERE_GET_SYSREG(daif); - THERMOSPHERE_SET_SYSREG_IMM(daifclr, BIT(1)); - return daif; - } - - static void RestoreInterruptFlags(u64 flags) - { - THERMOSPHERE_SET_SYSREG(daif, flags); - } - static IrqManager &GetInstance() { return instance; } static void HandleInterrupt(ExceptionStackFrame *frame);