/* * memory.h * * Copyright (C) 2015 Aleksandar Andrejevic * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef _MEMORY_H_ #define _MEMORY_H_ #include #include #include #include #include #include #include #define PAGE_SIZE 4096 #define PAGE_PRESENT (1 << 0) #define PAGE_WRITABLE (1 << 1) #define PAGE_USERMODE (1 << 2) #define PAGE_ACCESSED (1 << 5) #define PAGE_DIRTY (1 << 6) #define PAGE_GLOBAL (1 << 8) #define PAGE_EVICTABLE (1 << 9) #define PAGE_ERROR_PRESENT_FLAG (1 << 0) #define PAGE_ERROR_WRITE_FLAG (1 << 1) #define PAGE_ERROR_USERMODE_FLAG (1 << 2) #define ADDR_TO_PDE(x) ((x) >> 22) #define ADDR_TO_PTE(x) (((x) >> 12) & 0x3FF) #define PAGE_ALIGN(x) ((x) & 0xFFFFF000) #define PAGE_ALIGN_UP(x) (((x) + 0xFFF) & 0xFFFFF000) #define PAGE_OFFSET(x) ((x) & 0x00000FFF) #define PAGE_NUMBER(x) ((x) >> 12) #define KERNEL_AREA_START 0x80000000 #define KERNEL_AREA_END 0xFFFFFFFF #define KERNEL_POOL_START 0x81000000 #define KERNEL_POOL_END 0xBFFFFFFF #define MAPPING_START 0xC8000000 #define MAPPING_END 0xFFFFFFFF #define USER_AREA_START 0x00000000 #define USER_AREA_END 0x7FFFFFFF #define KERNEL_PAGE_START ADDR_TO_PDE(KERNEL_AREA_START) #define KERNEL_PAGE_END ADDR_TO_PDE(KERNEL_AREA_END) #define USER_PAGE_START ADDR_TO_PDE(USER_AREA_START) #define USER_PAGE_END ADDR_TO_PDE(USER_AREA_END) #define PAGEDIR_SELF_ENTRY 768 #define PAGE_DIRECTORY_ADDR ((PAGEDIR_SELF_ENTRY << 22) + (PAGEDIR_SELF_ENTRY << 12)) #define PAGE_TABLE_ADDR (PAGEDIR_SELF_ENTRY << 22) #define INVALID_PAGE ((void*)-1) #define TOTAL_PAGES 1048576 #define MEM_STACK_VIRT_ADDR 0xC0400000 #define MEM_TREE_BLOCKS 0xC0800000 #define TEMPORARY_PAGES 256 #define TEMPORARY_ADDR (0xC8000000 - TEMPORARY_PAGES * PAGE_SIZE) #define EVICTION_THRESHOLD 128 #define INVALID_STORE_NUMBER ((dword_t)-1) #define PAGE_STORE_ENTRY_PRESENT (1 << 31) typedef struct memory_block memory_block_t; typedef struct { uintptr_t phys_addr; uintptr_t ref_count; } page_t; typedef struct { list_entry_t link; void *page_directory; void *pool_address; uintptr_t pool_size; avl_tree_t by_addr_tree; avl_tree_t by_size_tree; lock_t lock; list_entry_t evictable_blocks; list_entry_t *evict_blk_ptr; uintptr_t evict_page_num; memory_stats_t stats; } memory_address_space_t; typedef struct { list_entry_t link; void *physical; uintptr_t offset; } shared_page_t; typedef struct { object_t header; dword_t flags; list_entry_t page_list; size_t size; file_instance_t *file; /* strong reference */ } memory_section_t; struct memory_block { avl_node_t by_addr_node; avl_node_t by_size_node; list_entry_t evict_link; uintptr_t address; size_t size; dword_t flags; memory_address_space_t *address_space; memory_section_t *section; qword_t section_offset; }; typedef struct { list_entry_t link; dword_t num_entries; dword_t max_entries; handle_t file_handle; dword_t *bitmap; list_entry_t entry_list; } page_store_t; typedef struct { list_entry_t link; void *address; memory_address_space_t *address_space; dword_t number; void *physical; } page_store_entry_t; typedef enum { PAGE_ERROR_NOTPRESENT, PAGE_ERROR_READONLY, PAGE_ERROR_UNPRIVILEGED } page_error_t; void set_page_directory(void *phys_addr); void *get_page_directory(); void *get_physical_address(void *virtual); dword_t map_memory_internal(void *physical, void *virtual, size_t size, dword_t page_flags); void unmap_memory_internal(void *virtual, size_t size); dword_t read_physical(void *physical, void *buffer, size_t size); dword_t write_physical(void *physical, void *buffer, size_t size); dword_t map_memory_in_address_space(memory_address_space_t *address_space, void *physical, void **virtual, uintptr_t size, dword_t block_flags); dword_t unmap_memory_in_address_space(memory_address_space_t *address_space, void *virtual); dword_t pin_memory(const void *virtual, void **pinned, size_t size, bool_t lock_contents); dword_t map_memory(void *physical, void **virtual, size_t size, dword_t page_flags); dword_t unmap_memory(void *virtual); dword_t alloc_memory_in_address_space( memory_address_space_t *address_space, void **address, size_t size, dword_t block_flags, memory_section_t *section, qword_t section_offset); dword_t free_memory_in_address_space(memory_address_space_t *address_space, void *address); dword_t commit_pages(void *address, size_t size); dword_t uncommit_pages(void *address, size_t size); void *alloc_pool(void *address, size_t size, dword_t block_flags); void free_pool(void *address); dword_t create_address_space(void *base_address, dword_t page_count, memory_address_space_t *mem_space); dword_t clone_address_space(memory_address_space_t *original, memory_address_space_t *clone); void bump_address_space(memory_address_space_t *mem_space); void delete_address_space(memory_address_space_t *mem_space); bool_t memory_fault_handler(void *address, registers_t *regs); void memory_init(multiboot_tag_mmap_t *mmap, uintptr_t lowest_physical); void memory_cleanup(object_t *obj); #endif