@ -2,11 +2,13 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
# include <cinttypes>
# include <map>
# include <memory>
# include <utility>
# include <vector>
# include "audio_core/audio_core.h"
# include "common/assert.h"
# include "common/common_types.h"
# include "common/logging/log.h"
# include "core/hle/config_mem.h"
@ -92,57 +94,96 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
UNREACHABLE ( ) ;
}
}
}
namespace Memory {
std : : array < u8 , Memory : : VRAM_SIZE > vram ;
std : : array < u8 , Memory : : N3DS_EXTRA_RAM_SIZE > n3ds_extra_ram ;
namespace {
void HandleSpecialMapping ( VMManager & address_space , const AddressMapping & mapping ) {
using namespace Memory ;
struct MemoryArea {
u32 base;
u32 siz e;
const char * nam e;
} ;
struct MemoryArea {
VAddr vaddr_ base;
PAddr paddr_bas e;
u32 siz e;
} ;
// We don't declare the IO regions in here since its handled by other means.
static MemoryArea memory_areas [ ] = {
{ VRAM_VADDR , VRAM_SIZE , " VRAM " } , // Video memory (VRAM)
} ;
}
// The order of entries in this array is important. The VRAM and IO VAddr ranges overlap, and
// VRAM must be tried first.
static constexpr MemoryArea memory_areas [ ] = {
{ VRAM_VADDR , VRAM_PADDR , VRAM_SIZE } ,
{ IO_AREA_VADDR , IO_AREA_PADDR , IO_AREA_SIZE } ,
{ DSP_RAM_VADDR , DSP_RAM_PADDR , DSP_RAM_SIZE } ,
{ N3DS_EXTRA_RAM_VADDR , N3DS_EXTRA_RAM_PADDR , N3DS_EXTRA_RAM_SIZE - 0x20000 } ,
} ;
void Init ( ) {
InitMemoryMap ( ) ;
LOG_DEBUG ( HW_Memory , " initialized OK " ) ;
}
void InitLegacyAddressSpace ( Kernel : : VMManager & address_space ) {
using namespace Kernel ;
for ( MemoryArea & area : memory_areas ) {
auto block = std : : make_shared < std : : vector < u8 > > ( area . size ) ;
address_space
. MapMemoryBlock ( area . base , std : : move ( block ) , 0 , area . size , MemoryState : : Private )
. Unwrap ( ) ;
VAddr mapping_limit = mapping . address + mapping . size ;
if ( mapping_limit < mapping . address ) {
LOG_CRITICAL ( Loader , " Mapping size overflowed: address=0x%08 " PRIX32 " size=0x% " PRIX32 ,
mapping . address , mapping . size ) ;
return ;
}
auto area =
std : : find_if ( std : : begin ( memory_areas ) , std : : end ( memory_areas ) , [ & ] ( const auto & area ) {
return mapping . address > = area . vaddr_base & &
mapping_limit < = area . vaddr_base + area . size ;
} ) ;
if ( area = = std : : end ( memory_areas ) ) {
LOG_ERROR ( Loader , " Unhandled special mapping: address=0x%08 " PRIX32 " size=0x% " PRIX32
" read_only=%d unk_flag=%d " ,
mapping . address , mapping . size , mapping . read_only , mapping . unk_flag ) ;
return ;
}
u32 offset_into_region = mapping . address - area - > vaddr_base ;
if ( area - > paddr_base = = IO_AREA_PADDR ) {
LOG_ERROR ( Loader , " MMIO mappings are not supported yet. phys_addr=0x%08 " PRIX32 ,
area - > paddr_base + offset_into_region ) ;
return ;
}
// TODO(yuriks): Use GetPhysicalPointer when that becomes independent of the virtual
// mappings.
u8 * target_pointer = nullptr ;
switch ( area - > paddr_base ) {
case VRAM_PADDR :
target_pointer = vram . data ( ) ;
break ;
case DSP_RAM_PADDR :
target_pointer = AudioCore : : GetDspMemory ( ) . data ( ) ;
break ;
case N3DS_EXTRA_RAM_PADDR :
target_pointer = n3ds_extra_ram . data ( ) ;
break ;
default :
UNREACHABLE ( ) ;
}
// TODO(yuriks): This flag seems to have some other effect, but it's unknown what
MemoryState memory_state = mapping . unk_flag ? MemoryState : : Static : MemoryState : : IO ;
auto vma = address_space
. MapBackingMemory ( mapping . address , target_pointer + offset_into_region ,
mapping . size , memory_state )
. MoveFrom ( ) ;
address_space . Reprotect ( vma ,
mapping . read_only ? VMAPermission : : Read : VMAPermission : : ReadWrite ) ;
}
void MapSharedPages ( VMManager & address_space ) {
auto cfg_mem_vma = address_space
. MapBackingMemory ( CONFIG_MEMORY_VADDR , ( u8 * ) & ConfigMem : : config_mem ,
CONFIG_MEMORY_SIZE , MemoryState : : Shared )
. MapBackingMemory ( Memory : : CONFIG_MEMORY_VADDR ,
reinterpret_cast < u8 * > ( & ConfigMem : : config_mem ) ,
Memory : : CONFIG_MEMORY_SIZE , MemoryState : : Shared )
. MoveFrom ( ) ;
address_space . Reprotect ( cfg_mem_vma , VMAPermission : : Read ) ;
auto shared_page_vma = address_space
. MapBackingMemory ( SHARED_PAGE_VADDR , ( u8 * ) & SharedPage : : shared_page ,
SHARED_PAGE_SIZE , MemoryState : : Shared )
. MapBackingMemory ( Memory : : SHARED_PAGE_VADDR ,
reinterpret_cast < u8 * > ( & SharedPage : : shared_page ) ,
Memory : : SHARED_PAGE_SIZE , MemoryState : : Shared )
. MoveFrom ( ) ;
address_space . Reprotect ( shared_page_vma , VMAPermission : : Read ) ;
auto & dsp_ram = AudioCore : : GetDspMemory ( ) ;
auto dsp_vma = address_space
. MapBackingMemory ( DSP_RAM_VADDR , dsp_ram . data ( ) , dsp_ram . size ( ) ,
Kernel : : MemoryState : : IO )
. MoveFrom ( ) ;
address_space . Reprotect ( dsp_vma , Kernel : : VMAPermission : : ReadWrite ) ;
}
} // namespace
} // namespace Kernel