diff options
| -rw-r--r-- | api/bits/x86_64/descriptor.h | 2 | ||||
| -rw-r--r-- | boot/fake_syscall_entry.S | 89 | ||||
| -rw-r--r-- | boot/main.c | 76 | ||||
| -rw-r--r-- | lldbscript | 2 |
4 files changed, 114 insertions, 55 deletions
diff --git a/api/bits/x86_64/descriptor.h b/api/bits/x86_64/descriptor.h index 649ac74..c0c00f6 100644 --- a/api/bits/x86_64/descriptor.h +++ b/api/bits/x86_64/descriptor.h @@ -4,7 +4,7 @@ struct descriptor_table_register_long { uint16_t limit; uint64_t base; -} __attribute__((packed, aligned(16))); +} __attribute__((packed, aligned(8))); struct segment_descriptor { diff --git a/boot/fake_syscall_entry.S b/boot/fake_syscall_entry.S index bc175c1..8a3f8c8 100644 --- a/boot/fake_syscall_entry.S +++ b/boot/fake_syscall_entry.S @@ -1,34 +1,79 @@ .section .text .global fake_syscall_entry -.global fake_syscall_return +.global fake_syscall_start .extern fake_syscall_handler -fake_syscall_entry: - hlt; - -fake_syscall_return: +fake_syscall_start: cli -fake_syscall_swap: - mov %cs, %rax - pushq %rax - pushq %rdx - mov %ds, %rax - pushq %rax - sub $16, %rsp - sgdt (%rsp) - mov %rsp, (%rsi) mov %rdi, %rsp - lgdt (%rsp) - add $16, %rsp - movw (%rsp), %ds - movw (%rsp), %es - movw (%rsp), %fs - movw (%rsp), %gs - movw (%rsp), %ss + jmp .L_fake_syscall_return + +/* + SYSCALL STACK FRAME - FROM LOWER TO HIGHER ADDRESS + + 0 pad + 8 syscall_index + 16 parameters[0] + 24 parameters[1] + 32 parameters[2] + 40 parameters[3] + 48 parameters[4] + 56 parameters[5] + 64 state.rflags + 72 state.gdtr.base:2 state.gdtr.limit:6 + 80 state.gdtr.limit:2 [unused]:6 + 88 state.return_ds + 96 state.return_rip + 104 state.return_cs +*/ + +fake_syscall_entry: + sub $112, %rsp + mov %rax, 8(%rsp) + mov %rdi, 16(%rsp) + mov %rsi, 24(%rsp) + mov %rdx, 32(%rsp) + mov %r10, 40(%rsp) + mov %r8, 48(%rsp) + mov %r9, 56(%rsp) + + pushfq + pop %rdi + mov %rdi, 64(%rsp) + + sgdt 72(%rsp) + movw %ds, 88(%rsp) + mov %rcx, 96(%rsp) + movw %cs, 104(%rsp) + + mov %rsp, %rdi + call fake_syscall_handler + + push %rbp + mov %rsp, %rbp + add $64, %rsp + popfq + mov %rbp, %rsp + pop %rbp + +.L_fake_syscall_return: + lgdt 72(%rsp) + mov 88(%rsp), %rdi + mov %di, %ds + mov %di, %es + mov %di, %fs + mov %di, %gs + mov %di, %ss - add $8, %rsp + mov 16(%rsp), %rdi + mov 24(%rsp), %rsi + mov 32(%rsp), %rdx + mov 40(%rsp), %r10 + mov 48(%rsp), %r8 + mov 56(%rsp), %r9 + add $96, %rsp lretq diff --git a/boot/main.c b/boot/main.c index d217235..12b411c 100644 --- a/boot/main.c +++ b/boot/main.c @@ -3,6 +3,8 @@ #include <asm/x86_64/msr.h> #include <bits/x86_64/msr.h> #include <bits/x86_64/descriptor.h> +#include <libc/stdio.h> +#include <posix/sys/mman.h> /* * Fake syscall mechanism - @@ -43,15 +45,39 @@ static struct segment_descriptor const fake_syscall_gdt[] = { 0xffff, 0, 0, 0x92, 0xcf, 0} }; -SYSV_ABI static void fake_syscall_handler(void) +typedef uint64_t syscall_delegate_parameters[6]; + +struct syscall_context_return_state { - while (true); -} + uint64_t rflags; // 8 + struct descriptor_table_register_long gdtr; // 24 + uint64_t return_ds; // 32 + uintptr_t return_rip; // 40 + uint64_t return_cs; // 48 +}; + +struct syscall_context +{ + uint64_t pad; // 8 + uint64_t syscall_index; // 16 + syscall_delegate_parameters parameters; // 64 + struct syscall_context_return_state state; +}; + +typedef int64_t (syscall_delegate)(syscall_delegate_parameters params); + +//constexpr int NR_SYSCALLS = 10; +//static syscall_delegate *syscall_handler_delegates[NR_SYSCALLS]; -static void *return_rsp; +SYSV_ABI int64_t fake_syscall_handler(uint64_t syscall_index, struct syscall_context *context) +{ + (void)syscall_index; + (void)context; + return -1; +} SYSV_ABI void fake_syscall_entry(void); -SYSV_ABI void fake_syscall_return(void *target_rsp, void **return_rsp, SYSV_ABI void (*callback)()); +SYSV_ABI void fake_syscall_start(void *stack); static void install_syscall_handler(void) { @@ -66,37 +92,24 @@ static void install_syscall_handler(void) msr_write(MSR_INDEX_EFER, efer); } -struct context_stack_frame -{ - struct descriptor_table_register_long lret_gdtr; - uint64_t lret_ds; - uint64_t lret_rip; - uint64_t lret_cs; -}; - -static void enter_boot_image(struct kjarna_boot_image *image) +static void *create_fake_syscall_stack(void *entry_addr) { - size_t boot_stack_size = 0x10000; - char *boot_image_stack = calloc(1, boot_stack_size); - void *boot_image_stack_head = boot_image_stack + boot_stack_size; + constexpr size_t fake_syscall_stack_size = 0x20000; // 128KiB stack + char *stack_pointer_base = mmap(nullptr, fake_syscall_stack_size, 0, 0, -1, 0); + void *stack_pointer_head = stack_pointer_base + fake_syscall_stack_size; - struct context_stack_frame *stack_frame = stack_alloc(&boot_image_stack_head, sizeof(*stack_frame)); + struct syscall_context *context = stack_alloc(&stack_pointer_head, sizeof(*context)); - stack_frame->lret_cs = 8; - stack_frame->lret_ds = 16; - stack_frame->lret_rip = (uintptr_t)image->entry; + context->state.rflags = 0; + context->state.gdtr.base = (uintptr_t)&fake_syscall_gdt; + context->state.gdtr.limit = sizeof(fake_syscall_gdt) - 1; + context->state.return_ds = 16; + context->state.return_cs = 8; + context->state.return_rip = (uintptr_t)entry_addr; - stack_frame->lret_gdtr.limit = sizeof(fake_syscall_gdt) - 1; - stack_frame->lret_gdtr.base = (uintptr_t)fake_syscall_gdt; - - - fake_syscall_return(boot_image_stack_head, &return_rsp, fake_syscall_handler); - - while (true); + return stack_pointer_head; } -#include <libc/stdio.h> - int main(int argc, char **argv) { (void)argc; @@ -104,6 +117,7 @@ int main(int argc, char **argv) struct kjarna_boot_image boot_image = get_boot_image(); install_syscall_handler(); - enter_boot_image(&boot_image); + void *fake_syscall_stack = create_fake_syscall_stack((void *)boot_image.entry); + fake_syscall_start(fake_syscall_stack); } @@ -3,5 +3,5 @@ target modules add service/kjarna.os gdb-remote localhost:1234 target modules load --file kjarna.efi .text 0x6184000 .data 0x6189000 target modules load --file kjarna.os --slide 0x6178000 -b enter_boot_image +b main |
