summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/sys/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/sys/init.c')
-rw-r--r--arch/x86_64/sys/init.c91
1 files changed, 38 insertions, 53 deletions
diff --git a/arch/x86_64/sys/init.c b/arch/x86_64/sys/init.c
index c55eabe..40c3240 100644
--- a/arch/x86_64/sys/init.c
+++ b/arch/x86_64/sys/init.c
@@ -12,15 +12,9 @@
#include "boot/cmdline.h"
#include "boot/initrd.h"
-PAGEALIGN static page_t s_init_program_pml3[512];
-PAGEALIGN static page_t s_init_program_pml2[512];
-PAGEALIGN static page_t s_init_program_pml1[512];
-PAGEALIGN static uint8_t s_init_program_pages[INIT_PROGRAM_PAGES_MAX][0x1000];
-
-PAGEALIGN static page_t s_init_stack_pml3[512];
-PAGEALIGN static page_t s_init_stack_pml2[512];
-PAGEALIGN static page_t s_init_stack_pml1[512];
-PAGEALIGN static uint8_t s_init_stack_pages[INIT_STACK_PAGES][0x1000];
+PAGEALIGN static uint8_t s_init_program_pages[INIT_PROGRAM_PAGES_MAX + 3][0x1000];
+PAGEALIGN static uint8_t s_init_stack_pages[INIT_STACK_PAGES + 3][0x1000];
+PAGEALIGN static uint8_t s_init_message_page[0x1000];
static int
elf_is_valid(struct elf_header *ehdr)
@@ -54,24 +48,6 @@ elf_is_valid(struct elf_header *ehdr)
void
init_setup(void)
{
- memset(s_init_program_pml3, 0, 0x1000);
- memset(s_init_program_pml2, 0, 0x1000);
- memset(s_init_program_pml1, 0, 0x1000);
-
- memset(s_init_stack_pml3, 0, 0x1000);
- memset(s_init_stack_pml2, 0, 0x1000);
- memset(s_init_stack_pml1, 0, 0x1000);
-
- uintptr_t init_program_pml3_pptr = KPTR_TOPHYS(&s_init_program_pml3);
- uintptr_t init_program_pml2_pptr = KPTR_TOPHYS(&s_init_program_pml2);
- uintptr_t init_program_pml1_pptr = KPTR_TOPHYS(&s_init_program_pml1);
- uintptr_t init_program_pml0_pptr = KPTR_TOPHYS(&s_init_program_pages);
-
- uintptr_t init_stack_pml3_pptr = KPTR_TOPHYS(&s_init_stack_pml3);
- uintptr_t init_stack_pml2_pptr = KPTR_TOPHYS(&s_init_stack_pml2);
- uintptr_t init_stack_pml1_pptr = KPTR_TOPHYS(&s_init_stack_pml1);
- uintptr_t init_stack_pml0_pptr = KPTR_TOPHYS(&s_init_stack_pages);
-
//Get the init file data from the initrd.
const char *init_path = cmdline_getarg("init");
if(init_path == NULL) {
@@ -102,6 +78,7 @@ init_setup(void)
size_t last_base = 0;
//Load the init ELF
+ size_t last_page = 0;
for(size_t i = 0; i < init_ehdr->e_phnum; i++) {
struct elf_phdr *phdr = init_data + init_ehdr->e_phoff + i * init_ehdr->e_phentsize;
if(phdr->p_type != PT_LOAD) continue;
@@ -109,28 +86,26 @@ init_setup(void)
uintptr_t base = phdr->p_vaddr;
size_t limit = phdr->p_memsz;
+ if(last_base < base + limit) last_base = base + limit;
uintptr_t page_base = base & ~0xFFFULL;
- size_t pml3i = (page_base >> PMLI_SHL(3)) & 0x1FF;
- size_t pml2i = (page_base >> PMLI_SHL(2)) & 0x1FF;
- size_t pml1i = (page_base >> PMLI_SHL(1)) & 0x1FF;
- size_t base_pml0i = (page_base >> PMLI_SHL(0)) & 0x1FF;
-
- pml4[pml3i].value = init_program_pml3_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER;
- s_init_program_pml3[pml2i].value = init_program_pml2_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER;
- s_init_program_pml2[pml1i].value = init_program_pml1_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER;
-
size_t pages = (limit + 4095) / 4096;
- for(size_t pmlo = 0; pmlo < pages; pmlo++) {
- size_t pml0i = base_pml0i + pmlo;
- if(pml0i > INIT_PROGRAM_PAGES_MAX) {
+ for(size_t i = 0; i < pages; i++) {
+ uintptr_t page_virt = page_base + (i << 12);
+ if(last_page > INIT_PROGRAM_PAGES_MAX) {
kpanic("init: Program exceeds maximum program pages in the same hugepage frame!\n");
}
- if(last_base < base + limit) last_base = base + limit;
- uintptr_t pml0_pptr = init_program_pml0_pptr + (pml0i << 12);
- s_init_program_pml1[pml0i].value = pml0_pptr | PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE;
+ int tblres = 0;
+ do {
+ uintptr_t tbl_frame = KPTR_TOPHYS(&s_init_program_pages[last_page++]);
+ tblres = pagedir_map_table(pml4, tbl_frame, page_virt);
+ if(tblres == EHASMAP) last_page--;
+ }while(!tblres);
+
+ pagedir_map_frame(pml4, KPTR_TOPHYS(&s_init_program_pages[last_page++]), page_virt,
+ PAGE_WRITEABLE | PAGE_USER);
}
//Copy data from section if SHT_PROGBITS
@@ -138,22 +113,32 @@ init_setup(void)
}
//Map the stack
- pml4[255].value = init_stack_pml3_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
- s_init_stack_pml3[511].value = init_stack_pml2_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
- s_init_stack_pml2[511].value = init_stack_pml1_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
- for(size_t pmlo = 0; pmlo < INIT_STACK_PAGES; pmlo++) {
- size_t pml0i = 511 - pmlo;
- uintptr_t page_pptr = init_stack_pml0_pptr + (pmlo << 12);
-
- s_init_stack_pml1[pml0i].value = page_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
+ size_t stack_base = 0x00007FFFFFFFF000;
+ int stack_mapres = 0;
+
+ last_page = 0;
+ for(size_t i = 0; i < INIT_STACK_PAGES; i++) {
+ uintptr_t page_virt = stack_base - (i << 12);
+ int tblres = 0;
+
+ do {
+ uintptr_t tbl_frame = KPTR_TOPHYS(&s_init_stack_pages[last_page++]);
+ tblres = pagedir_map_table(pml4, tbl_frame, page_virt);
+ if(tblres == EHASMAP) last_page--;
+ }while(!tblres);
+
+ pagedir_map_frame(pml4, KPTR_TOPHYS(&s_init_stack_pages[last_page++]), page_virt,
+ PAGE_WRITEABLE | PAGE_USER | PAGE_XD);
}
//Map the syscall message.
last_base = (last_base + 0xFFF) & ~0xFFF;
- size_t last_page = (last_base >> 12) & 0x1FF;
- uintptr_t message_pptr = init_program_pml0_pptr + (last_page << 12);
- s_init_program_pml1[last_page].value = message_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
+ uintptr_t message_pptr = KPTR_TOPHYS(s_init_message_page);
+ pagedir_map_frame(pml4, message_pptr, last_base,
+ PAGE_WRITEABLE | PAGE_USER | PAGE_XD);
+ extern struct init_payload _init_payload;
+ memcpy((void*)last_base, &_init_payload, sizeof(struct init_payload));
jove_owned_obj_t *message_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_MESSAGE_I);
obj_settype(message_obj, JOVE_OBJ_MESSAGE);