Improved kernel memory usage

Moved base linear address to 0xFF800000
Kernel only reserves the page frames it actually needs
Memory for multiboot2 headers is freed
Video memory and APIC registers are dynamically mapped into linear addresses
This commit is contained in:
2021-04-17 03:45:45 -05:00
parent b141582f40
commit 961139df9e
10 changed files with 91 additions and 57 deletions

View File

@@ -72,4 +72,4 @@ size_t free_page_count(struct page_stack_t *stack);
* @param stack * @param stack
* @param map * @param map
*/ */
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size); int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map);

View File

@@ -2,6 +2,8 @@
#include <stdarg.h> #include <stdarg.h>
int initialize_screen();
int putchar(int c); int putchar(int c);
int puts(const char *str); int puts(const char *str);

View File

@@ -1,4 +1,6 @@
#include "pageallocator.h" #include "pageallocator.h"
#include "mmgr.h"
#include "allocator.h"
#include "types/status.h" #include "types/status.h"
physaddr_t reserve_page(struct page_stack_t *stack) physaddr_t reserve_page(struct page_stack_t *stack)
@@ -15,12 +17,25 @@ physaddr_t reserve_page(struct page_stack_t *stack)
int free_page(struct page_stack_t *stack, physaddr_t location) int free_page(struct page_stack_t *stack, physaddr_t location)
{ {
void *new_limit;
if(stack->stack_pointer > stack->limit_pointer) if(stack->stack_pointer > stack->limit_pointer)
{ {
stack->stack_pointer--; stack->stack_pointer--;
*stack->stack_pointer = location; *stack->stack_pointer = location;
return S_OK; return S_OK;
} }
else if((new_limit = allocate_from_top(page_size)) != NULL)
{
switch(map_page(stack, new_limit, location, PAGE_RW))
{
case S_OUT_OF_MEMORY:
return S_OUT_OF_MEMORY;
case S_OUT_OF_BOUNDS:
return S_OUT_OF_BOUNDS;
case S_OK:
stack->limit_pointer = new_limit;
}
}
return S_OUT_OF_MEMORY; return S_OUT_OF_MEMORY;
} }
@@ -29,7 +44,7 @@ size_t free_page_count(struct page_stack_t *stack)
return stack->base_pointer - stack->stack_pointer; return stack->base_pointer - stack->stack_pointer;
} }
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size) int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map)
{ {
stack->total_pages = 0; stack->total_pages = 0;
for(int i = 0; i < map->size; i++) for(int i = 0; i < map->size; i++)

View File

@@ -1,4 +1,5 @@
#include "mmgr.h" #include "mmgr.h"
#include "allocator.h"
#include "apic.h" #include "apic.h"
#include "msr.h" #include "msr.h"
#include "stdio.h" #include "stdio.h"
@@ -33,9 +34,9 @@ void apic_enable(struct page_stact_t *page_stack)
); );
struct msr_apic_base_t msr; struct msr_apic_base_t msr;
read_msr(MSR_APIC_BASE, (uint64_t*)&msr); read_msr(MSR_APIC_BASE, (uint64_t*)&msr);
map_page(page_stack, &_kernel_end, msr.apic_base << 12, PAGE_RW); apic_registers = (struct apic_registers_t*)allocate_from_bottom(page_size);
map_page(page_stack, apic_registers, msr.apic_base << 12, PAGE_RW);
printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr));
apic_registers = (struct apic_registers_t*)&_kernel_end;
apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100;
} }

View File

