Reimplement AVL trees
[monolithium.git] / kernel / include / memory.h
1 /*
2  * memory.h
3  *
4  * Copyright (C) 2015 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifndef _MEMORY_H_
21 #define _MEMORY_H_
22
23 #include <common.h>
24 #include <interrupt.h>
25 #include <boot/multiboot.h>
26 #include <object.h>
27 #include <filesystem.h>
28 #include <sdk/avltree.h>
29 #include <sdk/memory.h>
30
31 #define PAGE_SIZE      4096
32 #define PAGE_PRESENT   (1 << 0)
33 #define PAGE_WRITABLE  (1 << 1)
34 #define PAGE_USERMODE  (1 << 2)
35 #define PAGE_ACCESSED  (1 << 5)
36 #define PAGE_DIRTY     (1 << 6)
37 #define PAGE_GLOBAL    (1 << 8)
38 #define PAGE_EVICTABLE (1 << 9)
39
40 #define PAGE_ERROR_PRESENT_FLAG  (1 << 0)
41 #define PAGE_ERROR_WRITE_FLAG    (1 << 1)
42 #define PAGE_ERROR_USERMODE_FLAG (1 << 2)
43
44 #define ADDR_TO_PDE(x)   ((x) >> 22)
45 #define ADDR_TO_PTE(x)   (((x) >> 12) & 0x3FF)
46 #define PAGE_ALIGN(x)    ((x) & 0xFFFFF000)
47 #define PAGE_ALIGN_UP(x) (((x) + 0xFFF) & 0xFFFFF000)
48 #define PAGE_OFFSET(x)   ((x) & 0x00000FFF)
49 #define PAGE_NUMBER(x)   ((x) >> 12)
50
51 #define KERNEL_AREA_START 0x80000000
52 #define KERNEL_AREA_END   0xFFFFFFFF
53 #define KERNEL_POOL_START 0x81000000
54 #define KERNEL_POOL_END   0xBFFFFFFF
55 #define MAPPING_START     0xC8000000
56 #define MAPPING_END       0xFFFFFFFF
57 #define USER_AREA_START   0x00000000
58 #define USER_AREA_END     0x7FFFFFFF
59 #define KERNEL_PAGE_START ADDR_TO_PDE(KERNEL_AREA_START)
60 #define KERNEL_PAGE_END   ADDR_TO_PDE(KERNEL_AREA_END)
61 #define USER_PAGE_START   ADDR_TO_PDE(USER_AREA_START)
62 #define USER_PAGE_END     ADDR_TO_PDE(USER_AREA_END)
63
64 #define PAGEDIR_SELF_ENTRY  768
65 #define PAGE_DIRECTORY_ADDR ((PAGEDIR_SELF_ENTRY << 22) + (PAGEDIR_SELF_ENTRY << 12))
66 #define PAGE_TABLE_ADDR     (PAGEDIR_SELF_ENTRY << 22)
67
68 #define INVALID_PAGE        ((void*)-1)
69 #define TOTAL_PAGES         1048576
70 #define MEM_FIRST_PHYS_ADDR 0x400000
71 #define MEM_STACK_VIRT_ADDR 0xC0400000
72 #define MEM_TREE_BLOCKS     0xC0800000
73 #define TEMPORARY_PAGES     256
74 #define TEMPORARY_ADDR      (0xC8000000 - TEMPORARY_PAGES * PAGE_SIZE)
75 #define EVICTION_THRESHOLD  128
76
77 #define INVALID_STORE_NUMBER        ((dword_t)-1)
78 #define PAGE_STORE_ENTRY_PRESENT    (1 << 31)
79
80 typedef struct memory_block memory_block_t;
81
82 typedef struct
83 {
84     uintptr_t phys_addr;
85     uintptr_t ref_count;
86 } page_t;
87
88 typedef struct
89 {
90     list_entry_t link;
91     void *page_directory;
92     void *pool_address;
93     uintptr_t pool_size;
94     avl_tree_t by_addr_tree;
95     avl_tree_t by_size_tree;
96     resource_t resource;
97     list_entry_t evictable_blocks;
98     list_entry_t *evict_blk_ptr;
99     uintptr_t evict_page_num;
100     memory_stats_t stats;
101 } memory_address_space_t;
102
103 typedef struct
104 {
105     list_entry_t link;
106     void *physical;
107     uintptr_t offset;
108 } shared_page_t;
109
110 typedef struct
111 {
112     object_t header;
113     dword_t flags;
114     list_entry_t page_list;
115     size_t size;
116     file_instance_t *file; /* strong reference */
117 } memory_section_t;
118
119 struct memory_block
120 {
121     avl_node_t by_addr_node;
122     avl_node_t by_size_node;
123     list_entry_t evict_link;
124     uintptr_t address;
125     size_t size;
126     dword_t flags;
127     memory_address_space_t *address_space;
128     memory_section_t *section;
129     qword_t section_offset;
130 };
131
132 typedef struct
133 {
134     list_entry_t link;
135     dword_t num_entries;
136     dword_t max_entries;
137     handle_t file_handle;
138     dword_t *bitmap;
139     list_entry_t entry_list;
140 } page_store_t;
141
142 typedef struct
143 {
144     list_entry_t link;
145     void *address;
146     memory_address_space_t *address_space;
147     dword_t number;
148     void *physical;
149 } page_store_entry_t;
150
151 typedef enum
152 {
153     PAGE_ERROR_NOTPRESENT,
154     PAGE_ERROR_READONLY,
155     PAGE_ERROR_UNPRIVILEGED
156 } page_error_t;
157
158 void set_page_directory(void *phys_addr);
159 void *get_page_directory();
160 void *get_physical_address(void *virtual);
161 dword_t map_memory_internal(void *physical, void *virtual, size_t size, dword_t page_flags);
162 void unmap_memory_internal(void *virtual, size_t size);
163 dword_t read_physical(void *physical, void *buffer, size_t size);
164 dword_t write_physical(void *physical, void *buffer, size_t size);
165 dword_t map_memory_in_address_space(memory_address_space_t *address_space,
166                                     void *physical,
167                                     void **virtual,
168                                     uintptr_t size,
169                                     dword_t block_flags);
170 dword_t unmap_memory_in_address_space(memory_address_space_t *address_space, void *virtual);
171 dword_t pin_memory(const void *virtual, void **pinned, size_t size, bool_t lock_contents);
172 dword_t map_memory(void *physical, void **virtual, size_t size, dword_t page_flags);
173 dword_t unmap_memory(void *virtual);
174 dword_t alloc_memory_in_address_space(
175     memory_address_space_t *address_space,
176     void **address,
177     size_t size,
178     dword_t block_flags,
179     memory_section_t *section,
180     qword_t section_offset);
181 dword_t free_memory_in_address_space(memory_address_space_t *address_space, void *address);
182 dword_t commit_pages(void *address, size_t size);
183 dword_t uncommit_pages(void *address, size_t size);
184 void *alloc_pool(void *address, size_t size, dword_t block_flags);
185 void free_pool(void *address);
186 dword_t create_address_space(void *base_address, dword_t page_count, memory_address_space_t *mem_space);
187 dword_t clone_address_space(memory_address_space_t *original, memory_address_space_t *clone);
188 void bump_address_space(memory_address_space_t *mem_space);
189 void delete_address_space(memory_address_space_t *mem_space);
190 bool_t memory_fault_handler(void *address, registers_t *regs);
191 void memory_init(multiboot_mmap_t *mmap_addr, dword_t mmap_length);
192 void memory_cleanup(object_t *obj);
193
194 #endif