@ -39,6 +39,73 @@ namespace {
constexpr bool Is4KBAligned ( VAddr address ) {
return ( address & 0xFFF ) = = 0 ;
}
// Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
constexpr bool IsValidAddressRange ( VAddr address , u64 size ) {
return address + size > address ;
}
// Checks if a given address range lies within a larger address range.
constexpr bool IsInsideAddressRange ( VAddr address , u64 size , VAddr address_range_begin ,
VAddr address_range_end ) {
const VAddr end_address = address + size - 1 ;
return address_range_begin < = address & & end_address < = address_range_end - 1 ;
}
bool IsInsideAddressSpace ( const VMManager & vm , VAddr address , u64 size ) {
return IsInsideAddressRange ( address , size , vm . GetAddressSpaceBaseAddress ( ) ,
vm . GetAddressSpaceEndAddress ( ) ) ;
}
bool IsInsideNewMapRegion ( const VMManager & vm , VAddr address , u64 size ) {
return IsInsideAddressRange ( address , size , vm . GetNewMapRegionBaseAddress ( ) ,
vm . GetNewMapRegionEndAddress ( ) ) ;
}
// Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order.
ResultCode MapUnmapMemorySanityChecks ( const VMManager & vm_manager , VAddr dst_addr , VAddr src_addr ,
u64 size ) {
if ( ! Is4KBAligned ( dst_addr ) | | ! Is4KBAligned ( src_addr ) ) {
return ERR_INVALID_ADDRESS ;
}
if ( size = = 0 | | ! Is4KBAligned ( size ) ) {
return ERR_INVALID_SIZE ;
}
if ( ! IsValidAddressRange ( dst_addr , size ) ) {
return ERR_INVALID_ADDRESS_STATE ;
}
if ( ! IsValidAddressRange ( src_addr , size ) ) {
return ERR_INVALID_ADDRESS_STATE ;
}
if ( ! IsInsideAddressSpace ( vm_manager , src_addr , size ) ) {
return ERR_INVALID_ADDRESS_STATE ;
}
if ( ! IsInsideNewMapRegion ( vm_manager , dst_addr , size ) ) {
return ERR_INVALID_MEMORY_RANGE ;
}
const VAddr dst_end_address = dst_addr + size ;
if ( dst_end_address > vm_manager . GetHeapRegionBaseAddress ( ) & &
dst_addr < vm_manager . GetHeapRegionEndAddress ( ) ) {
return ERR_INVALID_MEMORY_RANGE ;
}
if ( dst_end_address > vm_manager . GetNewMapRegionBaseAddress ( ) & &
dst_addr < vm_manager . GetMapRegionEndAddress ( ) ) {
return ERR_INVALID_MEMORY_RANGE ;
}
return RESULT_SUCCESS ;
}
} // Anonymous namespace
/// Set the process heap to a given Size. It can both extend and shrink the heap.
@ -69,15 +136,15 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE ( Kernel_SVC , " called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X} " , dst_addr ,
src_addr , size ) ;
if ( ! Is4KBAligned ( dst_addr ) | | ! Is4KBAligned ( src_addr ) ) {
return ERR_INVALID_ADDRESS ;
auto * const current_process = Core : : CurrentProcess ( ) ;
const auto & vm_manager = current_process - > VMManager ( ) ;
const auto result = MapUnmapMemorySanityChecks ( vm_manager , dst_addr , src_addr , size ) ;
if ( result ! = RESULT_SUCCESS ) {
return result ;
}
if ( size = = 0 | | ! Is4KBAligned ( size ) ) {
return ERR_INVALID_SIZE ;
}
return Core : : CurrentProcess ( ) - > MirrorMemory ( dst_addr , src_addr , size ) ;
return current_process - > MirrorMemory ( dst_addr , src_addr , size ) ;
}
/// Unmaps a region that was previously mapped with svcMapMemory
@ -85,15 +152,15 @@ static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE ( Kernel_SVC , " called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X} " , dst_addr ,
src_addr , size ) ;
if ( ! Is4KBAligned ( dst_addr ) | | ! Is4KBAligned ( src_addr ) ) {
return ERR_INVALID_ADDRESS ;
auto * const current_process = Core : : CurrentProcess ( ) ;
const auto & vm_manager = current_process - > VMManager ( ) ;
const auto result = MapUnmapMemorySanityChecks ( vm_manager , dst_addr , src_addr , size ) ;
if ( result ! = RESULT_SUCCESS ) {
return result ;
}
if ( size = = 0 | | ! Is4KBAligned ( size ) ) {
return ERR_INVALID_SIZE ;
}
return Core : : CurrentProcess ( ) - > UnmapMemory ( dst_addr , src_addr , size ) ;
return current_process - > UnmapMemory ( dst_addr , src_addr , size ) ;
}
/// Connect to an OS service given the port name, returns the handle to the port to out