summaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-09-04 21:38:16 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-09-04 21:38:16 -0400
commit69a27cf95a8a8e3bbbd5e3d81a36893bf312cf3e (patch)
tree47ff56106345e43fbb5184071c8fe72987fe62bb /arch/x86_64
parent1768abb217f974cf96448ee847453b604800c546 (diff)
downloadjove-kernel-69a27cf95a8a8e3bbbd5e3d81a36893bf312cf3e.tar.gz
jove-kernel-69a27cf95a8a8e3bbbd5e3d81a36893bf312cf3e.tar.bz2
jove-kernel-69a27cf95a8a8e3bbbd5e3d81a36893bf312cf3e.zip
add usermode jump into init
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/boot/limine/framebuffer.c2
-rw-r--r--arch/x86_64/hal/paging.c2
-rw-r--r--arch/x86_64/hal/paging.h4
-rw-r--r--arch/x86_64/hal/smp.c1
-rw-r--r--arch/x86_64/lib/elf.h68
-rw-r--r--arch/x86_64/sys/init.c142
-rw-r--r--arch/x86_64/sys/syscall.c7
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)
+{
+
+}