@@ -30,7 +30,7 @@
.set tagEntryType, 3 .set tagEntryType, 3
.set tagEntrySize, 12 .set tagEntrySize, 12
.set tagEntryAddress, _start - (0xFF900000 - 0x100000) .set tagEntryAddress, _start - (0xFF800000 - 0x100000)
.set tagModuleAlignType, 6 .set tagModuleAlignType, 6
.set tagModuleAlignSize, 8 .set tagModuleAlignSize, 8
@@ -109,19 +109,6 @@ _tempIdentityMap:
_tempPgTable: _tempPgTable:
.skip 4096 .skip 4096
_bootCmdLine:
.skip 64
.align 64
.global system_info
system_info:
.skip 16
.align 64
.global memory_map
memory_map:
.skip 16 * 16
.section .text .section .text
.global _start .global _start
.type _start, @function .type _start, @function
@@ -152,6 +139,15 @@ _start:
sub $BASE_DIFF, %eax sub $BASE_DIFF, %eax
push %eax push %eax
# Push ending physical address to map
mov (%ebx), %eax
add %ebx, %eax
push %eax
# Push starting physical address to map
mov $PHYSICAL_BASE, %eax
push %eax
# Load physical address of startPaging() # Load physical address of startPaging()
mov $start_paging, %eax mov $start_paging, %eax
sub $BASE_DIFF, %eax sub $BASE_DIFF, %eax
@@ -173,7 +169,7 @@ _start:
# Change EBX to point to the virtual address of the multiboot info # Change EBX to point to the virtual address of the multiboot info
# If the new pointer is out-of-bounds, error # If the new pointer is out-of-bounds, error
add $0xFF800000, %ebx add $0xFF700000, %ebx
cmp $0xFF800000, %ebx cmp $0xFF800000, %ebx
jl .err jl .err
cmp $0xFFC00000, %ebx cmp $0xFFC00000, %ebx

View File

@@ -2,7 +2,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0xFF900000; . = 0xFF800000;
VIRTUAL_BASE = .; VIRTUAL_BASE = .;
PHYSICAL_BASE = 0x100000; PHYSICAL_BASE = 0x100000;
BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE;
@@ -34,9 +34,8 @@ SECTIONS
BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE);
IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096;
_pageMapLocation = 0xFF800000; _kernel_pstart = PHYSICAL_BASE;
_heapLocation = 0xFFB00000; _kernel_pend = PHYSICAL_BASE + (4096 * IMAGE_SIZE);
_heapSize = 0x100000; _kernel_start = VIRTUAL_BASE;
_kernelStart = VIRTUAL_BASE;
_kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE); _kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE);
} }

View File

@@ -28,6 +28,34 @@ struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000
struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000; struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000;
int start_paging(physaddr_t start, physaddr_t end, uint32_t *directory, uint32_t *table, uint32_t *identity_table)
{
physaddr_t p = start;
size_t count = 0;
while(p < end)
{
uint32_t table_entry = p + 3;
int index = p / page_size;
table[index - start / page_size] = table_entry;
identity_table[index] = table_entry;
p += page_size;
count++;
}
directory[0] = ((uint32_t)identity_table) + 3;
directory[1022] = ((uint32_t)table) + 3;
directory[1023] = ((uint32_t)directory) + 3;
asm("mov %0, %%cr3"
:
: "r"(directory));
asm("mov %%cr0, %%eax \n"
"or $0x80010000, %%eax \n"
"mov %%eax, %%cr0"
:
:
: "eax");
return count;
}
physaddr_t create_address_space(struct page_stack_t *page_stack) physaddr_t create_address_space(struct page_stack_t *page_stack)
{ {
physaddr_t table = reserve_page(page_stack); physaddr_t table = reserve_page(page_stack);

View File

@@ -36,10 +36,6 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
M_UNAVAILABLE); M_UNAVAILABLE);
boot_info->module_count++; boot_info->module_count++;
} }
else
{
printf("WARNING: Too many modules, must skip one.\n");
}
break; break;
case MB_BOOT_COMMAND: case MB_BOOT_COMMAND:
strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str); strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str);

View File

