mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
kern: skeleton enough types to init KCoreLocalRegion in main()
This commit is contained in:
parent
ad0d2faa6c
commit
981bb1f15d
24 changed files with 1066 additions and 33 deletions
|
@ -37,9 +37,13 @@
|
||||||
#include "mesosphere/kern_k_memory_layout.hpp"
|
#include "mesosphere/kern_k_memory_layout.hpp"
|
||||||
|
|
||||||
/* Core functionality. */
|
/* Core functionality. */
|
||||||
#include "mesosphere/kern_select_interrupts.hpp"
|
#include "mesosphere/kern_select_interrupt_manager.hpp"
|
||||||
|
#include "mesosphere/kern_k_spin_lock.hpp"
|
||||||
#include "mesosphere/kern_k_page_heap.hpp"
|
#include "mesosphere/kern_k_page_heap.hpp"
|
||||||
#include "mesosphere/kern_k_memory_manager.hpp"
|
#include "mesosphere/kern_k_memory_manager.hpp"
|
||||||
|
#include "mesosphere/kern_k_interrupt_task_manager.hpp"
|
||||||
|
#include "mesosphere/kern_k_core_local_region.hpp"
|
||||||
|
#include "mesosphere/kern_kernel.hpp"
|
||||||
|
|
||||||
/* Supervisor Calls. */
|
/* Supervisor Calls. */
|
||||||
#include "mesosphere/kern_svc.hpp"
|
#include "mesosphere/kern_svc.hpp"
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_select_cpu.hpp>
|
||||||
|
#include <mesosphere/kern_k_hardware_timer_base.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern::arm64 {
|
||||||
|
|
||||||
|
class KHardwareTimer : public KHardwareTimerBase {
|
||||||
|
public:
|
||||||
|
static constexpr s32 InterruptId = 30; /* Nintendo uses the non-secure timer interrupt. */
|
||||||
|
public:
|
||||||
|
constexpr KHardwareTimer() : KHardwareTimerBase() { /* ... */ }
|
||||||
|
|
||||||
|
virtual void DoTask() override;
|
||||||
|
|
||||||
|
/* TODO: Actually implement more of KHardwareTimer, */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include <mesosphere/kern_select_cpu.hpp>
|
||||||
|
#include <mesosphere/kern_k_typed_address.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern::arm64 {
|
||||||
|
|
||||||
|
struct GicDistributor {
|
||||||
|
u32 ctlr;
|
||||||
|
u32 typer;
|
||||||
|
u32 iidr;
|
||||||
|
u32 reserved_0x0c;
|
||||||
|
u32 statusr;
|
||||||
|
u32 reserved_0x14[3];
|
||||||
|
u32 impldef_0x20[8];
|
||||||
|
u32 setspi_nsr;
|
||||||
|
u32 reserved_0x44;
|
||||||
|
u32 clrspi_nsr;
|
||||||
|
u32 reserved_0x4c;
|
||||||
|
u32 setspi_sr;
|
||||||
|
u32 reserved_0x54;
|
||||||
|
u32 clrspi_sr;
|
||||||
|
u32 reserved_0x5c[9];
|
||||||
|
u32 igroupr[32];
|
||||||
|
u32 isenabler[32];
|
||||||
|
u32 icenabler[32];
|
||||||
|
u32 ispendr[32];
|
||||||
|
u32 icpendr[32];
|
||||||
|
u32 isactiver[32];
|
||||||
|
u32 icactiver[32];
|
||||||
|
u8 ipriorityr[1020];
|
||||||
|
u32 _0x7fc;
|
||||||
|
u8 itargetsr[1020];
|
||||||
|
u32 _0xbfc;
|
||||||
|
u32 icfgr[64];
|
||||||
|
u32 igrpmodr[32];
|
||||||
|
u32 _0xd80[32];
|
||||||
|
u32 nsacr[64];
|
||||||
|
u32 sgir;
|
||||||
|
u32 _0xf04[3];
|
||||||
|
u32 cpendsgir[4];
|
||||||
|
u32 spendsgir[4];
|
||||||
|
u32 reserved_0xf30[52];
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<GicDistributor>::value);
|
||||||
|
static_assert(sizeof(GicDistributor) == 0x1000);
|
||||||
|
|
||||||
|
struct GicController {
|
||||||
|
u32 ctlr;
|
||||||
|
u32 pmr;
|
||||||
|
u32 bpr;
|
||||||
|
u32 iar;
|
||||||
|
u32 eoir;
|
||||||
|
u32 rpr;
|
||||||
|
u32 hppir;
|
||||||
|
u32 abpr;
|
||||||
|
u32 aiar;
|
||||||
|
u32 aeoir;
|
||||||
|
u32 ahppir;
|
||||||
|
u32 statusr;
|
||||||
|
u32 reserved_30[4];
|
||||||
|
u32 impldef_40[36];
|
||||||
|
u32 apr[4];
|
||||||
|
u32 nsapr[4];
|
||||||
|
u32 reserved_f0[3];
|
||||||
|
u32 iidr;
|
||||||
|
u32 reserved_100[960];
|
||||||
|
u32 dir;
|
||||||
|
u32 _0x1004[1023];
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<GicController>::value);
|
||||||
|
static_assert(sizeof(GicController) == 0x2000);
|
||||||
|
|
||||||
|
struct KInterruptController {
|
||||||
|
NON_COPYABLE(KInterruptController);
|
||||||
|
NON_MOVEABLE(KInterruptController);
|
||||||
|
public:
|
||||||
|
static constexpr size_t NumLocalInterrupts = 32;
|
||||||
|
static constexpr size_t NumGlobalInterrupts = 988;
|
||||||
|
static constexpr size_t NumInterrupts = NumLocalInterrupts + NumGlobalInterrupts;
|
||||||
|
public:
|
||||||
|
struct LocalState {
|
||||||
|
u32 local_isenabler[NumLocalInterrupts / 32];
|
||||||
|
u32 local_ipriorityr[NumLocalInterrupts / 4];
|
||||||
|
u32 local_targetsr[NumLocalInterrupts / 4];
|
||||||
|
u32 local_icfgr[NumLocalInterrupts / 16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalState {
|
||||||
|
u32 global_isenabler[NumGlobalInterrupts / 32];
|
||||||
|
u32 global_ipriorityr[NumGlobalInterrupts / 4];
|
||||||
|
u32 global_targetsr[NumGlobalInterrupts / 4];
|
||||||
|
u32 global_icfgr[NumGlobalInterrupts / 16];
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static inline volatile GicDistributor *s_gicd;
|
||||||
|
static inline volatile GicController *s_gicc;
|
||||||
|
static inline u32 s_mask[cpu::NumCores];
|
||||||
|
private:
|
||||||
|
volatile GicDistributor *gicd;
|
||||||
|
volatile GicController *gicc;
|
||||||
|
public:
|
||||||
|
KInterruptController() { /* Don't initialize anything -- this will be taken care of by ::Initialize() */ }
|
||||||
|
|
||||||
|
/* TODO: Actually implement KInterruptController functionality. */
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include <mesosphere/kern_select_cpu.hpp>
|
||||||
|
#include <mesosphere/kern_k_spin_lock.hpp>
|
||||||
|
#include <mesosphere/kern_k_interrupt_task.hpp>
|
||||||
|
#include <mesosphere/kern_select_interrupt_controller.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern::arm64 {
|
||||||
|
|
||||||
|
class KInterruptManager {
|
||||||
|
NON_COPYABLE(KInterruptManager);
|
||||||
|
NON_MOVEABLE(KInterruptManager);
|
||||||
|
private:
|
||||||
|
struct KCoreLocalInterruptEntry {
|
||||||
|
KInterruptHandler *handler;
|
||||||
|
bool manually_cleared;
|
||||||
|
bool needs_clear;
|
||||||
|
u8 priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KGlobalInterruptEntry {
|
||||||
|
KInterruptHandler *handler;
|
||||||
|
bool manually_cleared;
|
||||||
|
bool needs_clear;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static inline KSpinLock s_lock;
|
||||||
|
static inline KGlobalInterruptEntry s_global_interrupts[KInterruptController::NumGlobalInterrupts];
|
||||||
|
static inline KInterruptController::GlobalState s_global_state;
|
||||||
|
static inline bool s_global_state_saved;
|
||||||
|
private:
|
||||||
|
KCoreLocalInterruptEntry core_local_interrupts[KInterruptController::NumLocalInterrupts];
|
||||||
|
KInterruptController interrupt_controller;
|
||||||
|
KInterruptController::LocalState local_state;
|
||||||
|
bool local_state_saved;
|
||||||
|
public:
|
||||||
|
KInterruptManager() : local_state_saved(false) { /* Leave things mostly uninitalized. We'll call ::Initialize() later. */ }
|
||||||
|
/* TODO: Actually implement KInterruptManager functionality. */
|
||||||
|
public:
|
||||||
|
static ALWAYS_INLINE u32 DisableInterrupts() {
|
||||||
|
u64 intr_state;
|
||||||
|
__asm__ __volatile__("mrs %[intr_state], daif" : [intr_state]"=r"(intr_state));
|
||||||
|
__asm__ __volatile__("msr daif, %[intr_state]" :: [intr_state]"r"(intr_state | 0x80));
|
||||||
|
return intr_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE u32 EnableInterrupts() {
|
||||||
|
u64 intr_state;
|
||||||
|
__asm__ __volatile__("mrs %[intr_state], daif" : [intr_state]"=r"(intr_state));
|
||||||
|
__asm__ __volatile__("msr daif, %[intr_state]" :: [intr_state]"r"(intr_state & 0x7F));
|
||||||
|
return intr_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void RestoreInterrupts(u32 intr_state) {
|
||||||
|
u64 cur_state;
|
||||||
|
__asm__ __volatile__("mrs %[cur_state], daif" : [cur_state]"=r"(cur_state));
|
||||||
|
__asm__ __volatile__("msr daif, %[intr_state]" :: [intr_state]"r"((cur_state & 0x7F) | (intr_state & 0x80)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE bool AreInterruptsEnabled() {
|
||||||
|
u64 intr_state;
|
||||||
|
__asm__ __volatile__("mrs %[intr_state], daif" : [intr_state]"=r"(intr_state));
|
||||||
|
return (intr_state & 0x80) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include <mesosphere/kern_select_cpu.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern::arm64 {
|
||||||
|
|
||||||
|
class KNotAlignedSpinLock {
|
||||||
|
private:
|
||||||
|
u32 packed_tickets;
|
||||||
|
public:
|
||||||
|
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
||||||
|
|
||||||
|
void Lock() {
|
||||||
|
u32 tmp0, tmp1;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" prfm pstl1keep, %[packed_tickets]\n"
|
||||||
|
"loop1:\n"
|
||||||
|
" ldaxr %w[tmp0], %[packed_tickets]\n"
|
||||||
|
" add %w[tmp0], %w[tmp0], #0x10000\n"
|
||||||
|
" stxr %w[tmp1], %w[tmp0], %[packed_tickets]\n"
|
||||||
|
" cbnz %w[tmp1], loop1\n"
|
||||||
|
" \n"
|
||||||
|
" and %w[tmp1], %w[tmp0], #0xFFFF\n"
|
||||||
|
" cmp %w[tmp1], %w[tmp0], lsr #16\n"
|
||||||
|
" b.eq done"
|
||||||
|
" sevl\n"
|
||||||
|
"loop2:\n"
|
||||||
|
" wfe\n"
|
||||||
|
" ldaxrh %w[tmp1], %[packed_tickets]\n"
|
||||||
|
" cmp %w[tmp1], %w[tmp0], lsr #16\n"
|
||||||
|
" b.ne loop2\n"
|
||||||
|
"done:\n"
|
||||||
|
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [packed_tickets]"+Q"(this->packed_tickets)
|
||||||
|
:
|
||||||
|
: "cc", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unlock() {
|
||||||
|
const u32 value = this->packed_tickets + 1;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" stlrh %w[value], %[packed_tickets]\n"
|
||||||
|
: [packed_tickets]"+Q"(this->packed_tickets)
|
||||||
|
: [value]"r"(value)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KNotAlignedSpinLock) == sizeof(u32));
|
||||||
|
|
||||||
|
class KAlignedSpinLock {
|
||||||
|
private:
|
||||||
|
alignas(cpu::DataCacheLineSize) u16 current_ticket;
|
||||||
|
alignas(cpu::DataCacheLineSize) u16 next_ticket;
|
||||||
|
public:
|
||||||
|
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
||||||
|
|
||||||
|
void Lock() {
|
||||||
|
u32 tmp0, tmp1, got_lock;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" prfm pstl1keep, %[next_ticket]\n"
|
||||||
|
"loop1:\n"
|
||||||
|
" ldaxrh %w[tmp0], %[next_ticket]\n"
|
||||||
|
" add %w[tmp1], %w[tmp0], #0x1\n"
|
||||||
|
" stxrh %w[got_lock], %w[tmp1], %[next_ticket]\n"
|
||||||
|
" cbnz %w[got_lock], loop1\n"
|
||||||
|
" \n"
|
||||||
|
" sevl\n"
|
||||||
|
"loop2:\n"
|
||||||
|
" wfe\n"
|
||||||
|
" ldaxrh %w[tmp1], %[current_ticket]\n"
|
||||||
|
" cmp %w[tmp1], %w[tmp0]\n"
|
||||||
|
" b.ne loop2\n"
|
||||||
|
: [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [got_lock]"=&r"(got_lock), [next_ticket]"+Q"(this->next_ticket)
|
||||||
|
: [current_ticket]"Q"(this->current_ticket)
|
||||||
|
: "cc", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unlock() {
|
||||||
|
const u32 value = this->current_ticket + 1;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" stlrh %w[value], %[current_ticket]\n"
|
||||||
|
: [current_ticket]"+Q"(this->current_ticket)
|
||||||
|
: [value]"r"(value)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KAlignedSpinLock) == 2 * cpu::DataCacheLineSize);
|
||||||
|
|
||||||
|
using KSpinLock = KAlignedSpinLock;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include <mesosphere/kern_select_cpu.hpp>
|
||||||
|
#include <mesosphere/kern_k_current_context.hpp>
|
||||||
|
#include <mesosphere/kern_k_scheduler.hpp>
|
||||||
|
#include <mesosphere/kern_k_interrupt_task_manager.hpp>
|
||||||
|
#include <mesosphere/kern_select_interrupt_manager.hpp>
|
||||||
|
#include <mesosphere/kern_select_hardware_timer.hpp>
|
||||||
|
#include <mesosphere/kern_k_memory_manager.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
struct KCoreLocalContext {
|
||||||
|
KCurrentContext current;
|
||||||
|
KScheduler scheduler;
|
||||||
|
KInterruptTaskManager interrupt_task_manager;
|
||||||
|
KInterruptManager interrupt_manager;
|
||||||
|
KHardwareTimer hardware_timer;
|
||||||
|
/* Everything after this point is for debugging. */
|
||||||
|
/* Retail kernel doesn't even consistently update these fields. */
|
||||||
|
u64 num_sw_interrupts;
|
||||||
|
u64 num_hw_interrupts;
|
||||||
|
std::atomic<u64> num_svc;
|
||||||
|
u64 num_process_switches;
|
||||||
|
u64 num_thread_switches;
|
||||||
|
u64 num_fpu_switches;
|
||||||
|
u64 num_scheduler_updates;
|
||||||
|
u64 num_invoked_scheduler_updates;
|
||||||
|
std::atomic<u64> num_specific_svc[0x80];
|
||||||
|
u32 perf_counters[6];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KCoreLocalContext) < KMemoryManager::PageSize);
|
||||||
|
|
||||||
|
struct KCoreLocalPage {
|
||||||
|
KCoreLocalContext context;
|
||||||
|
u8 padding[KMemoryManager::PageSize - sizeof(KCoreLocalContext)];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KCoreLocalPage) == KMemoryManager::PageSize);
|
||||||
|
|
||||||
|
struct KCoreLocalRegion {
|
||||||
|
KCoreLocalPage current;
|
||||||
|
KCoreLocalPage absolute[cpu::NumCores];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KCoreLocalRegion) == KMemoryManager::PageSize * (1 + cpu::NumCores));
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_select_cpu.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KThread;
|
||||||
|
class KProcess;
|
||||||
|
class KScheduler;
|
||||||
|
class KInterruptTaskManager;
|
||||||
|
|
||||||
|
struct KCurrentContext {
|
||||||
|
KThread *current_thread;
|
||||||
|
KProcess *current_process;
|
||||||
|
KScheduler *scheduler;
|
||||||
|
KInterruptTaskManager *interrupt_task_manager;
|
||||||
|
s32 core_id;
|
||||||
|
void *exception_stack_bottom;
|
||||||
|
};
|
||||||
|
static_assert(std::is_pod<KCurrentContext>::value);
|
||||||
|
static_assert(sizeof(KCurrentContext) <= cpu::DataCacheLineSize);
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
ALWAYS_INLINE KCurrentContext &GetCurrentContext() {
|
||||||
|
return *reinterpret_cast<KCurrentContext *>(cpu::GetCoreLocalRegionAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KThread *GetCurrentThreadPointer() {
|
||||||
|
return impl::GetCurrentContext().current_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KThread &GetCurrentThread() {
|
||||||
|
return *GetCurrentThreadPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KProcess *GetCurrentProcessPointer() {
|
||||||
|
return impl::GetCurrentContext().current_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KProcess &GetCurrentProcess() {
|
||||||
|
return *GetCurrentProcessPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KScheduler *GetCurrentSchedulerPointer() {
|
||||||
|
return impl::GetCurrentContext().scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KScheduler &GetCurrentScheduler() {
|
||||||
|
return *GetCurrentSchedulerPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KInterruptTaskManager *GetCurrentInterruptTaskManagerPointer() {
|
||||||
|
return impl::GetCurrentContext().interrupt_task_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KInterruptTaskManager &GetCurrentInterruptTaskManager() {
|
||||||
|
return *GetCurrentInterruptTaskManagerPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE s32 GetCurrentCoreId() {
|
||||||
|
return impl::GetCurrentContext().core_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetCurrentThread(KThread *new_thread) {
|
||||||
|
impl::GetCurrentContext().current_thread = new_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetCurrentProcess(KProcess *new_process) {
|
||||||
|
impl::GetCurrentContext().current_process = new_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_k_spin_lock.hpp>
|
||||||
|
#include <mesosphere/kern_k_interrupt_task.hpp>
|
||||||
|
#include <mesosphere/kern_k_timer_task.hpp>
|
||||||
|
#include <mesosphere/kern_select_interrupt_manager.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KHardwareTimerBase : public KInterruptTask {
|
||||||
|
private:
|
||||||
|
using TimerTaskTree = util::IntrusiveRedBlackTreeBaseTraits<KTimerTask>::TreeType<KTimerTask>;
|
||||||
|
private:
|
||||||
|
KSpinLock lock;
|
||||||
|
TimerTaskTree task_tree;
|
||||||
|
KTimerTask *next_task;
|
||||||
|
public:
|
||||||
|
constexpr KHardwareTimerBase() : lock(), task_tree(), next_task(nullptr) { /* ... */ }
|
||||||
|
|
||||||
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override { return this; }
|
||||||
|
protected:
|
||||||
|
KSpinLock &GetLock() { return this->lock; }
|
||||||
|
|
||||||
|
/* TODO: Actually implement more of KHardwareTimerBase */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KInterruptTask;
|
||||||
|
|
||||||
|
class KInterruptHandler {
|
||||||
|
public:
|
||||||
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KInterruptTask : public KInterruptHandler {
|
||||||
|
private:
|
||||||
|
KInterruptTask *next_task;
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE KInterruptTask() : next_task(nullptr) { /* ... */ }
|
||||||
|
|
||||||
|
ALWAYS_INLINE KInterruptTask *GetNextTask() const {
|
||||||
|
return this->next_task;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetNextTask(KInterruptTask *t) {
|
||||||
|
this->next_task = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DoTask() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_k_interrupt_task.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KThread;
|
||||||
|
|
||||||
|
class KInterruptTaskManager {
|
||||||
|
private:
|
||||||
|
class TaskQueue {
|
||||||
|
private:
|
||||||
|
KInterruptTask *head;
|
||||||
|
KInterruptTask *tail;
|
||||||
|
public:
|
||||||
|
constexpr TaskQueue() : head(nullptr), tail(nullptr) { /* ... */ }
|
||||||
|
|
||||||
|
ALWAYS_INLINE KInterruptTask *GetHead() { return this->head; }
|
||||||
|
ALWAYS_INLINE bool IsEmpty() const { return this->head == nullptr; }
|
||||||
|
ALWAYS_INLINE void Clear() { this->head = nullptr; this->tail = nullptr; }
|
||||||
|
|
||||||
|
void Enqueue(KInterruptTask *task);
|
||||||
|
void Dequeue();
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
TaskQueue task_queue;
|
||||||
|
KThread *thread;
|
||||||
|
public:
|
||||||
|
/* TODO: Actually implement KInterruptTaskManager. This is a placeholder. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -402,6 +402,18 @@ namespace ams::kern {
|
||||||
return GetVirtualMemoryBlockTree().FindFirstBlockByTypeAttr(KMemoryRegionType_KernelMiscMainStack, static_cast<u32>(core_id))->GetEndAddress();
|
return GetVirtualMemoryBlockTree().FindFirstBlockByTypeAttr(KMemoryRegionType_KernelMiscMainStack, static_cast<u32>(core_id))->GetEndAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NOINLINE KVirtualAddress GetIdleStackTopAddress(s32 core_id) {
|
||||||
|
return GetVirtualMemoryBlockTree().FindFirstBlockByTypeAttr(KMemoryRegionType_KernelMiscIdleStack, static_cast<u32>(core_id))->GetEndAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
static NOINLINE KVirtualAddress GetExceptionStackBottomAddress(s32 core_id) {
|
||||||
|
return GetVirtualMemoryBlockTree().FindFirstBlockByTypeAttr(KMemoryRegionType_KernelMiscExceptionStack, static_cast<u32>(core_id))->GetAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() {
|
||||||
|
return GetVirtualMemoryBlockTree().FindFirstBlockByTypeAttr(KMemoryRegionType_CoreLocal)->GetAddress();
|
||||||
|
}
|
||||||
|
|
||||||
static void InitializeLinearMemoryBlockTrees(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start);
|
static void InitializeLinearMemoryBlockTrees(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_k_thread.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KScheduler {
|
||||||
|
NON_COPYABLE(KScheduler);
|
||||||
|
NON_MOVEABLE(KScheduler);
|
||||||
|
public:
|
||||||
|
struct SchedulingState {
|
||||||
|
std::atomic<bool> needs_scheduling;
|
||||||
|
bool interrupt_task_thread_runnable;
|
||||||
|
bool should_count_idle;
|
||||||
|
u64 idle_count;
|
||||||
|
KThread *highest_priority_thread;
|
||||||
|
void *idle_thread_stack;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
SchedulingState state;
|
||||||
|
bool is_active;
|
||||||
|
s32 core_id;
|
||||||
|
KThread *prev_thread;
|
||||||
|
u64 last_context_switch_time;
|
||||||
|
KThread *idle_thread;
|
||||||
|
public:
|
||||||
|
KScheduler();
|
||||||
|
/* TODO: Actually implement KScheduler. This is a placeholder. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include "kern_panic.hpp"
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||||
|
|
||||||
|
#include <mesosphere/arch/arm64/kern_k_spin_lock.hpp>
|
||||||
|
namespace ams::kern {
|
||||||
|
using ams::kern::arm64::KAlignedSpinLock;
|
||||||
|
using ams::kern::arm64::KNotAlignedSpinLock;
|
||||||
|
using ams::kern::arm64::KSpinLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unknown architecture for KInterruptManager"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KScopedSpinLock {
|
||||||
|
private:
|
||||||
|
KSpinLock *lock_ptr;
|
||||||
|
public:
|
||||||
|
explicit ALWAYS_INLINE KScopedSpinLock(KSpinLock *l) : lock_ptr(l) {
|
||||||
|
this->lock_ptr->Lock();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE ~KScopedSpinLock() {
|
||||||
|
this->lock_ptr->Unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class KScopedAlignedSpinLock {
|
||||||
|
private:
|
||||||
|
KAlignedSpinLock *lock_ptr;
|
||||||
|
public:
|
||||||
|
explicit ALWAYS_INLINE KScopedAlignedSpinLock(KAlignedSpinLock *l) : lock_ptr(l) {
|
||||||
|
this->lock_ptr->Lock();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE ~KScopedAlignedSpinLock() {
|
||||||
|
this->lock_ptr->Unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class KScopedNotAlignedSpinLock {
|
||||||
|
private:
|
||||||
|
KNotAlignedSpinLock *lock_ptr;
|
||||||
|
public:
|
||||||
|
explicit ALWAYS_INLINE KScopedNotAlignedSpinLock(KNotAlignedSpinLock *l) : lock_ptr(l) {
|
||||||
|
this->lock_ptr->Lock();
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE ~KScopedNotAlignedSpinLock() {
|
||||||
|
this->lock_ptr->Unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
25
libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp
Normal file
25
libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
|
||||||
|
class KThread {
|
||||||
|
/* TODO: This should be a KAutoObject, and this is a placeholder definition. */
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class KTimerTask : public util::IntrusiveRedBlackTreeBaseNode<KTimerTask> {
|
||||||
|
private:
|
||||||
|
s64 time;
|
||||||
|
public:
|
||||||
|
static constexpr ALWAYS_INLINE int Compare(const KTimerTask &lhs, const KTimerTask &rhs) {
|
||||||
|
if (lhs.GetTime() < rhs.GetTime()) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
constexpr ALWAYS_INLINE KTimerTask() : time(0) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE void SetTime(s64 t) {
|
||||||
|
this->time = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE s64 GetTime() const {
|
||||||
|
return this->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnTimer() = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
40
libraries/libmesosphere/include/mesosphere/kern_kernel.hpp
Normal file
40
libraries/libmesosphere/include/mesosphere/kern_kernel.hpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <mesosphere/kern_k_typed_address.hpp>
|
||||||
|
#include <mesosphere/kern_k_memory_layout.hpp>
|
||||||
|
#include <mesosphere/kern_k_memory_manager.hpp>
|
||||||
|
#include <mesosphere/kern_k_core_local_region.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
class Kernel {
|
||||||
|
public:
|
||||||
|
enum class State : u8 {
|
||||||
|
Invalid = 0,
|
||||||
|
Initializing = 1,
|
||||||
|
Initialized = 2,
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static inline State s_state = State::Invalid;
|
||||||
|
public:
|
||||||
|
static void Initialize(s32 core_id);
|
||||||
|
|
||||||
|
static ALWAYS_INLINE State GetState() { return s_state; }
|
||||||
|
static ALWAYS_INLINE void SetState(State state) { s_state = state; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include "kern_panic.hpp"
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||||
|
|
||||||
|
#include <mesosphere/arch/arm64/kern_k_hardware_timer.hpp>
|
||||||
|
namespace ams::kern {
|
||||||
|
using ams::kern::arm64::KHardwareTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unknown architecture for KHardwareTimer"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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 <vapours.hpp>
|
||||||
|
#include "kern_panic.hpp"
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||||
|
|
||||||
|
#include <mesosphere/arch/arm64/kern_k_interrupt_controller.hpp>
|
||||||
|
namespace ams::kern {
|
||||||
|
using ams::kern::arm64::KInterruptController;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unknown architecture for KInterruptController"
|
||||||
|
|
||||||
|
#endif
|
|
@ -17,26 +17,42 @@
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
#include "kern_panic.hpp"
|
#include "kern_panic.hpp"
|
||||||
|
|
||||||
namespace ams::kern {
|
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||||
|
|
||||||
/* TODO: Actually select between architecture-specific interrupt code. */
|
#include <mesosphere/arch/arm64/kern_k_interrupt_manager.hpp>
|
||||||
|
namespace ams::kern {
|
||||||
|
using ams::kern::arm64::KInterruptManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unknown architecture for KInterruptManager"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
|
||||||
/* Enable or disable interrupts for the lifetime of an object. */
|
/* Enable or disable interrupts for the lifetime of an object. */
|
||||||
class KScopedInterruptDisable {
|
class KScopedInterruptDisable {
|
||||||
NON_COPYABLE(KScopedInterruptDisable);
|
NON_COPYABLE(KScopedInterruptDisable);
|
||||||
NON_MOVEABLE(KScopedInterruptDisable);
|
NON_MOVEABLE(KScopedInterruptDisable);
|
||||||
|
private:
|
||||||
|
u32 prev_intr_state;
|
||||||
public:
|
public:
|
||||||
KScopedInterruptDisable();
|
ALWAYS_INLINE KScopedInterruptDisable() : prev_intr_state(KInterruptManager::DisableInterrupts()) { /* ... */ }
|
||||||
~KScopedInterruptDisable();
|
~KScopedInterruptDisable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class KScopedInterruptEnable {
|
class KScopedInterruptEnable {
|
||||||
NON_COPYABLE(KScopedInterruptEnable);
|
NON_COPYABLE(KScopedInterruptEnable);
|
||||||
NON_MOVEABLE(KScopedInterruptEnable);
|
NON_MOVEABLE(KScopedInterruptEnable);
|
||||||
|
private:
|
||||||
|
u32 prev_intr_state;
|
||||||
public:
|
public:
|
||||||
KScopedInterruptEnable();
|
ALWAYS_INLINE KScopedInterruptEnable() : prev_intr_state(KInterruptManager::EnableInterrupts()) { /* ... */ }
|
||||||
~KScopedInterruptEnable();
|
~KScopedInterruptEnable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern::arm64 {
|
||||||
|
|
||||||
|
void KHardwareTimer::DoTask() {
|
||||||
|
/* TODO: Actually implement this. */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,20 +17,24 @@
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
inline KScopedInterruptDisable::KScopedInterruptDisable() {
|
void KInterruptTaskManager::TaskQueue::Enqueue(KInterruptTask *task) {
|
||||||
/* Intentionally do nothing, KernelLdr doesn't have interrupts set up. */
|
/* Insert the task into the queue. */
|
||||||
|
if (this->tail != nullptr) {
|
||||||
|
this->tail->SetNextTask(task);
|
||||||
|
} else {
|
||||||
|
this->head = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->tail = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline KScopedInterruptDisable::~KScopedInterruptDisable() {
|
void KInterruptTaskManager::TaskQueue::Dequeue() {
|
||||||
/* Intentionally do nothing, KernelLdr doesn't have interrupts set up. */
|
if (this->head == this->tail) {
|
||||||
}
|
this->head = nullptr;
|
||||||
|
this->tail = nullptr;
|
||||||
inline KScopedInterruptEnable::KScopedInterruptEnable() {
|
} else {
|
||||||
/* Intentionally do nothing, KernelLdr doesn't have interrupts set up. */
|
this->head = this->head->GetNextTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline KScopedInterruptEnable::~KScopedInterruptEnable() {
|
|
||||||
/* Intentionally do nothing, KernelLdr doesn't have interrupts set up. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,20 +17,15 @@
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
WEAK_SYMBOL KScopedInterruptDisable::KScopedInterruptDisable() {
|
KScheduler::KScheduler()
|
||||||
/* TODO: Disable interrupts. */
|
: is_active(false), core_id(0), prev_thread(nullptr), last_context_switch_time(0), idle_thread(nullptr)
|
||||||
}
|
{
|
||||||
|
this->state.needs_scheduling = true;
|
||||||
WEAK_SYMBOL KScopedInterruptDisable::~KScopedInterruptDisable() {
|
this->state.interrupt_task_thread_runnable = false;
|
||||||
/* TODO: un-disable interrupts. */
|
this->state.should_count_idle = false;
|
||||||
}
|
this->state.idle_count = 0;
|
||||||
|
this->state.idle_thread_stack = nullptr;
|
||||||
WEAK_SYMBOL KScopedInterruptEnable::KScopedInterruptEnable() {
|
this->state.highest_priority_thread = nullptr;
|
||||||
/* TODO: Enable interrupts. */
|
|
||||||
}
|
|
||||||
|
|
||||||
WEAK_SYMBOL KScopedInterruptEnable::~KScopedInterruptEnable() {
|
|
||||||
/* TODO: un-enable interrupts. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
49
libraries/libmesosphere/source/kern_kernel.cpp
Normal file
49
libraries/libmesosphere/source/kern_kernel.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-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/>.
|
||||||
|
*/
|
||||||
|
#include <mesosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::kern {
|
||||||
|
|
||||||
|
NOINLINE void Kernel::Initialize(s32 core_id) {
|
||||||
|
/* Construct the core local region object in place. */
|
||||||
|
KCoreLocalContext *clc = GetPointer<KCoreLocalContext>(KMemoryLayout::GetCoreLocalRegionAddress());
|
||||||
|
new (clc) KCoreLocalContext;
|
||||||
|
|
||||||
|
/* Set the core local region address into the global register. */
|
||||||
|
cpu::SetCoreLocalRegionAddress(reinterpret_cast<uintptr_t>(clc));
|
||||||
|
|
||||||
|
/* Initialize current context. */
|
||||||
|
clc->current.current_thread = nullptr;
|
||||||
|
clc->current.current_process = nullptr;
|
||||||
|
clc->current.scheduler = std::addressof(clc->scheduler);
|
||||||
|
clc->current.interrupt_task_manager = std::addressof(clc->interrupt_task_manager);
|
||||||
|
clc->current.core_id = core_id;
|
||||||
|
clc->current.exception_stack_bottom = GetVoidPointer(KMemoryLayout::GetExceptionStackBottomAddress(core_id));
|
||||||
|
|
||||||
|
/* Clear debugging counters. */
|
||||||
|
clc->num_sw_interrupts = 0;
|
||||||
|
clc->num_hw_interrupts = 0;
|
||||||
|
clc->num_svc = 0;
|
||||||
|
clc->num_process_switches = 0;
|
||||||
|
clc->num_thread_switches = 0;
|
||||||
|
clc->num_fpu_switches = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < util::size(clc->perf_counters); i++) {
|
||||||
|
clc->perf_counters[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,7 +18,14 @@
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
NORETURN void HorizonKernelMain(s32 core_id) {
|
NORETURN void HorizonKernelMain(s32 core_id) {
|
||||||
|
/* Setup the Core Local Region, and note that we're initializing. */
|
||||||
|
Kernel::Initialize(core_id);
|
||||||
|
Kernel::SetState(Kernel::State::Initializing);
|
||||||
|
|
||||||
|
/* Ensure that all cores get to this point before proceeding. */
|
||||||
cpu::SynchronizeAllCores();
|
cpu::SynchronizeAllCores();
|
||||||
|
|
||||||
|
/* TODO: Implement more of Main() */
|
||||||
while (true) { /* ... */ }
|
while (true) { /* ... */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue