Commit 03bcbc44d81b4c9c5d97208f0759abf4c78fc779
- Diff rendering mode:
- inline
- side by side
kernel/arch/x86/paging.cc
(36 / 26)
|   | |||
| 9 | 9 | ||
| 10 | 10 | using namespace std; | |
| 11 | 11 | ||
| 12 | // Macros used in the bitset algorithms. | ||
| 13 | #define INDEX_FROM_BIT(a) (a/(8*4)) | ||
| 14 | #define OFFSET_FROM_BIT(a) (a%(8*4)) | ||
| 15 | |||
| 16 | 12 | // Placement address and kernel heap aredefined in src/mm/kheap.c | |
| 17 | 13 | extern uintptr placement_address; | |
| 18 | 14 | extern heap::heap * kheap; | |
| … | … | ||
| 26 | 26 | uintptr * frames; | |
| 27 | 27 | u32int n_frames; | |
| 28 | 28 | ||
| 29 | // Inline functions used in the bitset algorithms. | ||
| 30 | template<typename T> | ||
| 31 | inline uintptr index_from_bit(const T& a) | ||
| 32 | { | ||
| 33 | return a / (8 * 4); | ||
| 34 | } | ||
| 35 | |||
| 36 | template<typename T> | ||
| 37 | inline uintptr offset_from_bit(const T& a) | ||
| 38 | { | ||
| 39 | return a % (8 * 4); | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
| 29 | 43 | // Paging function prototypes | |
| 30 | 44 | void set_frame(uintptr address); | |
| 31 | 45 | void clear_frame(uintptr address); | |
| … | … | ||
| 57 | 57 | ||
| 58 | 58 | // Work out the number of frames we can fit in our memory, allocate | |
| 59 | 59 | // space for them, and then clear that memory | |
| 60 | n_frames = memory_end / PAGE_SIZE; | ||
| 61 | frames = (uintptr *) kmalloc(INDEX_FROM_BIT(n_frames)); | ||
| 62 | memset(frames, 0, INDEX_FROM_BIT(n_frames)); | ||
| 60 | n_frames = memory_end / PageSize; | ||
| 61 | frames = (uintptr *) kmalloc(index_from_bit(n_frames)); | ||
| 62 | memset(frames, 0, index_from_bit(n_frames)); | ||
| 63 | 63 | ||
| 64 | 64 | // Make a page directory for the kernel, and set its physical address | |
| 65 | 65 | kernel_directory = (page_directory_t *) kmalloc(sizeof(page_directory_t), true); | |
| … | … | ||
| 73 | 73 | // yet because they have to be indentity mapped first | |
| 74 | 74 | u32int i; | |
| 75 | 75 | ||
| 76 | for(i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += PAGE_SIZE) | ||
| 76 | for(i = KHeapStart; i < KHeapStart + KHeapInitialSize; i += PageSize) | ||
| 77 | 77 | { | |
| 78 | 78 | get_page(i, true, kernel_directory); | |
| 79 | 79 | } | |
| … | … | ||
| 83 | 83 | // enabled. We loop and change the placement address before calling kmalloc() | |
| 84 | 84 | i = 0; | |
| 85 | 85 | ||
| 86 | while(i < placement_address + PAGE_SIZE) | ||
| 86 | while(i < placement_address + PageSize) | ||
| 87 | 87 | { | |
| 88 | 88 | // Set the kernel code as readable but not writable from the userspace | |
| 89 | 89 | allocate_frame(get_page(i, true, kernel_directory), true, false); | |
| 90 | 90 | ||
| 91 | i += PAGE_SIZE; | ||
| 91 | i += PageSize; | ||
| 92 | 92 | } | |
| 93 | 93 | ||
| 94 | 94 | // Allocate the pages for the kernel heap (mapped earlier) | |
| 95 | for(i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += PAGE_SIZE) | ||
| 95 | for(i = KHeapStart; i < KHeapStart + KHeapInitialSize; i += PageSize) | ||
| 96 | 96 | { | |
| 97 | 97 | allocate_frame(get_page(i, true, kernel_directory), true, false); | |
| 98 | 98 | } | |
| … | … | ||
| 104 | 104 | switch_directory(kernel_directory); | |
| 105 | 105 | ||
| 106 | 106 | // Now we need to initialise a heap for the kernel to use | |
| 107 | kheap = heap::create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, false, false); | ||
| 107 | kheap = heap::create_heap(KHeapStart, KHeapStart + KHeapInitialSize, 0xCFFFF000, false, false); | ||
| 108 | 108 | ||
| 109 | 109 | // Clone the kernel directory and switch to the clone | |
| 110 | 110 | current_directory = clone_directory(kernel_directory); | |
| … | … | ||
| 117 | 117 | // Set a frame in the bitset | |
| 118 | 118 | void set_frame(uintptr address) | |
| 119 | 119 | { | |
| 120 | u32int frame = address / PAGE_SIZE; | ||
| 121 | u32int index = INDEX_FROM_BIT(frame); | ||
| 122 | u32int offset = OFFSET_FROM_BIT(frame); | ||
| 120 | uintptr frame = address / PageSize; | ||
| 121 | uintptr index = index_from_bit(frame); | ||
| 122 | uintptr offset = offset_from_bit(frame); | ||
| 123 | 123 | ||
| 124 | 124 | frames[index] |= (0x1 << offset); | |
| 125 | 125 | } | |
| … | … | ||
| 127 | 127 | // Clear a frame in the bitset | |
| 128 | 128 | void clear_frame(uintptr address) | |
| 129 | 129 | { | |
| 130 | u32int frame = address / PAGE_SIZE; | ||
| 131 | u32int index = INDEX_FROM_BIT(frame); | ||
| 132 | u32int offset = OFFSET_FROM_BIT(frame); | ||
| 130 | uintptr frame = address / PageSize; | ||
| 131 | uintptr index = index_from_bit(frame); | ||
| 132 | uintptr offset = offset_from_bit(frame); | ||
| 133 | 133 | ||
| 134 | 134 | frames[index] &= ~(0x1 << offset); | |
| 135 | 135 | } | |
| … | … | ||
| 137 | 137 | // Test to see if a frame exists | |
| 138 | 138 | uintptr test_frame(uintptr address) | |
| 139 | 139 | { | |
| 140 | u32int frame = address / PAGE_SIZE; | ||
| 141 | u32int index = INDEX_FROM_BIT(frame); | ||
| 142 | u32int offset = OFFSET_FROM_BIT(frame); | ||
| 140 | uintptr frame = address / PageSize; | ||
| 141 | uintptr index = index_from_bit(frame); | ||
| 142 | uintptr offset = offset_from_bit(frame); | ||
| 143 | 143 | ||
| 144 | 144 | return (frames[index] & (0x1 << offset)); | |
| 145 | 145 | } | |
| … | … | ||
| 147 | 147 | // Find the first available free frame | |
| 148 | 148 | uintptr first_frame() | |
| 149 | 149 | { | |
| 150 | for(u32int i = 0; i < INDEX_FROM_BIT(n_frames); i++) | ||
| 150 | for(u32int i = 0; i < index_from_bit(n_frames); i++) | ||
| 151 | 151 | { | |
| 152 | 152 | if(frames[i] != 0xFFFFFFFF) // No free frames | |
| 153 | 153 | { | |
| … | … | ||
| 182 | 182 | panic("No free frames"); | |
| 183 | 183 | } | |
| 184 | 184 | ||
| 185 | set_frame(index * PAGE_SIZE); | ||
| 185 | set_frame(index * PageSize); | ||
| 186 | 186 | page->present = 1; // Mark as present | |
| 187 | 187 | page->rw = (writable)?1:0; // Is the page writable | |
| 188 | 188 | page->user = (kernel)?0:1; // Is this a user mode page? | |
| … | … | ||
| 231 | 231 | page_t * get_page(uintptr address, bool make, page_directory_t * dir) | |
| 232 | 232 | { | |
| 233 | 233 | // Change the address into an index | |
| 234 | address /= PAGE_SIZE; | ||
| 234 | address /= PageSize; | ||
| 235 | 235 | ||
| 236 | 236 | // Find the page table containing the address | |
| 237 | 237 | u32int table_index = address / 1024; | |
| … | … | ||
| 250 | 250 | dir->tables[table_index] = (page_table_t *)kmalloc(sizeof(page_table_t), &temp, true); | |
| 251 | 251 | ||
| 252 | 252 | // Clear the memory space allocated for the page | |
| 253 | memset(dir->tables[table_index], 0, PAGE_SIZE); | ||
| 253 | memset(dir->tables[table_index], 0, PageSize); | ||
| 254 | 254 | ||
| 255 | 255 | // Set the page as present, writable and user mode | |
| 256 | 256 | dir->tablesPhysical[table_index] = temp | 0x7; | |
| … | … | ||
| 330 | 330 | if(src->pages[i].dirty == 1) table->pages[i].dirty = 1; | |
| 331 | 331 | ||
| 332 | 332 | // Physically copy the data accross | |
| 333 | copy_page_physical(src->pages[i].frame * PAGE_SIZE, table->pages[i].frame * PAGE_SIZE); | ||
| 333 | copy_page_physical(src->pages[i].frame * PageSize, table->pages[i].frame * PageSize); | ||
| 334 | 334 | } | |
| 335 | 335 | ||
| 336 | 336 | return table; |
kernel/arch/x86/paging.h
(1 / 1)
|   | |||
| 5 | 5 | #include "mm/kheap.h" | |
| 6 | 6 | #include "isr.h" | |
| 7 | 7 | ||
| 8 | #define PAGE_SIZE 0x1000 | ||
| 8 | const size_t PageSize = 0x1000; | ||
| 9 | 9 | ||
| 10 | 10 | namespace paging | |
| 11 | 11 | { |
kernel/mm/kheap.cc
(34 / 34)
|   | |||
| 36 | 36 | heap * temp = new heap; | |
| 37 | 37 | ||
| 38 | 38 | // Make sure that the start and end addresses are page aligned | |
| 39 | ASSERT(start % PAGE_SIZE == 0); | ||
| 40 | ASSERT(end % PAGE_SIZE == 0); | ||
| 39 | ASSERT(start % PageSize == 0); | ||
| 40 | ASSERT(end % PageSize == 0); | ||
| 41 | 41 | ||
| 42 | 42 | // Initialise our index | |
| 43 | temp->heap_index = create_index((uintptr *)start, HEAP_INDEX_SIZE); | ||
| 43 | temp->heap_index = create_index((uintptr *)start, IndexSize); | ||
| 44 | 44 | ||
| 45 | 45 | // Move the start address past the index | |
| 46 | start += sizeof(uintptr *) * HEAP_INDEX_SIZE; | ||
| 46 | start += sizeof(uintptr *) * IndexSize; | ||
| 47 | 47 | ||
| 48 | 48 | // Make sure the start address is page aligned | |
| 49 | 49 | if ((start & 0xFFFFF000) != 0) | |
| 50 | 50 | { | |
| 51 | 51 | start &= 0xFFFFF000; | |
| 52 | start += PAGE_SIZE; | ||
| 52 | start += PageSize; | ||
| 53 | 53 | } | |
| 54 | 54 | ||
| 55 | 55 | // Fill the structure with the start, end and max addresses | |
| … | … | ||
| 62 | 62 | // The heap should be just one large hole to start off | |
| 63 | 63 | header * hole = (header *) start; | |
| 64 | 64 | hole->size = end - start; | |
| 65 | hole->magic = HEAP_MAGIC; | ||
| 65 | hole->magic = Magic; | ||
| 66 | 66 | hole->is_hole = true; | |
| 67 | 67 | ||
| 68 | 68 | // Insert this hole into the index | |
| … | … | ||
| 162 | 162 | ||
| 163 | 163 | if(((location + sizeof(header)) & 0xFFFFF000) != 0) | |
| 164 | 164 | { | |
| 165 | offset = PAGE_SIZE - (location + sizeof(header)) % PAGE_SIZE; | ||
| 165 | offset = PageSize - (location + sizeof(header)) % PageSize; | ||
| 166 | 166 | } | |
| 167 | 167 | ||
| 168 | 168 | s32int hole_size = (s32int)head->size - offset; | |
| … | … | ||
| 206 | 206 | if((new_size & 0xFFFFF000) != 0) | |
| 207 | 207 | { | |
| 208 | 208 | new_size &= 0xFFFFF000; | |
| 209 | new_size += PAGE_SIZE; | ||
| 209 | new_size += PageSize; | ||
| 210 | 210 | } | |
| 211 | 211 | ||
| 212 | 212 | // Make sure we aren't trying to expand the heap too much | |
| … | … | ||
| 220 | 220 | { | |
| 221 | 221 | paging::allocate_frame(paging::get_page(heap->start_address + i, true, kernel_directory), | |
| 222 | 222 | heap->supervisor, heap->readonly); | |
| 223 | i += PAGE_SIZE; | ||
| 223 | i += PageSize; | ||
| 224 | 224 | } | |
| 225 | 225 | ||
| 226 | 226 | heap->end_address = heap->start_address + new_size; | |
| … | … | ||
| 233 | 233 | ASSERT(new_size < heap->end_address - heap->start_address); | |
| 234 | 234 | ||
| 235 | 235 | // Find the nearest following page boundary | |
| 236 | if(new_size & PAGE_SIZE) | ||
| 236 | if(new_size & PageSize) | ||
| 237 | 237 | { | |
| 238 | new_size &= PAGE_SIZE; | ||
| 239 | new_size += PAGE_SIZE; | ||
| 238 | new_size &= PageSize; | ||
| 239 | new_size += PageSize; | ||
| 240 | 240 | } | |
| 241 | 241 | ||
| 242 | 242 | // We can only contract the heap as small as its minimum size | |
| 243 | if(new_size < HEAP_MIN_SIZE) | ||
| 243 | if(new_size < MinSize) | ||
| 244 | 244 | { | |
| 245 | new_size = HEAP_MIN_SIZE; | ||
| 245 | new_size = MinSize; | ||
| 246 | 246 | } | |
| 247 | 247 | ||
| 248 | 248 | // Calculate the current heap size | |
| 249 | 249 | size_t old_size = heap->end_address - heap->start_address; | |
| 250 | 250 | ||
| 251 | size_t i = old_size - PAGE_SIZE; | ||
| 251 | size_t i = old_size - PageSize; | ||
| 252 | 252 | ||
| 253 | 253 | while(new_size < i) | |
| 254 | 254 | { | |
| 255 | 255 | paging::free_frame(paging::get_page(heap->start_address + i, false, kernel_directory)); | |
| 256 | i -= PAGE_SIZE; | ||
| 256 | i -= PageSize; | ||
| 257 | 257 | } | |
| 258 | 258 | ||
| 259 | 259 | // Set the new end address of the contracted heap | |
| … | … | ||
| 272 | 272 | if(phys != NULL) | |
| 273 | 273 | { | |
| 274 | 274 | paging::page_t * page = paging::get_page((uintptr)address, false, kernel_directory); | |
| 275 | *phys = (page->frame * PAGE_SIZE) + ((uintptr)address & 0xFFF); | ||
| 275 | *phys = (page->frame * PageSize) + ((uintptr)address & 0xFFF); | ||
| 276 | 276 | } | |
| 277 | 277 | ||
| 278 | 278 | return (uintptr)address; | |
| … | … | ||
| 289 | 289 | { | |
| 290 | 290 | // If it's not aligned... | |
| 291 | 291 | placement_address &= 0xFFFFF000; | |
| 292 | placement_address += PAGE_SIZE; | ||
| 292 | placement_address += PageSize; | ||
| 293 | 293 | } | |
| 294 | 294 | ||
| 295 | 295 | if(phys != NULL) | |
| … | … | ||
| 357 | 357 | { | |
| 358 | 358 | // We didn't find any, so we need to add a new header | |
| 359 | 359 | header * head = (header *) old_end_address; | |
| 360 | head->magic = HEAP_MAGIC; | ||
| 360 | head->magic = Magic; | ||
| 361 | 361 | head->size = new_length - old_length; | |
| 362 | 362 | head->is_hole = true; | |
| 363 | 363 | footer * foot = (footer *) (old_end_address + head->size - sizeof(footer)); | |
| 364 | foot->magic = HEAP_MAGIC; | ||
| 364 | foot->magic = Magic; | ||
| 365 | 365 | foot->head = head; | |
| 366 | 366 | ||
| 367 | 367 | // Insert this hole into the index | |
| … | … | ||
| 376 | 376 | // Rewrite the footer | |
| 377 | 377 | footer * foot = (footer *) ((uintptr)head + head->size - sizeof(footer)); | |
| 378 | 378 | foot->head = head; | |
| 379 | foot->magic = HEAP_MAGIC; | ||
| 379 | foot->magic = Magic; | ||
| 380 | 380 | } | |
| 381 | 381 | ||
| 382 | 382 | // Now we have enough space. Run this function again and return the result | |
| … | … | ||
| 404 | 404 | // already aligned. Also, make a hole in front of the block to not waste space | |
| 405 | 405 | if(page_align && (original_hole_pos & 0xFFFFF000)) | |
| 406 | 406 | { | |
| 407 | uintptr new_location = original_hole_pos + PAGE_SIZE - (original_hole_pos & 0xFFF) - sizeof(header); | ||
| 407 | uintptr new_location = original_hole_pos + PageSize - (original_hole_pos & 0xFFF) - sizeof(header); | ||
| 408 | 408 | ||
| 409 | 409 | // The new hole's header | |
| 410 | 410 | header * hole_header = (header *) original_hole_pos; | |
| 411 | hole_header->size = PAGE_SIZE - (original_hole_pos & 0xFFF) - sizeof(header); | ||
| 412 | hole_header->magic = HEAP_MAGIC; | ||
| 411 | hole_header->size = PageSize - (original_hole_pos & 0xFFF) - sizeof(header); | ||
| 412 | hole_header->magic = Magic; | ||
| 413 | 413 | hole_header->is_hole = true; | |
| 414 | 414 | ||
| 415 | 415 | // A matching footer before our allocated block | |
| 416 | 416 | footer * hole_footer = (footer *) ((uintptr)new_location - sizeof(footer)); | |
| 417 | hole_footer->magic = HEAP_MAGIC; | ||
| 417 | hole_footer->magic = Magic; | ||
| 418 | 418 | hole_footer->head = hole_header; | |
| 419 | 419 | original_hole_pos = new_location; | |
| 420 | 420 | original_hole_size = original_hole_size - hole_header->size; | |
| … | … | ||
| 427 | 427 | ||
| 428 | 428 | // Overwrite the hole's header | |
| 429 | 429 | header * block_header = (header *) original_hole_pos; | |
| 430 | block_header->magic = HEAP_MAGIC; | ||
| 430 | block_header->magic = Magic; | ||
| 431 | 431 | block_header->is_hole = false; | |
| 432 | 432 | block_header->size = new_size; | |
| 433 | 433 | ||
| 434 | 434 | // And the footer | |
| 435 | 435 | footer * block_footer = (footer *) (original_hole_pos + sizeof(header) + size); | |
| 436 | block_footer->magic = HEAP_MAGIC; | ||
| 436 | block_footer->magic = Magic; | ||
| 437 | 437 | block_footer->head = block_header; | |
| 438 | 438 | ||
| 439 | 439 | // If we have the space, we should make another hole after the block we just allocated | |
| 440 | 440 | if(original_hole_size - new_size > 0) | |
| 441 | 441 | { | |
| 442 | 442 | header * new_hole_header = (header *) (original_hole_pos + sizeof(header) + size + sizeof(footer)); | |
| 443 | new_hole_header->magic = HEAP_MAGIC; | ||
| 443 | new_hole_header->magic = Magic; | ||
| 444 | 444 | new_hole_header->size = original_hole_size - new_size; | |
| 445 | 445 | ||
| 446 | 446 | // The new hole's matching footer | |
| … | … | ||
| 449 | 449 | ||
| 450 | 450 | if((uintptr) new_hole_footer < heap->end_address) | |
| 451 | 451 | { | |
| 452 | new_hole_footer->magic = HEAP_MAGIC; | ||
| 452 | new_hole_footer->magic = Magic; | ||
| 453 | 453 | new_hole_footer->head = new_hole_header; | |
| 454 | 454 | } | |
| 455 | 455 | ||
| … | … | ||
| 474 | 474 | ||
| 475 | 475 | // Sanity checks, to make sure that neither the header nor footer have been corrupted | |
| 476 | 476 | // or overwritten | |
| 477 | ASSERT(head->magic == HEAP_MAGIC); | ||
| 478 | ASSERT(foot->magic == HEAP_MAGIC); | ||
| 477 | ASSERT(head->magic == Magic); | ||
| 478 | ASSERT(foot->magic == Magic); | ||
| 479 | 479 | ||
| 480 | 480 | // Mark this block of memory as a hole | |
| 481 | 481 | head->is_hole = true; | |
| … | … | ||
| 488 | 488 | footer * test_footer = (footer *) ((uintptr)head - sizeof(footer)); | |
| 489 | 489 | ||
| 490 | 490 | // Check if this is a footer, and see if it is a hole | |
| 491 | if(test_footer->magic == HEAP_MAGIC && test_footer->head->is_hole) | ||
| 491 | if(test_footer->magic == Magic && test_footer->head->is_hole) | ||
| 492 | 492 | { | |
| 493 | 493 | // Remember the current memory block's size | |
| 494 | 494 | u32int cache_size = head->size; | |
| … | … | ||
| 509 | 509 | // If the next header in the heap is a hole, unify this and the next hole | |
| 510 | 510 | header * test_header = (header *) ((uintptr)foot + sizeof(footer)); | |
| 511 | 511 | ||
| 512 | if(test_header->magic == HEAP_MAGIC && test_header->is_hole) | ||
| 512 | if(test_header->magic == Magic && test_header->is_hole) | ||
| 513 | 513 | { | |
| 514 | 514 | // Increase the hole's header | |
| 515 | 515 | head->size += test_header->size; | |
| … | … | ||
| 549 | 549 | ||
| 550 | 550 | // Get the footer's address | |
| 551 | 551 | foot = (footer *) ((uintptr)head + head->size - sizeof(footer)); | |
| 552 | foot->magic = HEAP_MAGIC; | ||
| 552 | foot->magic = Magic; | ||
| 553 | 553 | ||
| 554 | 554 | // Point the footer's head var to our header | |
| 555 | 555 | foot->head = head; |
kernel/mm/kheap.h
(8 / 5)
|   | |||
| 3 | 3 | ||
| 4 | 4 | #include "common.h" | |
| 5 | 5 | ||
| 6 | #define KHEAP_START 0xC0000000 | ||
| 7 | #define KHEAP_INITIAL_SIZE 0x100000 | ||
| 8 | #define HEAP_INDEX_SIZE 0x20000 | ||
| 9 | #define HEAP_MAGIC 0x123890AB | ||
| 10 | #define HEAP_MIN_SIZE 0x70000 | ||
| 6 | // Kheap constants | ||
| 7 | const uintptr KHeapStart = 0xC0000000; | ||
| 8 | const size_t KHeapInitialSize = 0x100000; | ||
| 11 | 9 | ||
| 12 | 10 | namespace heap | |
| 13 | 11 | { | |
| 12 | // General heap constants | ||
| 13 | const size_t IndexSize = 0x20000; | ||
| 14 | const u32int Magic = 0x123890AB; | ||
| 15 | const size_t MinSize = 0x70000; | ||
| 16 | |||
| 14 | 17 | typedef struct | |
| 15 | 18 | { | |
| 16 | 19 | uintptr ** array; |
kernel/process/task.cc
(1 / 1)
|   | |||
| 58 | 58 | void move_stack(void * new_stack_start, size_t size) | |
| 59 | 59 | { | |
| 60 | 60 | // Allocate space for the new stack | |
| 61 | for(uintptr i = (uintptr)new_stack_start; i >= ((uintptr)new_stack_start - size); i -= PAGE_SIZE) | ||
| 61 | for(uintptr i = (uintptr)new_stack_start; i >= ((uintptr)new_stack_start - size); i -= PageSize) | ||
| 62 | 62 | { | |
| 63 | 63 | // The stack should be user mode and writable | |
| 64 | 64 | paging::allocate_frame(paging::get_page(i, true, current_directory), false, true); |