@@ -1,4 +1,6 @@
#include "stdio.h" #include "stdio.h"
#include "mmgr.h"
#include "allocator.h"
#include <stddef.h> #include <stddef.h>
enum vga_color_t { enum vga_color_t {
@@ -28,12 +30,18 @@ struct cell_t
char bg : 4; char bg : 4;
}; };
struct cell_t *screen = (struct cell_t*)0xFF8B8000; struct cell_t *screen = (struct cell_t*)NULL;
size_t cursor = 0; size_t cursor = 0;
const size_t tab_width = 4; const size_t tab_width = 4;
const size_t line_width = 80; const size_t line_width = 80;
int initialize_screen()
{
screen = allocate_from_bottom(page_size);
map_page(NULL, screen, 0x000B8000, PAGE_RW);
}
int putchar(int c) int putchar(int c)
{ {
switch(c) switch(c)

View File

@@ -1,5 +1,7 @@
#include "kernel.h" #include "kernel.h"
#include "pageallocator.h" #include "pageallocator.h"
#include "allocator.h"
#include "mmgr.h"
#include "multiboot2.h" #include "multiboot2.h"
#include "memorymap.h" #include "memorymap.h"
#include "apic.h" #include "apic.h"
@@ -11,38 +13,18 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
extern int _kernel_pstart;
extern int _kernel_pend;
extern int _kernel_start;
extern int _kernel_end; extern int _kernel_end;
struct kernel_t kernel_state; struct kernel_t kernel_state;
int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable)
{
for (int i = 0; i < 1024; i++)
{
uint32_t pte = i * 4096 + 3;
table[i] = pte;
identityTable[i] = pte;
}
directory[0] = ((uint32_t)identityTable) + 3;
directory[1022] = ((uint32_t)table) + 3;
directory[1023] = ((uint32_t)directory) + 3;
asm("mov %0, %%cr3"
:
: "r"(directory));
asm("mov %%cr0, %%eax \n"
"or $0x80010000, %%eax \n"
"mov %%eax, %%cr0"
:
:
: "eax");
return 0;
}
int initialize(void *multiboot_info) int initialize(void *multiboot_info)
{ {
initialize_gdt(); initialize_gdt();
initialize_idt(); initialize_idt();
printf("***%s***\n", PACKAGE_STRING); initialize_allocator(&_kernel_end, (void*)0xFFC00000);
static struct page_stack_t page_stack; static struct page_stack_t page_stack;
struct memory_region_t map_array[16]; struct memory_region_t map_array[16];
char bootloader_name[64]; char bootloader_name[64];
@@ -55,12 +37,19 @@ int initialize(void *multiboot_info)
.array = map_array, .array = map_array,
.size = 0, .size = 0,
.capacity = 16}}; .capacity = 16}};
void *multiboot_end = multiboot_info + *(uint32_t*)multiboot_info;
multiboot_info += 8; multiboot_info += 8;
while (multiboot_info != NULL) while (multiboot_info != NULL)
{ {
multiboot_info = read_multiboot_table(&boot_info, multiboot_info); multiboot_info = read_multiboot_table(&boot_info, multiboot_info);
} }
insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE); insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend, M_UNAVAILABLE);
for(void *p = (void*)&_kernel_end; p < multiboot_end; p += page_size)
{
unmap_page(p);
}
initialize_screen();
printf("***%s***\n", PACKAGE_STRING);
printf("Type\t\tLocation\t\tSize\n"); printf("Type\t\tLocation\t\tSize\n");
for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++) for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++)
{ {
@@ -68,8 +57,8 @@ int initialize(void *multiboot_info)
} }
page_stack.base_pointer = (physaddr_t*)0xFFC00000; page_stack.base_pointer = (physaddr_t*)0xFFC00000;
page_stack.stack_pointer = (physaddr_t*)0xFFC00000; page_stack.stack_pointer = (physaddr_t*)0xFFC00000;
page_stack.limit_pointer = (physaddr_t*)0xFF900000; page_stack.limit_pointer = (physaddr_t*)0xFFC00000;
initialize_page_stack(&page_stack, &boot_info.map, 4096); initialize_page_stack(&page_stack, &boot_info.map);
apic_enable(page_stack); apic_enable(page_stack);
apic_registers->divide_config.value = APIC_DIVIDE_128; apic_registers->divide_config.value = APIC_DIVIDE_128;
apic_registers->lvt_timer.vector = ISR_APIC_TIMER; apic_registers->lvt_timer.vector = ISR_APIC_TIMER;