mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 15:49:48 -04:00
kern: switch->nx, implement sleep manager init
This commit is contained in:
parent
20b5268e90
commit
2c496e94d5
31 changed files with 378 additions and 59 deletions
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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>
|
||||
#include "kern_k_sleep_manager.hpp"
|
||||
#include "kern_secure_monitor.hpp"
|
||||
|
||||
namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Struct representing registers saved on wake/sleep. */
|
||||
class SavedSystemRegisters {
|
||||
private:
|
||||
u64 ttbr0_el1;
|
||||
u64 tcr_el1;
|
||||
u64 elr_el1;
|
||||
u64 sp_el0;
|
||||
u64 spsr_el1;
|
||||
u64 daif;
|
||||
u64 cpacr_el1;
|
||||
u64 vbar_el1;
|
||||
u64 csselr_el1;
|
||||
u64 cntp_ctl_el0;
|
||||
u64 cntp_cval_el0;
|
||||
u64 cntkctl_el1;
|
||||
u64 tpidr_el0;
|
||||
u64 tpidrro_el0;
|
||||
u64 mdscr_el1;
|
||||
u64 contextidr_el1;
|
||||
u64 dbgwcrN_el1[16];
|
||||
u64 dbgwvrN_el1[16];
|
||||
u64 dbgbcrN_el1[16];
|
||||
u64 dbgbvrN_el1[16];
|
||||
u64 pmccfiltr_el0;
|
||||
u64 pmccntr_el0;
|
||||
u64 pmcntenset_el0;
|
||||
u64 pmcr_el0;
|
||||
u64 pmevcntrN_el0[31];
|
||||
u64 pmevtyperN_el0[31];
|
||||
u64 pmcntenset_el1;
|
||||
u64 pmovsset_el0;
|
||||
u64 pmselr_el0;
|
||||
u64 pmuserenr_el0;
|
||||
public:
|
||||
void Save();
|
||||
void Restore() const;
|
||||
};
|
||||
|
||||
constexpr s32 SleepManagerThreadPriority = 2;
|
||||
|
||||
/* Globals for sleep/wake. */
|
||||
u64 g_sleep_target_cores;
|
||||
KLightLock g_request_lock;
|
||||
KLightLock g_cv_lock;
|
||||
KLightConditionVariable g_cv;
|
||||
KPhysicalAddress g_sleep_buffer_phys_addrs[cpu::NumCores];
|
||||
alignas(16) u64 g_sleep_buffers[cpu::NumCores][1_KB / sizeof(u64)];
|
||||
SavedSystemRegisters g_sleep_system_registers[cpu::NumCores] = {};
|
||||
|
||||
}
|
||||
|
||||
void KSleepManager::Initialize() {
|
||||
/* Create a sleep manager thread for each core. */
|
||||
for (size_t core_id = 0; core_id < cpu::NumCores; core_id++) {
|
||||
/* Reserve a thread from the system limit. */
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1));
|
||||
|
||||
/* Create a new thread. */
|
||||
KThread *new_thread = KThread::Create();
|
||||
MESOSPHERE_ABORT_UNLESS(new_thread != nullptr);
|
||||
|
||||
/* Launch the new thread. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeKernelThread(new_thread, KSleepManager::ProcessRequests, reinterpret_cast<uintptr_t>(g_sleep_buffers[core_id]), SleepManagerThreadPriority, static_cast<s32>(core_id)));
|
||||
|
||||
/* Register the new thread. */
|
||||
KThread::Register(new_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
new_thread->Run();
|
||||
}
|
||||
}
|
||||
|
||||
void KSleepManager::SleepSystem() {
|
||||
/* Ensure device mappings are not modified during sleep. */
|
||||
MESOSPHERE_TODO("KDevicePageTable::Lock();");
|
||||
ON_SCOPE_EXIT { MESOSPHERE_TODO("KDevicePageTable::Unlock();"); };
|
||||
|
||||
/* Request that the system sleep. */
|
||||
{
|
||||
KScopedLightLock lk(g_request_lock);
|
||||
|
||||
/* Signal the manager to sleep on all cores. */
|
||||
{
|
||||
KScopedLightLock lk(g_cv_lock);
|
||||
MESOSPHERE_ABORT_UNLESS(g_sleep_target_cores == 0);
|
||||
|
||||
g_sleep_target_cores = (1ul << (cpu::NumCores - 1));
|
||||
g_cv.Broadcast();
|
||||
|
||||
while (g_sleep_target_cores != 0) {
|
||||
g_cv.Wait(std::addressof(g_cv_lock));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KSleepManager::ProcessRequests(uintptr_t buffer) {
|
||||
const s32 core_id = GetCurrentCoreId();
|
||||
KPhysicalAddress resume_entry_phys_addr = Null<KPhysicalAddress>;
|
||||
|
||||
/* Get the physical addresses we'll need. */
|
||||
{
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(g_sleep_buffer_phys_addrs[core_id]), KProcessAddress(buffer)));
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetKernelPageTable().GetPhysicalAddress(std::addressof(resume_entry_phys_addr), KProcessAddress(&::ams::kern::board::nintendo::nx::KSleepManager::ResumeEntry)));
|
||||
|
||||
}
|
||||
const KPhysicalAddress sleep_buffer_phys_addr = g_sleep_buffer_phys_addrs[core_id];
|
||||
const u64 target_core_mask = (1ul << core_id);
|
||||
|
||||
/* Loop, processing sleep when requested. */
|
||||
while (true) {
|
||||
/* Wait for a request. */
|
||||
{
|
||||
KScopedLightLock lk(g_cv_lock);
|
||||
while (!(g_sleep_target_cores & target_core_mask)) {
|
||||
g_cv.Wait(std::addressof(g_cv_lock));
|
||||
}
|
||||
}
|
||||
|
||||
MESOSPHERE_TODO("Implement Sleep/Wake");
|
||||
(void)(g_sleep_system_registers[core_id]);
|
||||
(void)(sleep_buffer_phys_addr);
|
||||
|
||||
/* Signal request completed. */
|
||||
{
|
||||
KScopedLightLock lk(g_cv_lock);
|
||||
g_sleep_target_cores &= ~target_core_mask;
|
||||
if (g_sleep_target_cores == 0) {
|
||||
g_cv.Broadcast();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.hpp>
|
||||
|
||||
namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
class KSleepManager {
|
||||
private:
|
||||
static void CpuSleepHandler(uintptr_t arg, uintptr_t entry);
|
||||
static void ResumeEntry(uintptr_t arg);
|
||||
|
||||
static void ProcessRequests(uintptr_t buffer);
|
||||
public:
|
||||
static void Initialize();
|
||||
static void SleepSystem();
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* ams::kern::board::nintendo::nx::KSleepManager::ResumeEntry(uintptr_t arg) */
|
||||
.section .text._ZN3ams4kern5board8nintendo2nx13KSleepManager11ResumeEntryEm, "ax", %progbits
|
||||
.global _ZN3ams4kern5board8nintendo2nx13KSleepManager11ResumeEntryEm
|
||||
.type _ZN3ams4kern5board8nintendo2nx13KSleepManager11ResumeEntryEm, %function
|
||||
_ZN3ams4kern5board8nintendo2nx13KSleepManager11ResumeEntryEm:
|
||||
/* TODO: Implement a real function here. */
|
||||
brk 1000
|
|
@ -15,14 +15,20 @@
|
|||
*/
|
||||
#include <mesosphere.hpp>
|
||||
#include "kern_secure_monitor.hpp"
|
||||
#include "kern_k_sleep_manager.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Global variables for panic. */
|
||||
bool g_call_smc_on_panic;
|
||||
|
||||
/* Global variables for secure memory. */
|
||||
constexpr size_t SecureAppletReservedMemorySize = 4_MB;
|
||||
KVirtualAddress g_secure_applet_memory_address;
|
||||
|
||||
|
||||
/* Global variables for randomness. */
|
||||
/* Nintendo uses std::mt19937_t for randomness. */
|
||||
/* To save space (and because mt19337_t isn't secure anyway), */
|
||||
|
@ -195,7 +201,7 @@ namespace ams::kern {
|
|||
}
|
||||
|
||||
/* System Initialization. */
|
||||
void KSystemControl::Initialize() {
|
||||
void KSystemControl::InitializePhase1() {
|
||||
/* Set IsDebugMode. */
|
||||
{
|
||||
KTargetSystem::SetIsDebugMode(GetConfigBool(smc::ConfigItem::IsDebugMode));
|
||||
|
@ -250,6 +256,21 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
void KSystemControl::InitializePhase2() {
|
||||
/* Initialize the sleep manager. */
|
||||
KSleepManager::Initialize();
|
||||
|
||||
/* Reserve secure applet memory. */
|
||||
{
|
||||
MESOSPHERE_ABORT_UNLESS(g_secure_applet_memory_address == Null<KVirtualAddress>);
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, SecureAppletReservedMemorySize));
|
||||
|
||||
constexpr auto SecureAppletAllocateOption = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
|
||||
g_secure_applet_memory_address = Kernel::GetMemoryManager().AllocateContinuous(SecureAppletReservedMemorySize / PageSize, 1, SecureAppletAllocateOption);
|
||||
MESOSPHERE_ABORT_UNLESS(g_secure_applet_memory_address != Null<KVirtualAddress>);
|
||||
}
|
||||
}
|
||||
|
||||
u32 KSystemControl::GetInitialProcessBinaryPool() {
|
||||
return KMemoryManager::Pool_Application;
|
||||
}
|
||||
|
@ -274,6 +295,11 @@ namespace ams::kern {
|
|||
return GenerateUniformRange(min, max, GenerateRandomU64FromGenerator);
|
||||
}
|
||||
|
||||
void KSystemControl::SleepSystem() {
|
||||
MESOSPHERE_LOG("SleepSystem() was called\n");
|
||||
KSleepManager::SleepSystem();
|
||||
}
|
||||
|
||||
void KSystemControl::StopSystem() {
|
||||
if (g_call_smc_on_panic) {
|
||||
/* Display a panic screen via secure monitor. */
|
|
@ -16,7 +16,7 @@
|
|||
#include <mesosphere.hpp>
|
||||
#include "kern_secure_monitor.hpp"
|
||||
|
||||
namespace ams::kern::smc {
|
||||
namespace ams::kern::board::nintendo::nx::smc {
|
||||
|
||||
namespace {
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::smc {
|
||||
namespace ams::kern::board::nintendo::nx::smc {
|
||||
|
||||
/* Types. */
|
||||
enum MemorySize {
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* 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>
|
||||
#include "../../../kern_debug_log_impl.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
namespace {
|
||||
|
||||
enum UartRegister {
|
||||
UartRegister_THR = 0,
|
||||
UartRegister_IER = 1,
|
||||
UartRegister_FCR = 2,
|
||||
UartRegister_LCR = 3,
|
||||
|
||||
UartRegister_LSR = 5,
|
||||
|
||||
UartRegister_IRSA_CSR = 8,
|
||||
|
||||
UartRegister_DLL = 0,
|
||||
UartRegister_DLH = 1,
|
||||
};
|
||||
|
||||
KVirtualAddress g_uart_address = 0;
|
||||
|
||||
NOINLINE u32 ReadUartRegister(UartRegister which) {
|
||||
return GetPointer<volatile u32>(g_uart_address)[which];
|
||||
}
|
||||
|
||||
NOINLINE void WriteUartRegister(UartRegister which, u32 value) {
|
||||
GetPointer<volatile u32>(g_uart_address)[which] = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool KDebugLogImpl::Initialize() {
|
||||
/* Set the uart register base address. */
|
||||
g_uart_address = KMemoryLayout::GetUartAddress();
|
||||
|
||||
/* Parameters for uart. */
|
||||
constexpr u32 BaudRate = 115200;
|
||||
constexpr u32 Pllp = 408000000;
|
||||
constexpr u32 Rate = 16 * BaudRate;
|
||||
constexpr u32 Divisor = (Pllp + Rate / 2) / Rate;
|
||||
|
||||
/* Initialize the UART registers. */
|
||||
/* Set Divisor Latch Access bit, to allow access to DLL/DLH */
|
||||
WriteUartRegister(UartRegister_LCR, 0x80);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Program the divisor into DLL/DLH. */
|
||||
WriteUartRegister(UartRegister_DLL, Divisor & 0xFF);
|
||||
WriteUartRegister(UartRegister_DLH, (Divisor >> 8) & 0xFF);
|
||||
ReadUartRegister(UartRegister_DLH);
|
||||
|
||||
/* Set word length to 3, clear Divisor Latch Access. */
|
||||
WriteUartRegister(UartRegister_LCR, 0x03);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Disable UART interrupts. */
|
||||
WriteUartRegister(UartRegister_IER, 0x00);
|
||||
|
||||
/* Configure the FIFO to be enabled and clear receive. */
|
||||
WriteUartRegister(UartRegister_FCR, 0x03);
|
||||
WriteUartRegister(UartRegister_IRSA_CSR, 0x02);
|
||||
ReadUartRegister(UartRegister_FCR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KDebugLogImpl::PutChar(char c) {
|
||||
while (ReadUartRegister(UartRegister_LSR) & 0x100) {
|
||||
/* While the FIFO is full, yield. */
|
||||
__asm__ __volatile__("yield" ::: "memory");
|
||||
}
|
||||
WriteUartRegister(UartRegister_THR, c);
|
||||
cpu::DataSynchronizationBarrier();
|
||||
}
|
||||
|
||||
void KDebugLogImpl::Flush() {
|
||||
while ((ReadUartRegister(UartRegister_LSR) & 0x40) == 0) {
|
||||
/* Wait for the TMTY bit to be one (transmit empty). */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uintptr_t DramPhysicalAddress = 0x80000000;
|
||||
constexpr size_t ReservedEarlyDramSize = 0x60000;
|
||||
|
||||
ALWAYS_INLINE bool SetupUartPhysicalMemoryRegion() {
|
||||
#if defined(MESOSPHERE_DEBUG_LOG_USE_UART_A)
|
||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006000, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_B)
|
||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006040, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_C)
|
||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_D)
|
||||
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006300, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
|
||||
#else
|
||||
#error "Unknown Debug UART device!"
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void SetupDevicePhysicalMemoryRegions() {
|
||||
/* TODO: Give these constexpr defines somewhere? */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(SetupUartPhysicalMemoryRegion());
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70019000, 0x1000, KMemoryRegionType_MemoryController | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7001C000, 0x1000, KMemoryRegionType_MemoryController0 | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7001D000, 0x1000, KMemoryRegionType_MemoryController1 | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E400, 0xC00, KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50040000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50041000, 0x1000, KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50042000, 0x1000, KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
}
|
||||
|
||||
void SetupDramPhysicalMemoryRegions() {
|
||||
const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize();
|
||||
const KPhysicalAddress physical_memory_base_address = KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress);
|
||||
|
||||
/* Insert blocks into the tree. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(GetInteger(physical_memory_base_address), intended_memory_size, KMemoryRegionType_Dram));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(GetInteger(physical_memory_base_address), ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue