2020-01-29 14:26:24 -08:00
/*
* 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 {
2020-02-09 01:16:13 -08:00
namespace {
2020-04-19 00:35:05 -07:00
KDynamicPageManager g_resource_manager_page_manager ;
2020-02-09 01:16:13 -08: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 01:53:30 -08:00
void Kernel : : InitializeCoreLocalRegion ( s32 core_id ) {
2020-12-01 13:41:37 -08:00
/* The core local region no longer exists, so just clear the current thread. */
AMS_UNUSED ( core_id ) ;
SetCurrentThread ( nullptr ) ;
2020-01-29 14:26:24 -08:00
}
2020-01-31 01:53:30 -08: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 ) ) ;
KAutoObject : : Create ( main_thread ) ;
KAutoObject : : Create ( idle_thread ) ;
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 04:58:35 -08:00
/* Initialize the interrupt manager, hardware timer, and scheduler */
2020-02-05 13:02:35 -08:00
GetInterruptManager ( ) . Initialize ( core_id ) ;
2020-12-01 13:08:47 -08:00
GetHardwareTimer ( ) . Initialize ( ) ;
2020-02-05 13:02:35 -08:00
GetScheduler ( ) . Initialize ( idle_thread ) ;
2020-01-29 22:06:25 -08:00
}
2020-02-07 04:58:35 -08:00
void Kernel : : InitializeResourceManagers ( KVirtualAddress address , size_t size ) {
/* Ensure that the buffer is suitable for our use. */
2020-04-19 00:35:05 -07:00
//const size_t app_size = ApplicationMemoryBlockSlabHeapSize * sizeof(KMemoryBlock);
//const size_t sys_size = SystemMemoryBlockSlabHeapSize * sizeof(KMemoryBlock);
//const size_t info_size = BlockInfoSlabHeapSize * sizeof(KBlockInfo);
//const size_t fixed_size = util::AlignUp(app_size + sys_size + info_size, PageSize);
2020-02-07 04:58:35 -08:00
MESOSPHERE_ABORT_UNLESS ( util : : IsAligned ( GetInteger ( address ) , PageSize ) ) ;
MESOSPHERE_ABORT_UNLESS ( util : : IsAligned ( size , PageSize ) ) ;
2020-04-19 00:35:05 -07:00
/* Ensure that we have space for our reference counts. */
const size_t rc_size = util : : AlignUp ( KPageTableManager : : CalculateReferenceCountSize ( size ) , PageSize ) ;
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. */
s_app_memory_block_manager . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , ApplicationMemoryBlockSlabHeapSize ) ;
s_sys_memory_block_manager . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , SystemMemoryBlockSlabHeapSize ) ;
s_block_info_manager . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , BlockInfoSlabHeapSize ) ;
/* Reserve all remaining pages for the page table manager. */
const size_t num_pt_pages = g_resource_manager_page_manager . GetCount ( ) - g_resource_manager_page_manager . GetUsed ( ) ;
s_page_table_manager . Initialize ( std : : addressof ( g_resource_manager_page_manager ) , num_pt_pages , GetPointer < KPageTableManager : : RefCount > ( address + size ) ) ;
2020-02-07 04:58:35 -08:00
}
2020-02-09 01:16:13 -08:00
void Kernel : : PrintLayout ( ) {
2020-07-13 18:50:37 -07:00
const auto target_fw = kern : : GetTargetFirmware ( ) ;
2020-02-09 01:16:13 -08:00
/* Print out the kernel version. */
MESOSPHERE_LOG ( " Horizon Kernel (Mesosphere) \n " ) ;
2020-02-09 02:05:49 -08: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-13 18:50:37 -07:00
MESOSPHERE_LOG ( " Target Firmware: %d.%d.%d \n " , ( target_fw > > 24 ) & 0xFF , ( target_fw > > 16 ) & 0xFF , ( target_fw > > 8 ) & 0xFF ) ;
2020-02-09 01:16:13 -08: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 12:06:24 -07:00
PrintMemoryRegion ( " LinearRegion " , KMemoryLayout : : GetLinearRegionVirtualExtents ( ) ) ;
2020-02-09 01:16:13 -08: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-25 18:10:58 -07:00
if ( GetTargetFirmware ( ) > = TargetFirmware_5_0_0 ) {
PrintMemoryRegion ( " System " , KMemoryLayout : : GetKernelSystemPoolRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Management " , KMemoryLayout : : GetKernelPoolManagementRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " SystemUnsafe " , KMemoryLayout : : GetKernelSystemNonSecurePoolRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Applet " , KMemoryLayout : : GetKernelAppletPoolRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Application " , KMemoryLayout : : GetKernelApplicationPoolRegionPhysicalExtents ( ) ) ;
} else {
PrintMemoryRegion ( " Secure " , KMemoryLayout : : GetKernelSystemPoolRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Management " , KMemoryLayout : : GetKernelPoolManagementRegionPhysicalExtents ( ) ) ;
PrintMemoryRegion ( " Unsafe " , KMemoryLayout : : GetKernelApplicationPoolRegionPhysicalExtents ( ) ) ;
}
2020-07-31 17:01:01 -07:00
if constexpr ( IsKTraceEnabled ) {
MESOSPHERE_LOG ( " Debug \n " ) ;
PrintMemoryRegion ( " Trace Buffer " , KMemoryLayout : : GetKernelTraceBufferRegionPhysicalExtents ( ) ) ;
}
2020-02-09 01:16:13 -08:00
MESOSPHERE_LOG ( " \n " ) ;
}
2020-01-29 14:26:24 -08:00
}