2020-01-29 22:26:24 +00:00
/*
2021-10-04 20:59:10 +01:00
* Copyright ( c ) Atmosphère - NX
2020-01-29 22:26:24 +00:00
*
* 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 {
2020-02-09 09:16:13 +00:00
namespace {
2020-04-19 08:35:05 +01:00
KDynamicPageManager g_resource_manager_page_manager ;
2020-02-09 09:16:13 +00:00
template < typename T >
ALWAYS_INLINE void PrintMemoryRegion ( const char * prefix , const T & extents ) {
static_assert ( std : : is_same < decltype ( extents . GetAddress ( ) ) , uintptr_t > : : value ) ;
static_assert ( std : : is_same < decltype ( extents . GetLastAddress ( ) ) , uintptr_t > : : value ) ;
if constexpr ( std : : is_same < uintptr_t , unsigned int > : : value ) {
MESOSPHERE_LOG ( " %-24s0x%08x - 0x%08x \n " , prefix , extents . GetAddress ( ) , extents . GetLastAddress ( ) ) ;
} else if constexpr ( std : : is_same < uintptr_t , unsigned long > : : value ) {
MESOSPHERE_LOG ( " %-24s0x%016lx - 0x%016lx \n " , prefix , extents . GetAddress ( ) , extents . GetLastAddress ( ) ) ;
} else if constexpr ( std : : is_same < uintptr_t , unsigned long long > : : value ) {
MESOSPHERE_LOG ( " %-24s0x%016llx - 0x%016llx \n " , prefix , extents . GetAddress ( ) , extents . GetLastAddress ( ) ) ;
} else {
static_assert ( ! std : : is_same < T , T > : : value , " Unknown uintptr_t width! " ) ;
}
}
}
2020-01-31 09:53:30 +00:00
void Kernel : : InitializeCoreLocalRegion ( s32 core_id ) {
2020-12-01 21:41:37 +00:00
/* The core local region no longer exists, so just clear the current thread. */
AMS_UNUSED ( core_id ) ;
SetCurrentThread ( nullptr ) ;
2020-01-29 22:26:24 +00:00
}
2020-01-31 09:53:30 +00:00
void Kernel : : InitializeMainAndIdleThreads ( s32 core_id ) {
/* This function wants to setup the main thread and the idle thread. */
KThread * main_thread = std : : addressof ( Kernel : : GetMainThread ( core_id ) ) ;
void * main_thread_stack = GetVoidPointer ( KMemoryLayout : : GetMainStackTopAddress ( core_id ) ) ;
KThread * idle_thread = std : : addressof ( Kernel : : GetIdleThread ( core_id ) ) ;
void * idle_thread_stack = GetVoidPointer ( KMemoryLayout : : GetIdleStackTopAddress ( core_id ) ) ;
2021-10-24 00:04:04 +01:00
KAutoObject : : Create < KThread > ( main_thread ) ;
KAutoObject : : Create < KThread > ( idle_thread ) ;
2020-01-31 09:53:30 +00:00
main_thread - > Initialize ( nullptr , 0 , main_thread_stack , 0 , KThread : : MainThreadPriority , core_id , nullptr , KThread : : ThreadType_Main ) ;
idle_thread - > Initialize ( nullptr , 0 , idle_thread_stack , 0 , KThread : : IdleThreadPriority , core_id , nullptr , KThread : : ThreadType_Main ) ;
/* Set the current thread to be the main thread, and we have no processes running yet. */
SetCurrentThread ( main_thread ) ;
2020-02-07 12:58:35 +00:00
/* Initialize the interrupt manager, hardware timer, and scheduler */
2020-02-05 21:02:35 +00:00
GetInterruptManager ( ) . Initialize ( core_id ) ;
2020-12-01 21:08:47 +00:00
GetHardwareTimer ( ) . Initialize ( ) ;
2020-02-05 21:02:35 +00:00
GetScheduler ( ) . Initialize ( idle_thread ) ;
2020-01-30 06:06:25 +00:00
}
2020-02-07 12:58:35 +00:00
void Kernel : : InitializeResourceManagers ( KVirtualAddress address , size_t size ) {
/* Ensure that the buffer is suitable for our use. */
MESOSPHERE_ABORT_UNLESS ( util : : IsAligned ( GetInteger ( address ) , PageSize ) ) ;
MESOSPHERE_ABORT_UNLESS ( util : : IsAligned ( size , PageSize ) ) ;
2020-04-19 08:35:05 +01:00
/* Ensure that we have space for our reference counts. */
2021-09-18 06:01:58 +01:00
const size_t rc_size = util : : AlignUp ( KPageTableSlabHeap : : CalculateReferenceCountSize ( size ) , PageSize ) ;
2020-04-19 08:35:05 +01:00
MESOSPHERE_ABORT_UNLESS ( rc_size < size ) ;
size - = rc_size ;
/* Initialize the resource managers' shared page manager. */
g_resource_manager_page_manager . Initialize ( address , size ) ;
/* Initialize the fixed-size slabheaps. */
2021-09-18 06:01:58 +01:00
s_app_memory_block_heap . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , ApplicationMemoryBlockSlabHeapSize ) ;
s_sys_memory_block_heap . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , SystemMemoryBlockSlabHeapSize ) ;
s_block_info_heap . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , BlockInfoSlabHeapSize ) ;
2020-04-19 08:35:05 +01:00
2021-09-18 06:01:58 +01:00
/* Reserve all but a fixed number of remaining pages for the page table heap. */
const size_t num_pt_pages = g_resource_manager_page_manager . GetCount ( ) - g_resource_manager_page_manager . GetUsed ( ) - ReservedDynamicPageCount ;
s_page_table_heap . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , num_pt_pages , GetPointer < KPageTableManager : : RefCount > ( address + size ) ) ;
/* Setup the slab managers. */
KDynamicPageManager * const app_dynamic_page_manager = nullptr ;
KDynamicPageManager * const sys_dynamic_page_manager = KTargetSystem : : IsDynamicResourceLimitsEnabled ( ) ? std : : addressof ( g_resource_manager_page_manager ) : nullptr ;
s_app_memory_block_manager . Initialize ( app_dynamic_page_manager , std : : addressof ( s_app_memory_block_heap ) ) ;
s_sys_memory_block_manager . Initialize ( sys_dynamic_page_manager , std : : addressof ( s_sys_memory_block_heap ) ) ;
s_app_block_info_manager . Initialize ( app_dynamic_page_manager , std : : addressof ( s_block_info_heap ) ) ;
s_sys_block_info_manager . Initialize ( sys_dynamic_page_manager , std : : addressof ( s_block_info_heap ) ) ;
s_app_page_table_manager . Initialize ( app_dynamic_page_manager , std : : addressof ( s_page_table_heap ) ) ;
s_sys_page_table_manager . Initialize ( sys_dynamic_page_manager , std : : addressof ( s_page_table_heap ) ) ;
/* Check that we have the correct number of dynamic pages available. */
MESOSPHERE_ABORT_UNLESS ( g_resource_manager_page_manager . GetCount ( ) - g_resource_manager_page_manager . GetUsed ( ) = = ReservedDynamicPageCount ) ;
2020-02-07 12:58:35 +00:00
}
2020-02-09 09:16:13 +00:00
void Kernel : : PrintLayout ( ) {
2020-07-14 02:50:37 +01:00
const auto target_fw = kern : : GetTargetFirmware ( ) ;
2020-02-09 09:16:13 +00:00
/* Print out the kernel version. */
MESOSPHERE_LOG ( " Horizon Kernel (Mesosphere) \n " ) ;
2020-02-09 10:05:49 +00:00
MESOSPHERE_LOG ( " Built: %s %s \n " , __DATE__ , __TIME__ ) ;
MESOSPHERE_LOG ( " Atmosphere version: %d.%d.%d-%s \n " , ATMOSPHERE_RELEASE_VERSION , ATMOSPHERE_GIT_REVISION ) ;
2020-07-14 02:50:37 +01:00
MESOSPHERE_LOG ( " Target Firmware: %d.%d.%d \n " , ( target_fw > > 24 ) & 0xFF , ( target_fw > > 16 ) & 0xFF , ( target_fw > > 8 ) & 0xFF ) ;
2020-02-09 09:16:13 +00:00
MESOSPHERE_LOG ( " Supported OS version: %d.%d.%d \n " , ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR , ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR , ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO ) ;
MESOSPHERE_LOG ( " \n " ) ;
/* Print relative memory usage. */
const auto [ total , kernel ] = KMemoryLayout : : GetTotalAndKernelMemorySizes ( ) ;
MESOSPHERE_LOG ( " Kernel Memory Usage: %zu/%zu MB \n " , util : : AlignUp ( kernel , 1 _MB ) / 1 _MB , util : : AlignUp ( total , 1 _MB ) / 1 _MB ) ;
MESOSPHERE_LOG ( " \n " ) ;
/* Print out important memory layout regions. */
MESOSPHERE_LOG ( " Virtual Memory Layout \n " ) ;
PrintMemoryRegion ( " KernelRegion " , KMemoryLayout : : GetKernelRegionExtents ( ) ) ;
PrintMemoryRegion ( " Code " , KMemoryLayout : : GetKernelCodeRegionExtents ( ) ) ;
PrintMemoryRegion ( " Stack " , KMemoryLayout : : GetKernelStackRegionExtents ( ) ) ;
PrintMemoryRegion ( " Misc " , KMemoryLayout : : GetKernelMiscRegionExtents ( ) ) ;
PrintMemoryRegion ( " Slab " , KMemoryLayout : : GetKernelSlabRegionExtents ( ) ) ;
2020-08-03 20:06:24 +01:00
PrintMemoryRegion ( " LinearRegion " , KMemoryLayout : : GetLinearRegionVirtualExtents ( ) ) ;
2020-02-09 09:16:13 +00:00
MESOSPHERE_LOG ( " \n " ) ;
MESOSPHERE_LOG ( " Physical Memory Layout \n " ) ;
PrintMemoryRegion ( " LinearRegion " , KMemoryLayout : : GetLinearRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " CarveoutRegion " , KMemoryLayout : : GetCarveoutRegionExtents ( ) ) ;
MESOSPHERE_LOG ( " \n " ) ;
PrintMemoryRegion ( " KernelRegion " , KMemoryLayout : : GetKernelRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Code " , KMemoryLayout : : GetKernelCodeRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Slab " , KMemoryLayout : : GetKernelSlabRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " PageTableHeap " , KMemoryLayout : : GetKernelPageTableHeapRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " InitPageTable " , KMemoryLayout : : GetKernelInitPageTableRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " MemoryPoolRegion " , KMemoryLayout : : GetKernelPoolPartitionRegionPhysicalExtents ( ) ) ;
2020-08-26 02:10:58 +01:00
if ( GetTargetFirmware ( ) > = TargetFirmware_5_0_0 ) {
PrintMemoryRegion ( " Management " , KMemoryLayout : : GetKernelPoolManagementRegionPhysicalExtents ( ) ) ;
2021-10-25 23:07:24 +01:00
PrintMemoryRegion ( " System " , KMemoryLayout : : GetKernelSystemPoolRegionPhysicalExtents ( ) ) ;
if ( KMemoryLayout : : HasKernelSystemNonSecurePoolRegion ( ) ) {
PrintMemoryRegion ( " SystemUnsafe " , KMemoryLayout : : GetKernelSystemNonSecurePoolRegionPhysicalExtents ( ) ) ;
}
if ( KMemoryLayout : : HasKernelAppletPoolRegion ( ) ) {
PrintMemoryRegion ( " Applet " , KMemoryLayout : : GetKernelAppletPoolRegionPhysicalExtents ( ) ) ;
}
if ( KMemoryLayout : : HasKernelApplicationPoolRegion ( ) ) {
PrintMemoryRegion ( " Application " , KMemoryLayout : : GetKernelApplicationPoolRegionPhysicalExtents ( ) ) ;
}
2020-08-26 02:10:58 +01:00
} else {
PrintMemoryRegion ( " Management " , KMemoryLayout : : GetKernelPoolManagementRegionPhysicalExtents ( ) ) ;
2021-10-25 23:07:24 +01:00
PrintMemoryRegion ( " Secure " , KMemoryLayout : : GetKernelSystemPoolRegionPhysicalExtents ( ) ) ;
2020-08-26 02:10:58 +01:00
PrintMemoryRegion ( " Unsafe " , KMemoryLayout : : GetKernelApplicationPoolRegionPhysicalExtents ( ) ) ;
}
2020-08-01 01:01:01 +01:00
if constexpr ( IsKTraceEnabled ) {
MESOSPHERE_LOG ( " Debug \n " ) ;
PrintMemoryRegion ( " Trace Buffer " , KMemoryLayout : : GetKernelTraceBufferRegionPhysicalExtents ( ) ) ;
}
2020-02-09 09:16:13 +00:00
MESOSPHERE_LOG ( " \n " ) ;
}
2020-01-29 22:26:24 +00:00
}