@ -20,8 +20,105 @@
# include "video_core/gpu.h"
namespace Memory {
namespace {
Common : : PageTable * current_page_table = nullptr ;
static Common : : PageTable * current_page_table = nullptr ;
/**
* Gets a pointer to the exact memory at the virtual address ( i . e . not page aligned )
* using a VMA from the current process
*/
u8 * GetPointerFromVMA ( const Kernel : : Process & process , VAddr vaddr ) {
const auto & vm_manager = process . VMManager ( ) ;
const auto it = vm_manager . FindVMA ( vaddr ) ;
DEBUG_ASSERT ( vm_manager . IsValidHandle ( it ) ) ;
u8 * direct_pointer = nullptr ;
const auto & vma = it - > second ;
switch ( vma . type ) {
case Kernel : : VMAType : : AllocatedMemoryBlock :
direct_pointer = vma . backing_block - > data ( ) + vma . offset ;
break ;
case Kernel : : VMAType : : BackingMemory :
direct_pointer = vma . backing_memory ;
break ;
case Kernel : : VMAType : : Free :
return nullptr ;
default :
UNREACHABLE ( ) ;
}
return direct_pointer + ( vaddr - vma . base ) ;
}
/**
* Gets a pointer to the exact memory at the virtual address ( i . e . not page aligned )
* using a VMA from the current process .
*/
u8 * GetPointerFromVMA ( VAddr vaddr ) {
return : : Memory : : GetPointerFromVMA ( * Core : : System : : GetInstance ( ) . CurrentProcess ( ) , vaddr ) ;
}
template < typename T >
T Read ( const VAddr vaddr ) {
const u8 * const page_pointer = current_page_table - > pointers [ vaddr > > PAGE_BITS ] ;
if ( page_pointer ! = nullptr ) {
// NOTE: Avoid adding any extra logic to this fast-path block
T value ;
std : : memcpy ( & value , & page_pointer [ vaddr & PAGE_MASK ] , sizeof ( T ) ) ;
return value ;
}
const Common : : PageType type = current_page_table - > attributes [ vaddr > > PAGE_BITS ] ;
switch ( type ) {
case Common : : PageType : : Unmapped :
LOG_ERROR ( HW_Memory , " Unmapped Read{} @ 0x{:08X} " , sizeof ( T ) * 8 , vaddr ) ;
return 0 ;
case Common : : PageType : : Memory :
ASSERT_MSG ( false , " Mapped memory page without a pointer @ {:016X} " , vaddr ) ;
break ;
case Common : : PageType : : RasterizerCachedMemory : {
const u8 * const host_ptr { GetPointerFromVMA ( vaddr ) } ;
Core : : System : : GetInstance ( ) . GPU ( ) . FlushRegion ( ToCacheAddr ( host_ptr ) , sizeof ( T ) ) ;
T value ;
std : : memcpy ( & value , host_ptr , sizeof ( T ) ) ;
return value ;
}
default :
UNREACHABLE ( ) ;
}
return { } ;
}
template < typename T >
void Write ( const VAddr vaddr , const T data ) {
u8 * const page_pointer = current_page_table - > pointers [ vaddr > > PAGE_BITS ] ;
if ( page_pointer ! = nullptr ) {
// NOTE: Avoid adding any extra logic to this fast-path block
std : : memcpy ( & page_pointer [ vaddr & PAGE_MASK ] , & data , sizeof ( T ) ) ;
return ;
}
Common : : PageType type = current_page_table - > attributes [ vaddr > > PAGE_BITS ] ;
switch ( type ) {
case Common : : PageType : : Unmapped :
LOG_ERROR ( HW_Memory , " Unmapped Write{} 0x{:08X} @ 0x{:016X} " , sizeof ( data ) * 8 ,
static_cast < u32 > ( data ) , vaddr ) ;
return ;
case Common : : PageType : : Memory :
ASSERT_MSG ( false , " Mapped memory page without a pointer @ {:016X} " , vaddr ) ;
break ;
case Common : : PageType : : RasterizerCachedMemory : {
u8 * const host_ptr { GetPointerFromVMA ( vaddr ) } ;
Core : : System : : GetInstance ( ) . GPU ( ) . InvalidateRegion ( ToCacheAddr ( host_ptr ) , sizeof ( T ) ) ;
std : : memcpy ( host_ptr , & data , sizeof ( T ) ) ;
break ;
}
default :
UNREACHABLE ( ) ;
}
}
} // Anonymous namespace
// Implementation class used to keep the specifics of the memory subsystem hidden
// from outside classes. This also allows modification to the internals of the memory
@ -191,102 +288,6 @@ void SetCurrentPageTable(Kernel::Process& process) {
system . ArmInterface ( 3 ) . PageTableChanged ( * current_page_table , address_space_width ) ;
}
/**
* Gets a pointer to the exact memory at the virtual address ( i . e . not page aligned )
* using a VMA from the current process
*/
static u8 * GetPointerFromVMA ( const Kernel : : Process & process , VAddr vaddr ) {
const auto & vm_manager = process . VMManager ( ) ;
const auto it = vm_manager . FindVMA ( vaddr ) ;
DEBUG_ASSERT ( vm_manager . IsValidHandle ( it ) ) ;
u8 * direct_pointer = nullptr ;
const auto & vma = it - > second ;
switch ( vma . type ) {
case Kernel : : VMAType : : AllocatedMemoryBlock :
direct_pointer = vma . backing_block - > data ( ) + vma . offset ;
break ;
case Kernel : : VMAType : : BackingMemory :
direct_pointer = vma . backing_memory ;
break ;
case Kernel : : VMAType : : Free :
return nullptr ;
default :
UNREACHABLE ( ) ;
}
return direct_pointer + ( vaddr - vma . base ) ;
}
/**
* Gets a pointer to the exact memory at the virtual address ( i . e . not page aligned )
* using a VMA from the current process .
*/
static u8 * GetPointerFromVMA ( VAddr vaddr ) {
return GetPointerFromVMA ( * Core : : System : : GetInstance ( ) . CurrentProcess ( ) , vaddr ) ;
}
template < typename T >
T Read ( const VAddr vaddr ) {
const u8 * page_pointer = current_page_table - > pointers [ vaddr > > PAGE_BITS ] ;
if ( page_pointer ) {
// NOTE: Avoid adding any extra logic to this fast-path block
T value ;
std : : memcpy ( & value , & page_pointer [ vaddr & PAGE_MASK ] , sizeof ( T ) ) ;
return value ;
}
Common : : PageType type = current_page_table - > attributes [ vaddr > > PAGE_BITS ] ;
switch ( type ) {
case Common : : PageType : : Unmapped :
LOG_ERROR ( HW_Memory , " Unmapped Read{} @ 0x{:08X} " , sizeof ( T ) * 8 , vaddr ) ;
return 0 ;
case Common : : PageType : : Memory :
ASSERT_MSG ( false , " Mapped memory page without a pointer @ {:016X} " , vaddr ) ;
break ;
case Common : : PageType : : RasterizerCachedMemory : {
auto host_ptr { GetPointerFromVMA ( vaddr ) } ;
Core : : System : : GetInstance ( ) . GPU ( ) . FlushRegion ( ToCacheAddr ( host_ptr ) , sizeof ( T ) ) ;
T value ;
std : : memcpy ( & value , host_ptr , sizeof ( T ) ) ;
return value ;
}
default :
UNREACHABLE ( ) ;
}
return { } ;
}
template < typename T >
void Write ( const VAddr vaddr , const T data ) {
u8 * page_pointer = current_page_table - > pointers [ vaddr > > PAGE_BITS ] ;
if ( page_pointer ) {
// NOTE: Avoid adding any extra logic to this fast-path block
std : : memcpy ( & page_pointer [ vaddr & PAGE_MASK ] , & data , sizeof ( T ) ) ;
return ;
}
Common : : PageType type = current_page_table - > attributes [ vaddr > > PAGE_BITS ] ;
switch ( type ) {
case Common : : PageType : : Unmapped :
LOG_ERROR ( HW_Memory , " Unmapped Write{} 0x{:08X} @ 0x{:016X} " , sizeof ( data ) * 8 ,
static_cast < u32 > ( data ) , vaddr ) ;
return ;
case Common : : PageType : : Memory :
ASSERT_MSG ( false , " Mapped memory page without a pointer @ {:016X} " , vaddr ) ;
break ;
case Common : : PageType : : RasterizerCachedMemory : {
auto host_ptr { GetPointerFromVMA ( vaddr ) } ;
Core : : System : : GetInstance ( ) . GPU ( ) . InvalidateRegion ( ToCacheAddr ( host_ptr ) , sizeof ( T ) ) ;
std : : memcpy ( host_ptr , & data , sizeof ( T ) ) ;
break ;
}
default :
UNREACHABLE ( ) ;
}
}
bool IsKernelVirtualAddress ( const VAddr vaddr ) {
return KERNEL_REGION_VADDR < = vaddr & & vaddr < KERNEL_REGION_END ;
}