kernel: unlayer CPU interrupt handling

This commit is contained in:
Liam
2022-07-07 20:06:46 -04:00
parent 591d1f1b09
commit 6523854dd6
13 changed files with 64 additions and 152 deletions

View File

@ -17,7 +17,6 @@
#include "common/thread.h"
#include "common/thread_worker.h"
#include "core/arm/arm_interface.h"
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
#include "core/core_timing.h"
@ -82,7 +81,7 @@ struct KernelCore::Impl {
void InitializeCores() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
cores[core_id].Initialize((*current_process).Is64BitProcess());
cores[core_id]->Initialize((*current_process).Is64BitProcess());
system.Memory().SetCurrentPageTable(*current_process, core_id);
}
}
@ -100,7 +99,9 @@ struct KernelCore::Impl {
next_user_process_id = KProcess::ProcessIDMin;
next_thread_id = 1;
cores.clear();
for (auto& core : cores) {
core = nullptr;
}
global_handle_table->Finalize();
global_handle_table.reset();
@ -199,7 +200,7 @@ struct KernelCore::Impl {
const s32 core{static_cast<s32>(i)};
schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel());
cores.emplace_back(i, system, *schedulers[i], interrupts);
cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]);
auto* main_thread{Kernel::KThread::Create(system.Kernel())};
main_thread->SetName(fmt::format("MainThread:{}", core));
@ -761,7 +762,7 @@ struct KernelCore::Impl {
std::unordered_set<KAutoObject*> registered_in_use_objects;
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
std::vector<Kernel::PhysicalCore> cores;
std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
@ -785,7 +786,6 @@ struct KernelCore::Impl {
Common::ThreadWorker service_threads_manager;
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
bool is_multicore{};
@ -874,11 +874,11 @@ const Kernel::KScheduler& KernelCore::Scheduler(std::size_t id) const {
}
Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
return impl->cores[id];
return *impl->cores[id];
}
const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
return impl->cores[id];
return *impl->cores[id];
}
size_t KernelCore::CurrentPhysicalCoreIndex() const {
@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const {
}
Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
return impl->cores[CurrentPhysicalCoreIndex()];
return *impl->cores[CurrentPhysicalCoreIndex()];
}
const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
return impl->cores[CurrentPhysicalCoreIndex()];
return *impl->cores[CurrentPhysicalCoreIndex()];
}
Kernel::KScheduler* KernelCore::CurrentScheduler() {
@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
return impl->schedulers[core_id].get();
}
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() {
return impl->interrupts;
}
const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
const {
return impl->interrupts;
}
Kernel::TimeManager& KernelCore::TimeManager() {
return impl->time_manager;
}
@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
return *impl->global_object_list_container;
}
void KernelCore::InterruptAllPhysicalCores() {
for (auto& physical_core : impl->cores) {
physical_core.Interrupt();
}
}
void KernelCore::InvalidateAllInstructionCaches() {
for (auto& physical_core : impl->cores) {
physical_core.ArmInterface().ClearInstructionCache();
physical_core->ArmInterface().ClearInstructionCache();
}
}
void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
for (auto& physical_core : impl->cores) {
if (!physical_core.IsInitialized()) {
if (!physical_core->IsInitialized()) {
continue;
}
physical_core.ArmInterface().InvalidateCacheRange(addr, size);
physical_core->ArmInterface().InvalidateCacheRange(addr, size);
}
}

View File

@ -9,14 +9,12 @@
#include <string>
#include <unordered_map>
#include <vector>
#include "core/arm/cpu_interrupt_handler.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/svc_common.h"
namespace Core {
class CPUInterruptHandler;
class ExclusiveMonitor;
class System;
} // namespace Core
@ -183,12 +181,6 @@ public:
const KAutoObjectWithListContainer& ObjectListContainer() const;
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts();
const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;
void InterruptAllPhysicalCores();
void InvalidateAllInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/core.h"
@ -11,16 +10,14 @@
namespace Kernel {
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_,
Core::CPUInterrupts& interrupts_)
: core_index{core_index_}, system{system_}, scheduler{scheduler_},
interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} {
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_)
: core_index{core_index_}, system{system_}, scheduler{scheduler_} {
#ifdef ARCHITECTURE_x86_64
// TODO(bunnei): Initialization relies on a core being available. We may later replace this with
// a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
auto& kernel = system.Kernel();
arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
#else
#error Platform not supported yet.
#endif
@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
if (!is_64_bit) {
// We already initialized a 64-bit core, replace with a 32-bit one.
arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
}
#else
#error Platform not supported yet.
@ -47,24 +44,26 @@ void PhysicalCore::Run() {
}
void PhysicalCore::Idle() {
interrupts[core_index].AwaitInterrupt();
std::unique_lock lk{guard};
on_interrupt.wait(lk, [this] { return is_interrupted; });
}
bool PhysicalCore::IsInterrupted() const {
return interrupts[core_index].IsInterrupted();
return is_interrupted;
}
void PhysicalCore::Interrupt() {
guard->lock();
interrupts[core_index].SetInterrupt(true);
std::unique_lock lk{guard};
is_interrupted = true;
arm_interface->SignalInterrupt();
guard->unlock();
on_interrupt.notify_all();
}
void PhysicalCore::ClearInterrupt() {
guard->lock();
interrupts[core_index].SetInterrupt(false);
guard->unlock();
std::unique_lock lk{guard};
is_interrupted = false;
arm_interface->ClearInterrupt();
on_interrupt.notify_all();
}
} // namespace Kernel

View File

@ -14,7 +14,6 @@ class KScheduler;
} // namespace Kernel
namespace Core {
class CPUInterruptHandler;
class ExclusiveMonitor;
class System;
} // namespace Core
@ -23,15 +22,11 @@ namespace Kernel {
class PhysicalCore {
public:
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_,
Core::CPUInterrupts& interrupts_);
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
~PhysicalCore();
PhysicalCore(const PhysicalCore&) = delete;
PhysicalCore& operator=(const PhysicalCore&) = delete;
PhysicalCore(PhysicalCore&&) = default;
PhysicalCore& operator=(PhysicalCore&&) = delete;
YUZU_NON_COPYABLE(PhysicalCore);
YUZU_NON_MOVEABLE(PhysicalCore);
/// Initialize the core for the specified parameters.
void Initialize(bool is_64_bit);
@ -86,9 +81,11 @@ private:
const std::size_t core_index;
Core::System& system;
Kernel::KScheduler& scheduler;
Core::CPUInterrupts& interrupts;
std::unique_ptr<std::mutex> guard;
std::mutex guard;
std::condition_variable on_interrupt;
std::unique_ptr<Core::ARM_Interface> arm_interface;
bool is_interrupted;
};
} // namespace Kernel