2021-01-29 09:03:25 -03:00
/*
* Copyright ( c ) 2021 , Liav A . < liavalb @ hotmail . co . il >
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2021-01-29 09:03:25 -03:00
*/
# include <AK/Memory.h>
# include <AK/StdLibExtras.h>
2021-09-11 03:19:20 -03:00
# include <Kernel/Devices/DeviceManagement.h>
2021-07-11 16:02:15 -03:00
# include <Kernel/Devices/MemoryDevice.h>
2021-09-11 04:39:47 -03:00
# include <Kernel/Firmware/BIOS.h>
2021-08-06 05:45:34 -03:00
# include <Kernel/Memory/AnonymousVMObject.h>
2021-12-23 16:49:31 -03:00
# include <Kernel/Memory/TypedMapping.h>
2021-06-22 12:40:16 -03:00
# include <Kernel/Sections.h>
2021-01-29 09:03:25 -03:00
namespace Kernel {
2021-06-18 05:37:26 -03:00
UNMAP_AFTER_INIT NonnullRefPtr < MemoryDevice > MemoryDevice : : must_create ( )
{
2021-09-11 03:19:20 -03:00
auto memory_device_or_error = DeviceManagement : : try_create_device < MemoryDevice > ( ) ;
2021-09-10 08:44:46 -03:00
// FIXME: Find a way to propagate errors
VERIFY ( ! memory_device_or_error . is_error ( ) ) ;
return memory_device_or_error . release_value ( ) ;
2021-06-18 05:37:26 -03:00
}
2021-02-19 17:29:46 -03:00
UNMAP_AFTER_INIT MemoryDevice : : MemoryDevice ( )
2021-01-29 09:03:25 -03:00
: CharacterDevice ( 1 , 1 )
{
}
2022-03-16 16:15:15 -03:00
UNMAP_AFTER_INIT MemoryDevice : : ~ MemoryDevice ( ) = default ;
2021-01-29 09:03:25 -03:00
2021-12-23 16:49:31 -03:00
ErrorOr < size_t > MemoryDevice : : read ( OpenFileDescription & , u64 offset , UserOrKernelBuffer & buffer , size_t length )
2021-01-29 09:03:25 -03:00
{
2021-12-23 16:49:31 -03:00
if ( ! MM . is_allowed_to_read_physical_memory_for_userspace ( PhysicalAddress ( offset ) , length ) ) {
2022-04-01 13:55:56 -03:00
dbgln_if ( MEMORY_DEVICE_DEBUG , " MemoryDevice: Trying to read physical memory at {} for range of {} bytes failed due to violation of access " , PhysicalAddress ( offset ) , length ) ;
2021-12-23 16:49:31 -03:00
return EINVAL ;
}
2022-01-13 13:20:22 -03:00
auto mapping = TRY ( Memory : : map_typed < u8 > ( PhysicalAddress ( offset ) , length ) ) ;
2021-12-23 16:49:31 -03:00
auto bytes = ReadonlyBytes { mapping . ptr ( ) , length } ;
TRY ( buffer . write ( bytes ) ) ;
return length ;
2021-01-29 09:03:25 -03:00
}
2021-11-07 20:51:39 -03:00
ErrorOr < Memory : : Region * > MemoryDevice : : mmap ( Process & process , OpenFileDescription & , Memory : : VirtualRange const & range , u64 offset , int prot , bool shared )
2021-01-29 09:03:25 -03:00
{
auto viewed_address = PhysicalAddress ( offset ) ;
2021-12-23 17:09:19 -03:00
// Note: This check happens to guard against possible memory leak.
// For example, if we try to mmap physical memory from 0x1000 to 0x2000 and you
// can actually mmap only from 0x1001, then we would fail as usual.
// However, in such case if we mmap from 0x1002, we are technically not violating
// any rules, besides the fact that we mapped an entire page with two bytes which we
// were not supposed to see. To prevent that, if we use mmap(2) syscall, we should
// always consider the start page to be aligned on PAGE_SIZE, or to be more precise
// is to be set to the page base of that start address.
VERIFY ( viewed_address = = viewed_address . page_base ( ) ) ;
2021-12-23 16:49:31 -03:00
if ( ! MM . is_allowed_to_read_physical_memory_for_userspace ( viewed_address , range . size ( ) ) ) {
2022-04-01 13:52:22 -03:00
dbgln_if ( MEMORY_DEVICE_DEBUG , " MemoryDevice: Trying to mmap physical memory at {} for range of {} bytes failed due to violation of access " , viewed_address , range . size ( ) ) ;
2021-01-29 09:03:25 -03:00
return EINVAL ;
}
2021-09-06 15:33:45 -03:00
auto vmobject = TRY ( Memory : : AnonymousVMObject : : try_create_for_physical_range ( viewed_address , range . size ( ) ) ) ;
2021-08-15 06:07:59 -03:00
2021-08-06 08:59:22 -03:00
return process . address_space ( ) . allocate_region_with_vmobject (
2021-01-29 09:03:25 -03:00
range ,
2021-09-06 15:33:45 -03:00
move ( vmobject ) ,
2021-01-29 09:03:25 -03:00
0 ,
" Mapped Physical Memory " ,
prot ,
shared ) ;
}
}