// SPDX-License-Identifier: MPL-2.0 #ifndef SH_LIB_PAGE_H #define SH_LIB_PAGE_H #include "std/type.h" #include "std/status.h" #include "memory/vmem_layout.h" #define SH_PAGE_KERNEL_PERM_VA_BASE SH_VMEM_LAYOUT_KERNEL_ALLOC_SPACE_VA #define SH_PAGE_KERNEL_PERM_VA_END SH_VMEM_LAYOUT_KERNEL_ALLOC_SPACE_VA_END #define SH_PAGE_MEMORY_MAP_VA SH_VMEM_LAYOUT_MEMORY_MAP_VA #define SH_PAGE_SIZE 4096 #define SH_PAGE_MAX_MEM_COUNT 16ULL*1024*1024*1024*1024 #define SH_PAGE_MAX_PAGES_COUNT (SH_PAGE_MAX_MEM_COUNT/SH_PAGE_SIZE) #define SH_PAGE_PTP_ALLOCATOR_PAGES_COUNT 4096 #define SH_PAGE_PTP_ALLOCATOR_BITMAP_UINT64 SH_PAGE_PTP_ALLOCATOR_PAGES_COUNT/64 typedef sh_uint32 sh_page_MEMORY_TYPE; #define SH_PAGE_RESERVED_MEMORY_TYPE (sh_page_MEMORY_TYPE)0 #define SH_PAGE_LOADER_CODE (sh_page_MEMORY_TYPE)1 #define SH_PAGE_LOADER_DATA (sh_page_MEMORY_TYPE)2 #define SH_PAGE_BOOT_SERVICES_CODE (sh_page_MEMORY_TYPE)3 #define SH_PAGE_BOOT_SERVICES_DATA (sh_page_MEMORY_TYPE)4 #define SH_PAGE_RUNTIME_SERVICES_CODE (sh_page_MEMORY_TYPE)5 #define SH_PAGE_RUNTIME_SERVICES_DATA (sh_page_MEMORY_TYPE)6 #define SH_PAGE_CONVENTIONAL_MEMORY (sh_page_MEMORY_TYPE)7 #define SH_PAGE_UNUSABLE_MEMORY (sh_page_MEMORY_TYPE)8 #define SH_PAGE_ACPI_RECLAIM_MEMORY (sh_page_MEMORY_TYPE)9 #define SH_PAGE_ACPI_MEMORY_NVS (sh_page_MEMORY_TYPE)10 #define SH_PAGE_MEMORY_MAPPED_IO (sh_page_MEMORY_TYPE)11 #define SH_PAGE_MEMORY_MAPPED_IO_PORT_SPACE (sh_page_MEMORY_TYPE)12 #define SH_PAGE_PAL_CODE (sh_page_MEMORY_TYPE)13 #define SH_PAGE_PERSISTENT_MEMORY (sh_page_MEMORY_TYPE)14 #define SH_PAGE_RESERVED (sh_page_MEMORY_TYPE)15 typedef sh_uint64 sh_page_PHYSICAL_ADDRESS; typedef sh_uint64 sh_page_VIRTUAL_ADDRESS; #define SH_PAGE_NULL_PA (sh_page_PHYSICAL_ADDRESS)0 #define SH_PAGE_NULL_VA (sh_page_VIRTUAL_ADDRESS)0 #define SH_PAGE_PRESENT (1ULL<<0) #define SH_PAGE_TABLE_FLAGS (1ULL<<1) #define SH_PAGE_RW (1ULL<<1) #define SH_PAGE_US (1ULL<<2) #define SH_PAGE_PWT (1ULL<<3) #define SH_PAGE_PCD (1ULL<<4) #define SH_PAGE_ACCESSED (1ULL<<5) #define SH_PAGE_DIRTY (1ULL<<6) #define SH_PAGE_PS (1ULL<<7) #define SH_PAGE_GLOBAL (1ULL<<8) #define SH_PAGE_NX (1ULL<<63) // Memory map entry structure. #pragma pack(1) typedef struct { sh_uint32 type; sh_uint64 physical_start; sh_uint64 pages_count; sh_uint64 attributes; } sh_page_MEMORY_MAP_ENTRY; #pragma pack() // Memory map header structure. #pragma pack(1) typedef struct { sh_uint8 sig_start[8]; sh_uint64 entry_count; sh_uint64 entry_size; sh_uint8 mmap_syntax_version; } sh_page_MEMORY_MAP_HEADER; #pragma pack() // Page table pool structure. #pragma pack(1) typedef struct { sh_page_PHYSICAL_ADDRESS page_table_pa; sh_page_VIRTUAL_ADDRESS page_table_va; sh_uint64 ptp_alloc_bitmap[SH_PAGE_PTP_ALLOCATOR_BITMAP_UINT64]; sh_uint64 ptp_pages_count; sh_uint64 ptp_alloc_bitmap_uint64_count; } sh_page_PAGE_TABLE_POOL; #pragma pack() // Memory statistics structure typedef struct { sh_uint64 memory_total_pages; // memory_total is the size of the addressable physical space sh_uint64 memory_total_bytes; sh_uint64 memory_installed_pages; // memory_installed is the sum of the size of all free regions at kernel boot sh_uint64 memory_installed_bytes; sh_uint64 free_pages; sh_uint64 used_pages; double free_ratio; double used_ratio; sh_uint64 largest_free_block; sh_uint64 largest_used_block; sh_uint64 free_blocks_count; sh_uint64 used_blocks_count; sh_uint64 physical_bitmap_size_pages; sh_uint64 physical_bitmap_size_bytes; } sh_page_MEM_STATS; // Load boot PTP VA. Intended for one usage only. SH_STATUS sh_page_load_boot_ptp_va(sh_page_VIRTUAL_ADDRESS pt_pool_va); // Return boot PTP VA. sh_page_VIRTUAL_ADDRESS sh_page_get_boot_ptp_va(); // Copy memory map provided bootloader into dedicated buffer. Intended for one usage only. SH_STATUS sh_page_copy_memory_map(); // Check for memory map signatures and read memory map header. SH_STATUS sh_page_check_memory_map(); // Return the amount of physical memory in pages sh_uint64 sh_page_get_physical_memory_amount_pages(); // Return the amount of physical memory in bytes sh_uint64 sh_page_get_physical_memory_amount_bytes(); // Return the first available physical page in physical bitmap. sh_uint64 sh_page_get_one_page_na(); // Set pages ranges into provided bitmap. SH_STATUS sh_page_set_pages_range_bitmap(sh_uint8 *bitmap,sh_uint64 page_count_in_bitmap,sh_uint64 page_index,sh_uint64 page_count,sh_bool state); // Return the status of a page inside the provided bitmap. static inline sh_bool sh_page_is_allocated(sh_uint8 *bitmap,sh_uint64 page_index) { sh_uint64 byte_index=page_index/8; sh_uint8 bit_index=page_index%8; return (bitmap[byte_index] & (1u<page_table_pa; sh_uint64 size=ptp->ptp_pages_count*4096; if (pa=base+size) return 0; return (sh_uint64 *)(ptp->page_table_va+(pa-base)); } // Map one physical page to VA to provided PTP. SH_STATUS sh_page_map_one_page_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_page_PHYSICAL_ADDRESS pa,sh_uint64 flags); // Return according SH_STATUS if provided VA is mapped inside provided PTP. SH_STATUS sh_page_is_va_mapped_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va); // Return according SH_STATUS if provided VA is mapped inside provided PTP for all the range provided SH_STATUS sh_page_is_va_range_mapped_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_uint64 size_bytes); // Search for an available amount of virtual memory inside provided range with the provided size SH_STATUS sh_page_search_available_va_range(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS range_base,sh_page_VIRTUAL_ADDRESS range_size_bytes,sh_uint64 size_bytes,sh_page_VIRTUAL_ADDRESS *address_found); // Map a range of pages from PA to VA. Both virtual and physic area has to be continuous. VAs availability is checked, not physical pages availability. SH_STATUS sh_page_map_contiguous_pages_range_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_page_PHYSICAL_ADDRESS pa,sh_uint64 flags,sh_uint64 size_bytes); // Search for an available amount of pages inside physical bitmap SH_STATUS sh_page_search_physical_contiguous_block_na(sh_uint64 pages_needed,sh_page_PHYSICAL_ADDRESS *pa); // Allocate the corresponding amount of pages to size_bytes. SH_STATUS sh_page_alloc_contiguous(sh_page_PAGE_TABLE_POOL *ptp,sh_uint64 size_bytes,sh_page_VIRTUAL_ADDRESS* va); // Allocate the corresponding amount of pages to size_bytes. Provide support for custom flags and VA range search. SH_STATUS sh_page_alloc_contiguous_extended(sh_page_PAGE_TABLE_POOL *ptp,sh_uint64 size_bytes,sh_page_VIRTUAL_ADDRESS* va,DEFAULT sh_uint64 flags,DEFAULT sh_page_VIRTUAL_ADDRESS va_range_start,DEFAULT sh_uint64 va_range_size_bytes); // Unmap one page from a PTP, assume VA is mapped. Does not unallocate associed physical page SH_STATUS sh_page_unmap_one_page_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va); // Map a range of pages to VA. Both virtual and physic area has to be continuous. VAs mapping is checked, not physical pages occupation. SH_STATUS sh_page_unmap_contiguous_pages_range_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_uint64 size_bytes); // Convert a VA allocated in a PTP into his equivalent PA by searching inside the PTP SH_STATUS sh_page_ptp_va_to_pa(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_page_PHYSICAL_ADDRESS *pa); // Unalloc one page from a VA. Check if VA is mapped or not. PA is calculted trough searching in PTP SH_STATUS sh_page_unalloc_one_page(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va); // Unalloc a range of virtually contiguous pages. Check if the entire range is allocated before unallocating anything. SH_STATUS sh_page_unalloc_contiguous(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS va,sh_uint64 size_bytes); // Parse memory map, set all non usable pages into physical bitmap and compute available amount of physical memory. Intended for one usage only. SH_STATUS sh_page_analyse_memory_map(sh_page_PAGE_TABLE_POOL *ptp); // Return physical bitmap pointer sh_page_VIRTUAL_ADDRESS sh_page_get_physical_bitmap_ptr(); // Get physical memory statistics SH_STATUS sh_page_get_memory_stats(sh_page_MEM_STATS *mem_stats); #endif