summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/Makefile4
-rw-r--r--boot/fake_syscall_entry.S17
-rw-r--r--boot/main.c97
3 files changed, 35 insertions, 83 deletions
diff --git a/boot/Makefile b/boot/Makefile
index 3c47336..49b6639 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -4,7 +4,7 @@ include ../defaults.mk
$(CC.info)
@$(CC) $(LDFLAGS) -o $@ $^
-VPATH := ../lib efi/
+VPATH := ../lib ../lib/asm/$(ARCH) efi/
IMAGE := kjarna.efi
@@ -22,7 +22,7 @@ LDFLAGS := --target=$(ARCH)-unknown-windows -nostdlib -ggdb \
all: $(IMAGE)
CRT_OBJS := start.o bind.o
-LIB_OBJS := memcmp.o memset.o memcpy.o memmove.o string.o elf64.o printf.o stdio.o
+LIB_OBJS := memcmp.o memset.o memcpy.o memmove.o string.o elf64.o printf.o stdio.o msr.o
EFI_OBJS := file.o memory.o protocol.o image.o
APP_OBJS := main.o fake_syscall_entry.o
diff --git a/boot/fake_syscall_entry.S b/boot/fake_syscall_entry.S
index ff2428d..bc175c1 100644
--- a/boot/fake_syscall_entry.S
+++ b/boot/fake_syscall_entry.S
@@ -1,18 +1,27 @@
.section .text
+.global fake_syscall_entry
+.global fake_syscall_return
+
.extern fake_syscall_handler
-.global fake_syscall_entry
fake_syscall_entry:
- hlt
+ hlt;
-.global fake_syscall_return
fake_syscall_return:
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
diff --git a/boot/main.c b/boot/main.c
index 570b703..d217235 100644
--- a/boot/main.c
+++ b/boot/main.c
@@ -1,5 +1,8 @@
#include "kjarna.h"
#include <stdnoreturn.h>
+#include <asm/x86_64/msr.h>
+#include <bits/x86_64/msr.h>
+#include <bits/x86_64/descriptor.h>
/*
* Fake syscall mechanism -
@@ -10,12 +13,12 @@
* in a way to make use of the SYSCALL instruction possible.
*
* This causes us to have to work inside of constraints during loading time
- * - All "user" mode execution entirely blocks interrupts processing. That
- * means that user mode code must not execute "hlt", or the system will
+ * - All "user" mode execution entirely blocks interrupt processing. That
+ * means that "user" mode code must not execute "hlt", or the system will
* be locked.
* - When (if?) user input is required, it is always buffered. It is possible
* to simulate unbuffered input, at the cost of one syscall per transfer
- * from "kernel" side to "user" side. This will cause high input lag.
+ * from "kernel" side to "user" side. This will cause high input latency.
* We will not be running Quake in this environment.
*
* These constraints are probably fine, as the loading process only needs to
@@ -23,40 +26,6 @@
*/
-struct dtr64
-{
- uint16_t limit;
- uint64_t base;
-} __attribute__((packed, aligned(16)));
-
-struct segment_descriptor
-{
- uint16_t limit0;
- uint16_t base0;
- uint8_t base16;
- uint8_t access;
- uint8_t flags_limit16;
- uint8_t base24;
-} __attribute__((packed, aligned(8)));
-
-union msr_star
-{
- struct
- {
- uint32_t target_eip;
- uint16_t syscall_selector_base;
- uint16_t sysret_selector_base;
- }
- fields;
- uint64_t value;
-};
-
-union msr_lstar
-{
- void (*syscall_handler)(void);
- uint64_t value;
-};
-
void *stack_alloc(void **stack_pointer, size_t alloc_size)
{
void *block = *(char **)stack_pointer -= alloc_size;
@@ -67,33 +36,6 @@ void *stack_alloc(void **stack_pointer, size_t alloc_size)
return block;
}
-static void msr_write(uint32_t index, uint64_t value)
-{
- uint32_t low = value & 0xffffffff;
- uint32_t high = value >> 32;
-
- __asm__ volatile
- (
- "wrmsr\n\t"
- :: "a"(low), "d"(high), "c"(index)
- );
-}
-
-uint64_t msr_read(uint32_t index)
-{
- uint32_t low;
- uint32_t high;
-
- __asm__ volatile
- (
- "rdmsr\n\t"
- : "=a"(low), "=d"(high)
- : "c"(index)
- );
-
- return ((uint64_t)high << 32)|low;
-}
-
static struct segment_descriptor const fake_syscall_gdt[] =
{
{ 0 },
@@ -101,35 +43,38 @@ static struct segment_descriptor const fake_syscall_gdt[] =
{ 0xffff, 0, 0, 0x92, 0xcf, 0}
};
-static noreturn void fake_syscall_entry(void)
+SYSV_ABI static void fake_syscall_handler(void)
{
while (true);
}
-SYSV_ABI void fake_syscall_return(void *target_rsp);
+static void *return_rsp;
+
+SYSV_ABI void fake_syscall_entry(void);
+SYSV_ABI void fake_syscall_return(void *target_rsp, void **return_rsp, SYSV_ABI void (*callback)());
static void install_syscall_handler(void)
{
- union msr_lstar lstar = { fake_syscall_entry };
+ union msr_lstar lstar = { (uintptr_t)fake_syscall_entry };
union msr_star star = { { 0, 1 << 3, 1 << 3 | 3 } };
- msr_write(0xc0000082, lstar.value);
- msr_write(0xc0000081, star.value);
+ msr_write(MSR_INDEX_LSTAR, lstar.value);
+ msr_write(MSR_INDEX_STAR, star.value);
- uint64_t efer = msr_read(0xc0000080);
+ uint64_t efer = msr_read(MSR_INDEX_EFER);
efer |= 1;
- msr_write(0xc0000080, efer);
+ msr_write(MSR_INDEX_EFER, efer);
}
struct context_stack_frame
{
- struct dtr64 lret_gdtr;
+ struct descriptor_table_register_long lret_gdtr;
uint64_t lret_ds;
uint64_t lret_rip;
uint64_t lret_cs;
};
-static noreturn void enter_boot_image(struct kjarna_boot_image *image)
+static void enter_boot_image(struct kjarna_boot_image *image)
{
size_t boot_stack_size = 0x10000;
char *boot_image_stack = calloc(1, boot_stack_size);
@@ -144,7 +89,8 @@ static noreturn void enter_boot_image(struct kjarna_boot_image *image)
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);
+
+ fake_syscall_return(boot_image_stack_head, &return_rsp, fake_syscall_handler);
while (true);
}
@@ -156,11 +102,8 @@ int main(int argc, char **argv)
(void)argc;
(void)argv;
- printf("DEBUG: alignof(struct dtr64) = %zu", alignof(struct dtr64));
- printf("DEBUG: sizeof(struct dtr64) = %zu", sizeof(struct dtr64));
struct kjarna_boot_image boot_image = get_boot_image();
install_syscall_handler();
enter_boot_image(&boot_image);
}
-