diff options
Diffstat (limited to 'arch/x86_64')
| -rw-r--r-- | arch/x86_64/boot/limine/framebuffer.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/hal/paging.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/hal/paging.h | 4 | ||||
| -rw-r--r-- | arch/x86_64/hal/smp.c | 1 | ||||
| -rw-r--r-- | arch/x86_64/lib/elf.h | 68 | ||||
| -rw-r--r-- | arch/x86_64/sys/init.c | 142 | ||||
| -rw-r--r-- | arch/x86_64/sys/syscall.c | 7 |
7 files changed, 207 insertions, 19 deletions
diff --git a/arch/x86_64/boot/limine/framebuffer.c b/arch/x86_64/boot/limine/framebuffer.c index ea7c714..85c3f43 100644 --- a/arch/x86_64/boot/limine/framebuffer.c +++ b/arch/x86_64/boot/limine/framebuffer.c @@ -52,7 +52,7 @@ fb_remap(uintptr_t fb_address, size_t pml1 = pml0 >> 9; size_t pml0_mod = pml0 % 512; uintptr_t pml0_pptr = fb_address + (pml0 << 12); - fb_pml1[pml1][pml0_mod].value = pml0_pptr | PAGE_PRESENT | PAGE_GLOBAL | PAGE_WRITEABLE; + fb_pml1[pml1][pml0_mod].value = pml0_pptr | PAGE_PRESENT | PAGE_GLOBAL | PAGE_WRITEABLE | PAGE_WRITETHROUGH | PAGE_XD; } uintptr_t fb_virt = IDENT_VIRT_BASE | (511ULL << PMLI_SHL(3)); diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c index 9ef67ab..5887e79 100644 --- a/arch/x86_64/hal/paging.c +++ b/arch/x86_64/hal/paging.c @@ -164,7 +164,7 @@ paging_pml4_init(void) size_t l2 = l1 / 512; size_t l1_mod = l1 % 512; - ident_pml2[l2][l1_mod].value = (l1 << 21) | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_PS | PAGE_GLOBAL; + ident_pml2[l2][l1_mod].value = (l1 << 21) | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_PS | PAGE_GLOBAL | PAGE_XD; ident_pml2[l2][l1_mod].xd = 1; } diff --git a/arch/x86_64/hal/paging.h b/arch/x86_64/hal/paging.h index eb916a3..5736326 100644 --- a/arch/x86_64/hal/paging.h +++ b/arch/x86_64/hal/paging.h @@ -40,11 +40,11 @@ typedef union page_table_entry extern void *_kernel_physptr; #define PMLI_SHL(l) (12 + (l * 9)) -#define PMLI_MASK(l) (~0xFFFF << PMLI_SHL(l)) +#define PMLI_MASK(l) (~0xFFFFULL << PMLI_SHL(l)) #define IDENT_VIRT_BASE 0xFFFF800000000000ULL #define KERNEL_VIRT_BASE 0xFFFFFFFF80000000ULL -#define KPTR_TOPHYS(v) ((uintptr_t)v - KERNEL_VIRT_BASE + (uintptr_t)_kernel_physptr) +#define KPTR_TOPHYS(v) (((uintptr_t)v) - KERNEL_VIRT_BASE + (uintptr_t)_kernel_physptr) uintptr_t paging_get_pml4(void); void paging_pml4_init(void); diff --git a/arch/x86_64/hal/smp.c b/arch/x86_64/hal/smp.c index a28fdc1..0b1ed9d 100644 --- a/arch/x86_64/hal/smp.c +++ b/arch/x86_64/hal/smp.c @@ -27,6 +27,7 @@ init_processor(processor_t *processor, jove_owned_obj_t *obj) gdt_setup(processor); idt_setup(processor); + msr_enable_sce(); msr_set_gs_base((uintptr_t)processor); obj_settype(obj, JOVE_OBJ_PROCESSOR); diff --git a/arch/x86_64/lib/elf.h b/arch/x86_64/lib/elf.h new file mode 100644 index 0000000..fae2255 --- /dev/null +++ b/arch/x86_64/lib/elf.h @@ -0,0 +1,68 @@ +#ifndef _JOVE_LIB_ELF_H +#define _JOVE_LIB_ELF_H 1 + +#include <stdint.h> + +#define EI_MAG0 0x7F +#define EI_MAG1 0x45 +#define EI_MAG2 0x4C +#define EI_MAG3 0x46 + +#define EI_CLASS_64 2 +#define EI_DATA_LE 1 + +#define ET_EXEC 0x02 +#define EM_x86_64 0x3E + +struct elf_header +{ + uint8_t e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +}; + +struct elf_phdr +{ + uint32_t p_type; + uint32_t p_flags; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; + uint64_t p_align; +}; + +#define SHT_PROGBITS 1 +#define SHT_NOBITS 4 + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 + +struct elf_shdr +{ + uint32_t sh_name; + uint32_t sh_type; + uint64_t sh_flags; + uint64_t sh_addr; + uint64_t sh_offset; + uint64_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint64_t sh_addralign; + uint64_t sh_entsize; +}; + +#endif diff --git a/arch/x86_64/sys/init.c b/arch/x86_64/sys/init.c index 06fbe48..2bd86d5 100644 --- a/arch/x86_64/sys/init.c +++ b/arch/x86_64/sys/init.c @@ -1,42 +1,75 @@ #include "init.h" +#include "arch/x86_64/hal/msr.h" #include "config.h" #include "jove.h" #include "hal/obj.h" #include "lib/string.h" #include "lib/panic.h" +#include "lib/printf.h" +#include "arch/x86_64/lib/elf.h" #include "arch/x86_64/hal/paging.h" #include "boot/cmdline.h" #include "boot/initrd.h" -#define INIT_PROGRAM_HUGEPAGES_MAX ((INIT_PROGRAM_PAGES_MAX + 511) / 512) -#define INIT_STACK_HUGEPAGES_MAX ((INIT_STACK_PAGES_MAX + 511) / 512) - 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[INIT_PROGRAM_HUGEPAGES_MAX][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[INIT_STACK_HUGEPAGES_MAX][512]; +PAGEALIGN static page_t s_init_stack_pml1[512]; +PAGEALIGN static uint8_t s_init_stack_pages[INIT_STACK_PAGES][0x1000]; + +static int +elf_is_valid(struct elf_header *ehdr) +{ + if(ehdr->e_ident[0] != EI_MAG0 || + ehdr->e_ident[1] != EI_MAG1 || + ehdr->e_ident[2] != EI_MAG2 || + ehdr->e_ident[3] != EI_MAG3) { + kprintf("ELF: Magic does not match!\n"); + return 0; + } + if(ehdr->e_ident[4] != EI_CLASS_64) { + kprintf("ELF: Class is not 64-bit!\n"); + return 0; + } + if(ehdr->e_ident[5] != EI_DATA_LE) { + kprintf("ELF: Data is not little-endian!\n"); + return 0; + } + if(ehdr->e_type != ET_EXEC) { + kprintf("ELF: Program is not standard executable type!\n"); + return 0; + } + if(ehdr->e_machine != EM_x86_64) { + kprintf("ELF: Executable is not x86_64!\n"); + return 0; + } + return 1; +} 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 * INIT_PROGRAM_HUGEPAGES_MAX); + 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 * INIT_STACK_HUGEPAGES_MAX); + 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_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_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"); @@ -45,9 +78,88 @@ init_setup(void) } jove_owned_obj_t *initrd_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_INITRD_I)); - jove_owned_obj_t *initfile_obj = initrd_seek(initrd_obj, init_path); - if(initfile_obj == NULL) { + jove_owned_obj_t *init_obj = initrd_seek(initrd_obj, init_path); + if(init_obj == NULL) { kpanic("init: Cannot find file '%s' in initrd.\n", init_path); } obj_release(initrd_obj); + + void *init_data = initrd_file_data(init_obj); + obj_release(init_obj); + + struct elf_header *init_ehdr = init_data; + if(init_ehdr == NULL) { + kpanic("init: Cannot get file data for file '%s': %i\n", init_path, errno); + } + + if(!elf_is_valid(init_ehdr)) { + kpanic("init: Either passed file '%s' is not an ELF file or is not loadable.\n", init_path); + } + + jove_owned_obj_t *init_pagedir = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_PAGEDIR_I)); + page_t *pml4 = obj_deref(init_pagedir); + + //Load the init ELF + for(size_t i = 0; i < init_ehdr->e_shnum; i++) { + struct elf_shdr *shdr = init_data + init_ehdr->e_shoff + i * init_ehdr->e_shentsize; + if(shdr->sh_type != SHT_PROGBITS && shdr->sh_type != SHT_NOBITS) continue; + if((shdr->sh_flags & SHF_ALLOC) == 0) continue; + + uintptr_t base = shdr->sh_addr; + size_t limit = shdr->sh_size; + + 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) { + kpanic("init: Program exceeds maximum program pages in the same hugepage frame!\n"); + } + + uintptr_t pml0_pptr = init_program_pml0_pptr + (pml0i << 12); + s_init_program_pml1[pml0i].value = pml0_pptr | PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE; + } + + //Copy data from section if SHT_PROGBITS + if(shdr->sh_type == SHT_PROGBITS) { + memcpy((void*)shdr->sh_addr, init_data + shdr->sh_offset, shdr->sh_size); + } + } + + //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; + } + + obj_release(init_pagedir); + + //Enable syscalls + extern void _syscall_entry(void); + msr_set_lstar(_syscall_entry); + + uintptr_t usp = 0x00007FFFFFFFFFF8; + uintptr_t uip = init_ehdr->e_entry; + + __asm__ volatile("movq %0, %%rsp; \ + movq %1, %%rcx; \ + movq $0x202, %%r11; \ + swapgs; \ + sysretq":: + "r"(usp), "r"(uip): "memory"); } diff --git a/arch/x86_64/sys/syscall.c b/arch/x86_64/sys/syscall.c new file mode 100644 index 0000000..8cc58bf --- /dev/null +++ b/arch/x86_64/sys/syscall.c @@ -0,0 +1,7 @@ + + +__attribute__((naked)) +void _syscall_entry(void) +{ + +} |
