From eed73e2414f8112d0b647e5324d7b89d07f8809e Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 25 Feb 2023 17:58:23 +0000 Subject: [PATCH] build: add a "user" arch to allow the kernel to run as a program on the host machine --- Makefile | 10 ++-- arch/user/config.mk | 18 +++++++ arch/user/cpu.c | 24 +++++++++ arch/user/extra.mk | 13 +++++ arch/user/hwlock.c | 27 ++++++++++ arch/user/include/arch/stdcon.h | 6 +++ arch/user/include/socks/machine/cpu.h | 15 ++++++ arch/user/include/socks/machine/hwlock.h | 14 +++++ arch/user/include/socks/machine/init.h | 8 +++ arch/user/include/socks/machine/irq.h | 5 ++ arch/user/include/socks/machine/pmap.h | 9 ++++ arch/user/include/socks/machine/vm.h | 26 +++++++++ arch/user/init.c | 68 ++++++++++++++++++++++++ arch/user/stdcon.c | 27 ++++++++++ arch/x86_64/config.mk | 12 ++++- arch/x86_64/extra.mk | 2 +- libc/include/socks/libc/string.h | 6 +-- libc/string/memchr.c | 4 +- libc/string/strcmp.c | 2 +- libc/string/strcpy.c | 6 +-- tools/make/gcc-cross-compile.mk | 10 ---- 21 files changed, 286 insertions(+), 26 deletions(-) create mode 100644 arch/user/config.mk create mode 100644 arch/user/cpu.c create mode 100644 arch/user/extra.mk create mode 100644 arch/user/hwlock.c create mode 100644 arch/user/include/arch/stdcon.h create mode 100644 arch/user/include/socks/machine/cpu.h create mode 100644 arch/user/include/socks/machine/hwlock.h create mode 100644 arch/user/include/socks/machine/init.h create mode 100644 arch/user/include/socks/machine/irq.h create mode 100644 arch/user/include/socks/machine/pmap.h create mode 100644 arch/user/include/socks/machine/vm.h create mode 100644 arch/user/init.c create mode 100644 arch/user/stdcon.c diff --git a/Makefile b/Makefile index ab3fd12..4cdc89b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ KERNEL_EXEC := socks_kernel -ARCH := x86_64 +SOCKS_ARCH ?= x86_64 MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) ROOT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH))) @@ -13,7 +13,7 @@ BUILD_DIR := build # Architecture-specific source files #################################### -include arch/$(ARCH)/config.mk +include arch/$(SOCKS_ARCH)/config.mk #################################### # Platform-independent kernel source files @@ -31,10 +31,10 @@ LIBC_SRC_DIRS := stdio string ctype LIBC_C_FILES := $(foreach dir,$(LIBC_SRC_DIRS),$(wildcard libc/$(dir)/*.c)) LIBC_OBJ := $(addprefix $(BUILD_DIR)/,$(LIBC_C_FILES:.c=.o)) -BUILD_ID := $(shell tools/generate_build_id.py --arch $(ARCH)) +BUILD_ID := $(shell tools/generate_build_id.py --arch $(SOCKS_ARCH)) CFLAGS := $(CFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" -g -Wall -Werror -pedantic \ - -Iinclude -Iarch/$(ARCH)/include -Ilibc/include -Os + -Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include -Os ASMFLAGS := $(ASMFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" LDFLAGS := $(LDFLAGS) -g -Os @@ -77,7 +77,7 @@ compile-db: $(BUILD_DIR)/compile_commands.json tools: @$(MAKE) --no-print-directory -C tools -include arch/$(ARCH)/extra.mk +include arch/$(SOCKS_ARCH)/extra.mk .PHONY: all tools compile-db $(BUILD_DIR)/compile_commands.json diff --git a/arch/user/config.mk b/arch/user/config.mk new file mode 100644 index 0000000..b44f632 --- /dev/null +++ b/arch/user/config.mk @@ -0,0 +1,18 @@ +LD := gcc +CC := gcc +ASM := gcc +OBJCOPY := objcopy +STRIP := strip + +CFLAGS := +ASMFLAGS := $(CFLAGS) +LDFLAGS := + +ARCH_CFLAGS := -D_64BIT +ARCH_LDFLAGS := + +ARCH_DIR := arch/$(SOCKS_ARCH) + +ARCH_C_FILES := $(wildcard $(ARCH_DIR)/*.c) $(wildcard $(ARCH_DIR)/acpi/*.c) +ARCH_ASM_FILES := $(wildcard $(ARCH_DIR)/*.S) $(wildcard $(ARCH_DIR)/acpi/*.S) +ARCH_OBJ := $(addprefix $(BUILD_DIR)/,$(ARCH_C_FILES:.c=.o) $(ARCH_ASM_FILES:.S=.o)) diff --git a/arch/user/cpu.c b/arch/user/cpu.c new file mode 100644 index 0000000..de3f477 --- /dev/null +++ b/arch/user/cpu.c @@ -0,0 +1,24 @@ +#include +#include + +int ml_init_bootcpu(void) +{ + return 0; +} + +int ml_cpu_block_init(ml_cpu_block *p) +{ + return 0; +} + +int ml_cpu_block_use(ml_cpu_block *p) +{ + return 0; +} + +void ml_halt_cpu(void) +{ + while (1) { + sleep(100); + } +} diff --git a/arch/user/extra.mk b/arch/user/extra.mk new file mode 100644 index 0000000..3f37719 --- /dev/null +++ b/arch/user/extra.mk @@ -0,0 +1,13 @@ +run: $(BUILD_DIR)/$(KERNEL_EXEC) + @printf " \033[1;93mEXEC\033[0m $<\n" + + @$(BUILD_DIR)/$(KERNEL_EXEC) + +debug: $(BUILD_DIR)/$(KERNEL_EXEC) + @if command -v gdb &> /dev/null; then \ + gdb -tui $(BUILD_DIR)/$(KERNEL_EXEC) \ + elif commad -v lldb &> /dev/null; then \ + lldb -- $(BUILD_DIR)/$(KERNEL_EXEC) \ + else \ + printf "No debuggers available." \ + endif diff --git a/arch/user/hwlock.c b/arch/user/hwlock.c new file mode 100644 index 0000000..26c0a34 --- /dev/null +++ b/arch/user/hwlock.c @@ -0,0 +1,27 @@ +#include +#include + +void ml_hwlock_lock(ml_hwlock_t *lck) +{ + volatile int q = 0; + while (!__sync_bool_compare_and_swap(lck, 0, 1)) { + q++; + } +} + +void ml_hwlock_unlock(ml_hwlock_t *lck) +{ + __sync_lock_release(lck); +} + +void ml_hwlock_lock_irqsave(ml_hwlock_t *lck, unsigned long *flags) +{ + (void)flags; + ml_hwlock_lock(lck); +} + +void ml_hwlock_unlock_irqrestore(ml_hwlock_t *lck, unsigned long flags) +{ + (void)flags; + ml_hwlock_unlock(lck); +} diff --git a/arch/user/include/arch/stdcon.h b/arch/user/include/arch/stdcon.h new file mode 100644 index 0000000..b35d005 --- /dev/null +++ b/arch/user/include/arch/stdcon.h @@ -0,0 +1,6 @@ +#ifndef ARCH_STDCON_H_ +#define ARCH_STDCON_H_ + +extern void stdcon_init(void); + +#endif diff --git a/arch/user/include/socks/machine/cpu.h b/arch/user/include/socks/machine/cpu.h new file mode 100644 index 0000000..36f90dc --- /dev/null +++ b/arch/user/include/socks/machine/cpu.h @@ -0,0 +1,15 @@ +#ifndef SOCKS_USER_CPU_H_ +#define SOCKS_USER_CPU_H_ + +typedef struct ml_cpu_block { + int cpu_reserved; +} ml_cpu_block; + +extern int ml_init_bootcpu(void); + +extern int ml_cpu_block_init(ml_cpu_block *p); +extern int ml_cpu_block_use(ml_cpu_block *p); + +extern void ml_halt_cpu(void); + +#endif diff --git a/arch/user/include/socks/machine/hwlock.h b/arch/user/include/socks/machine/hwlock.h new file mode 100644 index 0000000..6ba328b --- /dev/null +++ b/arch/user/include/socks/machine/hwlock.h @@ -0,0 +1,14 @@ +#ifndef SOCKS_USER_HWLOCK_H_ +#define SOCKS_USER_HWLOCK_H_ + +#define ML_HWLOCK_INIT (0) + +typedef int ml_hwlock_t; + +extern void ml_hwlock_lock(ml_hwlock_t *lck); +extern void ml_hwlock_unlock(ml_hwlock_t *lck); + +extern void ml_hwlock_lock_irqsave(ml_hwlock_t *lck, unsigned long *flags); +extern void ml_hwlock_unlock_irqrestore(ml_hwlock_t *lck, unsigned long flags); + +#endif diff --git a/arch/user/include/socks/machine/init.h b/arch/user/include/socks/machine/init.h new file mode 100644 index 0000000..6c594e6 --- /dev/null +++ b/arch/user/include/socks/machine/init.h @@ -0,0 +1,8 @@ +#ifndef SOCKS_X86_64_INIT_H_ +#define SOCKS_X86_64_INIT_H_ + +#include + +extern int ml_init(uintptr_t arg); + +#endif diff --git a/arch/user/include/socks/machine/irq.h b/arch/user/include/socks/machine/irq.h new file mode 100644 index 0000000..be06f01 --- /dev/null +++ b/arch/user/include/socks/machine/irq.h @@ -0,0 +1,5 @@ +#ifndef SOCKS_X86_64_IRQ_H_ +#define SOCKS_X86_64_IRQ_H_ + + +#endif diff --git a/arch/user/include/socks/machine/pmap.h b/arch/user/include/socks/machine/pmap.h new file mode 100644 index 0000000..85a1829 --- /dev/null +++ b/arch/user/include/socks/machine/pmap.h @@ -0,0 +1,9 @@ +#ifndef SOCKS_X86_64_PMAP_H_ +#define SOCKS_X86_64_PMAP_H_ + +#include + +typedef pml4t_ptr_t ml_pmap_t; +typedef uint64_t ml_pfn_t; + +#endif diff --git a/arch/user/include/socks/machine/vm.h b/arch/user/include/socks/machine/vm.h new file mode 100644 index 0000000..d841b4c --- /dev/null +++ b/arch/user/include/socks/machine/vm.h @@ -0,0 +1,26 @@ +#ifndef SOCKS_USER_VM_H_ +#define SOCKS_USER_VM_H_ + +#include + +extern uintptr_t __pagemap_base(void); +extern uintptr_t __pagemap_limit(void); + +/* kernel higher-half base virtual address. */ +#define VM_KERNEL_VOFFSET (__pagemap_base()) + +/* direct page-mapping region. + NOTE that these are the maximum bounds of this region. + the actual size depends on the amount of physical + memory present. */ +#define VM_PAGEMAP_BASE (__pagemap_base()) +#define VM_PAGEMAP_LIMIT (__pagemap_limit()) + +#define VM_PAGE_SIZE 0x1000 +#define VM_PAGE_MASK (VM_PAGE_SIZE-1) +#define VM_PAGE_SHIFT 12 + +#define VM_PAGE_MIN_ORDER VM_PAGE_4K +#define VM_PAGE_MAX_ORDER VM_PAGE_8M + +#endif diff --git a/arch/user/init.c b/arch/user/init.c new file mode 100644 index 0000000..6436daa --- /dev/null +++ b/arch/user/init.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMEM_SIZE 0x2000000 + +extern void kernel_init(uintptr_t arg); + +static void *pmem = NULL; + +static void early_vm_init(void) +{ + pmem = mmap(NULL, PMEM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (pmem == MAP_FAILED) { + fprintf(stderr, "arch: cannot map physical memory buffer."); + abort(); + } + + uintptr_t alloc_start = (uintptr_t)pmem + VM_PAGE_SIZE; + uintptr_t alloc_end = alloc_start + PMEM_SIZE; + + memblock_init(alloc_start, alloc_end, (uintptr_t)pmem); + printk("memblock: allocating from [0x%llx-0x%llx]", alloc_start, alloc_end); +} + +uintptr_t __pagemap_base(void) +{ + return (uintptr_t)pmem; +} + +uintptr_t __pagemap_limit(void) +{ + return (uintptr_t)pmem + PMEM_SIZE - 1; +} + +int ml_init(uintptr_t arg) +{ + stdcon_init(); + print_kernel_banner(); + early_vm_init(); + + memblock_add(0, PMEM_SIZE); + + vm_zone_descriptor_t vm_zones[] = { + { .zd_id = VM_ZONE_DMA, .zd_node = 0, .zd_name = "dma", .zd_base = 0x00, .zd_limit = 0xffffff }, + { .zd_id = VM_ZONE_NORMAL, .zd_node = 0, .zd_name = "normal", .zd_base = 0x1000000, .zd_limit = UINTPTR_MAX }, + }; + + vm_bootstrap(vm_zones, sizeof vm_zones / sizeof vm_zones[0]); + + object_bootstrap(); + return 0; +} + +int main(int argc, const char **argv) +{ + kernel_init(0); + + munmap(pmem, PMEM_SIZE); + return 0; +} diff --git a/arch/user/stdcon.c b/arch/user/stdcon.c new file mode 100644 index 0000000..d71373e --- /dev/null +++ b/arch/user/stdcon.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +static void stdcon_write(console_t *con, const char *s, unsigned int len) +{ + for (unsigned int i = 0; i < len; i++) { + fputc(s[i], stdout); + } +} + +static console_t stdcon = { + .c_name = "stdcon", + .c_flags = CON_BOOT, + .c_write = stdcon_write, + .c_lock = SPIN_LOCK_INIT, +}; + +void stdcon_init(void) +{ + console_register(&stdcon); + early_printk_init(&stdcon); +} diff --git a/arch/x86_64/config.mk b/arch/x86_64/config.mk index 308c1a7..484fb9a 100644 --- a/arch/x86_64/config.mk +++ b/arch/x86_64/config.mk @@ -1,7 +1,17 @@ +LD := $(SOCKS_ARCH)-elf-gcc +CC := $(SOCKS_ARCH)-elf-gcc +ASM := $(SOCKS_ARCH)-elf-gcc +OBJCOPY := $(SOCKS_ARCH)-elf-objcopy +STRIP := $(SOCKS_ARCH)-elf-strip + +CFLAGS := -ffreestanding -nostdlib +ASMFLAGS := $(CFLAGS) +LDFLAGS := -nostdlib + ARCH_CFLAGS := -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234 ARCH_LDFLAGS := -z max-page-size=0x1000 -T arch/x86_64/layout.ld -ARCH_DIR := arch/$(ARCH) +ARCH_DIR := arch/$(SOCKS_ARCH) ARCH_C_FILES := $(wildcard $(ARCH_DIR)/*.c) $(wildcard $(ARCH_DIR)/acpi/*.c) ARCH_ASM_FILES := $(wildcard $(ARCH_DIR)/*.S) $(wildcard $(ARCH_DIR)/acpi/*.S) diff --git a/arch/x86_64/extra.mk b/arch/x86_64/extra.mk index 9153d85..5b47079 100644 --- a/arch/x86_64/extra.mk +++ b/arch/x86_64/extra.mk @@ -1,5 +1,5 @@ QEMU := qemu-system-x86_64 -QEMU_FLAGS := -m 64M -smp 4 -cpu qemu64,pdpe1gb +QEMU_FLAGS := -m 10M -smp 4 -cpu qemu64,pdpe1gb ARCH_TEMP_FILES := $(BUILD_DIR)/$(KERNEL_EXEC).elf32 diff --git a/libc/include/socks/libc/string.h b/libc/include/socks/libc/string.h index 87c2c3f..a993d35 100644 --- a/libc/include/socks/libc/string.h +++ b/libc/include/socks/libc/string.h @@ -9,7 +9,7 @@ extern "C" { #endif extern char *strcpy(char *output, const char *input); -extern char *strncpy(char *output, const char *input, unsigned int count); +extern char *strncpy(char *output, const char *input, unsigned long count); extern char *strchrnul(const char *s, int c); extern char *strchr(const char *s, int c); extern size_t lfind(const char *str, const char accept); @@ -19,7 +19,7 @@ extern char *strpbrk(const char *s, const char *b); extern size_t strlen(const char *str); extern char *strrchr(const char *str, int c); extern int strcmp(const char *s1, const char *s2); -extern int strncmp(const char *s1, const char *s2, unsigned int n); +extern int strncmp(const char *s1, const char *s2, unsigned long n); extern void *memcpy(void *str1, const void *str2, size_t n); extern int memcmp(const void *str1, const void *str2, size_t n); extern void *memset(void *str, int c, size_t n); @@ -28,7 +28,7 @@ extern char *strdup(const char *src); extern char *strtok_r(char *str, const char *delim, char **saveptr); extern char *strcat(char *dest, const char *src); extern char *strncat(char *dest, const char *src, size_t num); -extern void *memchr(const void *ptr, int value, size_t num); +extern void *memchr(const void *ptr, int value, unsigned long num); #ifdef __cplusplus } diff --git a/libc/string/memchr.c b/libc/string/memchr.c index 9b4d9f1..7c47d65 100644 --- a/libc/string/memchr.c +++ b/libc/string/memchr.c @@ -1,10 +1,10 @@ #include -const void *memchr(const void *ptr, int value, size_t num) { +void *memchr(const void *ptr, int value, unsigned long num) { const unsigned char *buf = ptr; unsigned char val = value; - for (size_t i = 0; i < num; i++) { + for (unsigned long i = 0; i < num; i++) { if (buf[i] == val) { return (void *)(buf + i); } diff --git a/libc/string/strcmp.c b/libc/string/strcmp.c index 42aea66..f35df9b 100644 --- a/libc/string/strcmp.c +++ b/libc/string/strcmp.c @@ -8,7 +8,7 @@ int strcmp(const char *s1, const char *s2) return s1[i] - s2[i]; } -int strncmp(const char *s1, const char *s2, unsigned int n) +int strncmp(const char *s1, const char *s2, unsigned long n) { for (; n > 0; s1++, s2++, --n) if (*s1 != *s2) diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c index 7a816de..3056e02 100644 --- a/libc/string/strcpy.c +++ b/libc/string/strcpy.c @@ -11,10 +11,10 @@ char *strcpy(char *output, const char *input) return output; } -char *strncpy(char *output, const char *input, unsigned int count) +char *strncpy(char *output, const char *input, unsigned long count) { - unsigned int size = count; - unsigned int i; + unsigned long size = count; + unsigned long i; for (i = 0; i < size; i++) { output[i] = input[i]; diff --git a/tools/make/gcc-cross-compile.mk b/tools/make/gcc-cross-compile.mk index d24eba1..e69de29 100644 --- a/tools/make/gcc-cross-compile.mk +++ b/tools/make/gcc-cross-compile.mk @@ -1,10 +0,0 @@ -LD := $(ARCH)-elf-gcc -CC := $(ARCH)-elf-gcc -ASM := $(ARCH)-elf-gcc -OBJCOPY := $(ARCH)-elf-objcopy -STRIP := $(ARCH)-elf-strip - -CFLAGS := -ffreestanding -nostdlib -ASMFLAGS := $(CFLAGS) -LDFLAGS := -nostdlib -