diff --git a/.gitignore b/.gitignore index 272190f..65cb813 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea cmake-build-debug out/ +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index dd939d8..d80707f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,140 @@ -cmake_minimum_required(VERSION 2.8.4) -project(secX) +cmake_minimum_required(VERSION 3.10) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c11") +# disable in-source build +set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) +set(CMAKE_DISABLE_SOURCE_CHANGES ON) -file(GLOB_RECURSE hal_src ./inc/*.h ./hal/*.c ./hal/*.h ./common/*.c) -file(GLOB_RECURSE kernel_src ./inc/*.h ./kernel/*.c ./kernel/*.h ./common/*.c) -file(GLOB_RECURSE test_src ./inc/*.h ./test/*.c ./test/*.h ./common/*.c) -include_directories(inc) +project(bond) -# HAL -#include_directories(hal/inc) -#add_executable(hal ${hal_src}) +set(proj bond) +set(INC ${CMAKE_CURRENT_SOURCE_DIR}/inc) +set(MK ${CMAKE_CURRENT_SOURCE_DIR}/mk) +set(arch amd64) + +include(${MK}/${arch}.cmake) + +# sanity check +set(TOOLCHAINS + AS + CC + GRUB + LD + DMP) + +FOREACH(f IN LISTS TOOLCHAINS) + if(NOT ${f}) + message(FATAL_ERROR "Toolchain ${f} cannot be found.") + endif() +endforeach(f) + +set(CC_WARN_IGNORE + -Wno-gnu-statement-expression # this means we can assign the return val of the last statment in a block, useful in MAX, MIN, etc. + -Wno-gnu-zero-variadic-macro-arguments # this enables us to use __VA_ARGS__ in macros + ) + +set(CC_FLAGS + -std=c17 + -c + -g + -Og + -Wall + -Wextra + -Wpedantic + -Werror + ${CC_WARN_IGNORE} + -ffreestanding + -I${INC} + -fno-pic + -fno-stack-protector + ${CC_FLAGS_${ARCH}}) + +set(AS_FLAGS + ${AS_FLAGS_${ARCH}}) + +set(LD_FLAGS + -fuse-ld=${LD} + -nostdlib + -Wl,--fatal-warnings + ${LD_FLAGS_${ARCH}}) + +set(PP_FLAGS + -E + -xc + -P + -I${INC} + ${PP_FLAGS_${ARCH}}) + +set(DMP_FLAGS + ${DMP_FLAGS_${ARCH}}) + +set(SUBMODULES + kern + arch + scripts + test) + +# process submodules +FOREACH(f IN LISTS SUBMODULES) + add_subdirectory(${f}) +endforeach(f) + +# process dependencies +FOREACH(f IN LISTS SUBMODULES) + set(OBJS ${OBJS} ${OBJS_${f}}) + set(TARGETS ${TARGETS} ${TARGET_${f}}) +endforeach(f) + +# set target names -# KERNEL -include_directories(kernel/inc) -add_executable(kernel ${kernel_src}) +# Rules for generating the image +set(TARGET ${proj}_elf) +set(OBJ_${TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${proj}.elf) +add_custom_command( + OUTPUT ${OBJ_${TARGET}} + DEPENDS ${TARGETS} + COMMAND ${CC} ${LD_FLAGS} -Wl,-T, ${SCRIPT_LD} -o ${OBJ_${TARGET}} ${OBJS}) + +add_custom_target(${TARGET} ALL + DEPENDS ${OBJ_${TARGET}}) + + +# Rules for generating the dump +set(TARGET ${proj}_dmp) +set(OBJ_${TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${proj}.dmp) + +add_custom_command( + OUTPUT ${OBJ_${TARGET}} + DEPENDS ${proj}_elf + COMMAND ${DMP} ${DMP_FLAGS} ${OBJ_${proj}_elf} > ${OBJ_${TARGET}} +) +add_custom_target(${proj}_dmp ALL + DEPENDS ${OBJ_${TARGET}}) + + +# Rules for generating the iso +set(TARGET ${proj}_iso) +set(OBJ_${TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${proj}.iso) + +add_custom_command( + OUTPUT ${OBJ_${TARGET}} + DEPENDS ${proj}_elf ${TARGET_scripts} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso/boot + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso/boot/grub + COMMAND ${CMAKE_COMMAND} -E copy ${OBJ_${proj}_elf} ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso/ + COMMAND ${CMAKE_COMMAND} -E copy ${SCRIPT_GRUB} ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso/boot/grub/ + COMMAND ${GRUB} -d /usr/lib/grub/i386-pc -o ${OBJ_${TARGET}} ${CMAKE_CURRENT_BINARY_DIR}/tmp_iso +) + +add_custom_target(${proj}_iso ALL + DEPENDS ${OBJ_${TARGET}}) + +# hack for clion not parsing custom targets +if ($ENV{CLION_IDE}) + include_directories(${INC}) + add_executable(kernel ${G_CC_SRC}) + target_compile_options(kernel PRIVATE ${CC_FLAGS}) +endif() + -# KERNEL + TESTS -#include_directories(test/inc) -#include_directories(kernel/inc) -#add_definitions(-DTDBG) -#add_executable(tests ${test_src} ${kernel_src}) diff --git a/Makefile b/Makefile deleted file mode 100644 index 93b2f33..0000000 --- a/Makefile +++ /dev/null @@ -1,87 +0,0 @@ - -AS := nasm -CC := clang -LD := lld -DAS := llvm-objdump-6.0 - -ifneq '$(AS_ENV)' '' -AS := $(AS_ENV) -endif -$(info Using AS=$(AS)) - -ifneq '$(CC_ENV)' '' -CC := $(CC_ENV) -endif -$(info Using CC=$(CC)) - -ifneq '$(LD_ENV)' '' -LD := $(LD_ENV) -endif -$(info Using LD=$(LD)) - -ifneq '$(DAS_ENV)' '' -DAS := $(DAS_ENV) -endif -$(info Using DAS=$(DAS)) - -INC_COMMON := inc -MK := mk -OUT := out - -C_FLAGS_ARCH_X86_64 := -mcmodel=kernel \ - -target x86_64-pc-none-elf \ - -mno-red-zone \ - -mno-mmx \ - -mno-sse \ - -mno-sse2 \ - -mno-sse3 \ - -mno-3dnow - -# generic freestanding cflags used for target -# each submodule can append to this flag -C_FLAGS = -x c \ - -g \ - -c \ - -O2 \ - -std=c17 \ - -Wall \ - -Wextra \ - -Wpedantic \ - -Werror \ - -ffreestanding \ - -fno-pic \ - -fno-stack-protector \ - $(C_FLAGS_ARCH_X86_64) \ - -I$(INC_COMMON) \ - $(C_FLAGS_$(MOD)) - -# generic asm flags used for target -# each submodule can append to this flag -AS_FLAGS = -w+all \ - -w+error \ - -f elf64 \ - -F dwarf \ - -g \ - -I$(INC_COMMON) \ - $(AS_FLAGS_$(MOD)) - -# generic pre-processing flags used for target -PREP_FLAGS = -E \ - -xc\ - -P \ - -I$(INC_COMMON) \ - $(C_FLAGS_$(MOD)) - -# generic generate dependency flags used for target -# each submodule can append to this flag -GDEP_FLAGS = $(PREP_FLAGS) \ - -MMD \ - -MT $@ - -MKDIR = mkdir -p $(dir $@) -COMP = $(CC) $(C_FLAGS) -o $@ $< -COMPAS = $(AS) $(AS_FLAGS) -o $@ $< -PREP = $(CC) $(PREP_FLAGS) $< > $@ -GDEP = $(CC) $(GDEP_FLAGS) -MF $(addsuffix .d, $@) $< > /dev/null - -include Rules.top diff --git a/README.md b/README.md index 68be90d..9e9efa2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ # Building -### Environment -All platforms where the required packages are available. - ### Required packages For compiling kernel only (make compile): @@ -24,3 +21,46 @@ Load the iso with your favorite simulator or use "-kernel" option with QEMU. For UEFI simulation, use qemu_bios.bin in the root dir with QEMU. +# C++ +I would like my kernel code to be explicit so that I can reason about performance, memory allocation/deallocation. That mostly means when I look at a statement I know exactly what it does. +The philosophy overlaps with Go's design quite a lot: https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html. + +Using fully-featured C++ is overly complicated for kernels and I'm dubious of OOP in general. With "modern" C++ sometimes I find myself struggling more with the language itself than getting work done. Although the kernel is compiled with a C++ compiler, the base is very much C and we only add few nice things we can benefit from C++: + +## Stronger types +C++ is stronger typed than C. Simply compiling the kernel itself with a C++ compiler provides more type safety than C. + +## C++ style casts (no dynamic_cast) +They are compile time casts so no runtime overhead. They provide a bit better type safety than C style casts. The only two casts we would need are probably const_cast and reinterpret_cast. + +## template +For type safety for data structures. Linux's list.h isn't type safe. FreeBSD's queue.h tries to mimic templates with macros, which is less elegant than just using template. + +## namespace +Oh boy how I wish C standard would include namespace, if it weren't for backward compaibility and stable ABI. + +## Banned features worth mentioning +This list explains SOME of the banned features that might seem useful. + +### Class and ctors/dtors +All data structures should be POD structs. Basically it means a struct without user-defined constructors and destructors. The reason is 1. encapsulation is pretty useless in the kernel. 2. constructors and destructors are implicitly called when declaring objects and when objects go out of scope, which violates explicitness. 3. Everything becomes easy to reason about. Now I don't need to worry about "Object obj;" implicitly invoking the allocator, acquiring a lock and querying a SQL database. + +RAII which relies on ctors/dtors sure is nice but IMO Golang's defer is a much better approach being expressive as well as functionally "similar". C has the extension "cleanup" supported by GCC and Clang which does the same thing as defer. I'll investigate the latter. + +### Member methods +Member methods should just be functions that take the struct as a parameter. It's what C++ does internally anyway. Adding member methods also obfuscates the PODness of structs, ergo banned. + +### Inheritance +Inheritance is banned except for describing interfaces like file descriptors and other possible places that might benefit from it. Even then it shouldn't be abused - e.g. the kernel does NOT need a generic list interface with a billion implementations. + +### Function overloading +Just give it an expressive enough name. Function overloading is obfuscation. + +### Operator overriding +Think about what "f();" could mean in C++ and the code executed by "a + b;". Need I say more? + +### References +I don't like mixing references with pointers. I don't find reference offering much more than raw pointers. + +### RTTI and Exceptions +Totally useless for kernels. \ No newline at end of file diff --git a/Rules.top b/Rules.top deleted file mode 100644 index 7258941..0000000 --- a/Rules.top +++ /dev/null @@ -1,61 +0,0 @@ -include $(MK)/prologue.mk - -.DEFAULT_GOAL := all - -# OBJ var holds all OBJS required to link the kernel - -dir := hal -include $(dir)/Rules.mk -dir := kernel -include $(dir)/Rules.mk -dir := mk -include $(dir)/Rules.mk -dir := common -include $(dir)/Rules.mk - - -LD_SCRIPT := $(OUT)/$(MK)/linker.ld -GRUB_CFG = $(MK)/grub.cfg - -TGT := $(OUT)/secxkrnl.elf -DMP := $(OUT)/secxkrnl.dmp -ISO := $(OUT)/secxkrnl.iso - -DUMP_FLAGS = -x86-asm-syntax=intel \ - -disassemble \ - -r \ - -t \ - -triple=x86_64-pc-none-elf \ - -print-imm-hex - -LD_FLAGS = -fuse-ld=$(LD) \ - -nostdlib \ - -Wl,-T,$(LD_SCRIPT) \ - -Wl,--fatal-warnings - -$(TGT): $(OBJ) $(LD_SCRIPT) - $(CC) $(LD_FLAGS) -o $@ $^ - -$(DMP): $(TGT) - $(DAS) $(DUMP_FLAGS) $< > $@ - -.PHONY: iso -iso: $(TGT) $(GRUB_CFG) - mkdir -p $(OUT)/temp/secX - mkdir -p $(OUT)/temp/boot - mkdir -p $(OUT)/temp/boot/grub - cp $(TGT) $(OUT)/temp/secX/ - cp $(GRUB_CFG) $(OUT)/temp/boot/grub/ - grub-mkrescue -o $(ISO) $(OUT)/temp - -.PHONY: clean -clean: - rm -rf $(OUT) - -.PHONY: compile -compile: $(TGT) $(DMP) - -.PHONY: all -all: compile iso - -include $(MK)/epilogue.mk diff --git a/arch/CMakeLists.txt b/arch/CMakeLists.txt new file mode 100644 index 0000000..83cf40a --- /dev/null +++ b/arch/CMakeLists.txt @@ -0,0 +1,16 @@ +set(SUBMODULE arch) +set(CC_SRC + cpu.c + init.c + intr.c + mem.c + print.c + brute.c) + +set(AS_SRC + boot.asm + mb_hdr.asm + cpu.asm + intr.asm) + +include(${MK}/kern.cmake) \ No newline at end of file diff --git a/hal/boot.asm.in b/arch/boot.asm similarity index 93% rename from hal/boot.asm.in rename to arch/boot.asm index be17e82..6aee072 100644 --- a/hal/boot.asm.in +++ b/arch/boot.asm @@ -1,18 +1,17 @@ #define ASM_FILE -#include "mlayout.h" +#include <arch/mlayout.h> #include "multiboot2.h" -%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR) +%define GET_PADDR(x) ((x) - KERNEL_IMG_VADDR) %define GET_PML4(vaddr) (((vaddr) >> 39 ) & 0x1FF) %define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF) -global sys_entry -global sys_entry_64 -extern hmain +global arch_init_32 +extern arch_main section .text bits 32 -sys_entry: +arch_init_32: cli cld cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC @@ -35,10 +34,9 @@ sys_entry: mov eax, GET_PADDR(init_pml4) mov dword [eax], GET_PADDR(init_pdpt_iden) + 11b ; write the lower bits, higher = 0 ; point the nth PML4 entry to the kernel pdpt - add eax, GET_PML4(KERNEL_IMAGE_VADDR) * 8 + add eax, GET_PML4(KERNEL_SPACE_VADDR) * 8 mov dword [eax], GET_PADDR(init_pdpt_kern) + 11b - ; identity map the first 4GB mov eax, GET_PADDR(init_pdpt_iden) mov ebx, 10000011b ; R/W + SU + 1G page @@ -52,7 +50,7 @@ sys_entry: ; map the first 1 GB, which contains the kernel, to KERNEL_BASE_VADDR mov eax, GET_PADDR(init_pdpt_kern) ; extract the PML4 entry - add eax, GET_PDPT(KERNEL_IMAGE_VADDR) * 8 + add eax, GET_PDPT(KERNEL_SPACE_VADDR) * 8 mov ebx, 10000011b ; R/W + SU + 1G page mov dword [eax], ebx @@ -82,10 +80,9 @@ sys_entry: lgdt [GET_PADDR(init_gdt.ptr)] ; switch to long mode - jmp init_gdt.code:GET_PADDR(sys_entry_64) + jmp init_gdt.code:GET_PADDR(arch_init_64) .end: - hlt - + jmp $ check_long_mode: push ebp @@ -126,7 +123,7 @@ multiboot_info_ptr: section .text bits 64 -sys_entry_64: +arch_init_64: ; note that we are in long mode but rip is still lower ; switch to high address mov rax, .high @@ -140,10 +137,12 @@ sys_entry_64: mov gs,ax mov ss,ax + ; initial kernel stack, 4k mov rsp, init_stack xor rdi, rdi mov edi, dword [multiboot_info_ptr] - call hmain + ; init arch + call arch_main .end: hlt diff --git a/arch/brute.c b/arch/brute.c new file mode 100644 index 0000000..3ceafd9 --- /dev/null +++ b/arch/brute.c @@ -0,0 +1,6 @@ +#include <arch/brute.h> + +void arch_brute() +{ + while(1) {} +} diff --git a/arch/cpu.asm b/arch/cpu.asm new file mode 100644 index 0000000..c1f6680 --- /dev/null +++ b/arch/cpu.asm @@ -0,0 +1,229 @@ +;Functions preserve the registers rbx, rsp, rbp, r12, r13, r14, and 15 +;rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers. +;function parameter: rdi,rsi,rdx,rcx,r8,r9 + +global arch_flush_gdt +global arch_flush_tlb +global arch_flush_idt +global arch_read_idt +global arch_read_cr3 +global arch_write_cr3 +global arch_read_cr8 +global arch_write_cr8 +global arch_cpuid +global arch_halt_cpu +global arch_read_msr +global arch_write_msr + + +section .text +bits 64 + +; uint64* arch_random_int64(void) +; Returns a random 64-bit integer +global arch_random_int64 +arch_random_int64: +rdrand rax +ret + +; uint32* arch_random_int32(void) +; Returns a random 32-bit integer +global arch_random_int32 +arch_random_int32: +rdrand eax +ret + + + +arch_flush_gdt: +push rbp +mov rbp,rsp +lgdt [rdi] +;reload cs + +push rdx ; data_slct : ss +push rbp ; rsp + +pushfq +pop rax +push rax ; eflags + +push rsi ; cs +mov rax, .reload +push rax ;rip +iretq +.reload: +mov es,dx +mov fs,dx +mov gs,dx +mov ds,dx +pop rbp +ret + + +arch_flush_tlb: +mov rax,cr3 +mov cr3,rax +ret + + +arch_flush_idt: +lidt [rdi] +ret + +;====================== +global arch_read_idt +arch_read_idt: +sidt [rdi] +ret + +;====================== +global arch_read_cr3 +arch_read_cr3: +mov rax,cr3 +ret + +;====================== +global arch_write_cr3 +arch_write_cr3: +mov cr3,rdi +ret + +;====================== +global arch_read_cr8 +arch_read_cr8: +mov rax,cr8 +ret + +;====================== +global arch_write_cr8 +arch_write_cr8: +mov cr8,rdi +ret + +;====================== +global arch_halt +arch_halt: +hlt + + +; ============================ +; extern void KAPI arch_cpuid(uint32* eax, uint32* ebx, uint32* ecx, uint32* edx); +global arch_cpuid +arch_cpuid: +push rbp +mov rbp,rsp +; preserve rbx,rcx,rdx +push rbx +push rcx +push rdx +; cpuid parameters eax,ecx +mov eax, dword [rdi] +mov ecx, dword [rdx] +cpuid +; write results back to memory +mov dword [rdi], eax +mov dword [rsi], ebx +pop r11 +mov dword [r11], ecx +pop r11 +mov dword [r11], edx +pop rbx +mov rsp,rbp +pop rbp +ret + +;==================== +global arch_halt_cpu +arch_halt_cpu: +.loop: +hlt +jmp .loop + +;==================== +;(uint32 *ecx, uint32* edx, uint32* eax) +global arch_read_msr +arch_read_msr: +; preserve rdx +push rdx +mov ecx, dword [rdi] +rdmsr +mov dword [rdi], ecx +mov dword [rsi], edx +pop r11 +mov dword [r11], eax +ret + +;==================== +;(uint32 *ecx, uint32* edx, uint32* eax) +global arch_write_msr +arch_write_msr: +mov ecx, dword [rdi] +mov eax, dword [rdx] +mov edx, dword [rsi] +wrmsr +ret + + +global arch_write_port_16 +global arch_write_port_32 +global arch_write_port_8 +global arch_read_port_8 +global arch_read_port_16 +global arch_read_port_32 + +arch_write_port_32: +mov rdx,rdi +mov rax,rsi +out dx,eax +nop +nop +nop +ret + + +arch_write_port_16: +mov rdx,rdi +mov rax,rsi +out dx,ax +nop +nop +nop +ret + + +arch_write_port_8: +mov rdx,rdi +mov rax,rsi +out dx,al +nop +nop +nop +ret + +arch_read_port_8: +mov rdx,rdi +xor rax,rax +in al,dx +nop +nop +nop +ret + +arch_read_port_16: +mov rdx,rdi +xor rax,rax +in ax,dx +nop +nop +nop +ret + +arch_read_port_32: +mov rdx,rdi +xor rax,rax +in eax,dx +nop +nop +nop +ret \ No newline at end of file diff --git a/arch/cpu.c b/arch/cpu.c new file mode 100644 index 0000000..24f4979 --- /dev/null +++ b/arch/cpu.c @@ -0,0 +1,82 @@ +#include <kern/cdef.h> + +#include "cpu.h" + +#define GDT_ENTRY_SIZE 8 +#define GDT_ENTRY_NUM 9 + +#define SEG_GRANULARITY (1ull << 55) +#define SEG_LONG (1ull << 53) +#define SEG_DPL_0 (0ull << 45) +#define SEG_DPL_1 (1ull << 45) +#define SEG_DPL_2 (2ull << 45) +#define SEG_DPL_3 (3ull << 45) +#define SEG_PRESENT (1ull << 47) +#define SEG_CODE_DATA (1ull << 44) +#define SEG_TYPE_DATA_RW (2ull << 40) +#define SEG_TYPE_DATA_R (0ull << 40) +#define SEG_TYPE_CODE_X (8ull << 40) +#define SEG_TYPE_CODE_XR (10ull << 40) +#define SEG_TYPE_CODE_XC (12ull << 40) +#define SEG_TYPE_CODE_XRC (14ull << 40) +#define SEG_AVAILABLE (1ull << 52) +#define SEG_32_BITS (1ull << 54) + +static uint8 _gdts[HAL_CORE_COUNT][GDT_ENTRY_NUM * GDT_ENTRY_SIZE]; +static struct hal_gdt_ptr _gdt_ptrs[HAL_CORE_COUNT]; + +static inline uint32 seg_selector(uint32 index, uint32 rpl) +{ + return (index << 3) + rpl; +} + + +static void +write_segment_descriptor(void *const gdt, uint32 const base, uint32 const limit, uint64 const attr) +{ + if (gdt == NULL) { + return; + } + uint64 const seg_desc = (((uint64) base & 0xFFFF) << 16) | ((((uint64) base >> 16) & 0xFF) << 32) | + ((((uint64) base >> 24) & 0xFF) << 56) | ((uint64) limit & 0xFFFF) | + ((((uint64) limit >> 16) & 0xF) << 48) | attr; + ((uint8 *) gdt)[0] = (uint8) (seg_desc & 0xFF); + ((uint8 *) gdt)[1] = (uint8) ((seg_desc >> 8) & 0xFF); + ((uint8 *) gdt)[2] = (uint8) ((seg_desc >> 16) & 0xFF); + ((uint8 *) gdt)[3] = (uint8) ((seg_desc >> 24) & 0xFF); + ((uint8 *) gdt)[4] = (uint8) ((seg_desc >> 32) & 0xFF); + ((uint8 *) gdt)[5] = (uint8) ((seg_desc >> 40) & 0xFF); + ((uint8 *) gdt)[6] = (uint8) ((seg_desc >> 48) & 0xFF); + ((uint8 *) gdt)[7] = (uint8) ((seg_desc >> 56) & 0xFF); +} + +void hal_init_gdt(void) +{ + uint32 coreid = 0; + // get gdt ready + write_segment_descriptor((void *) &_gdts[coreid][0], 0, 0, 0); + write_segment_descriptor((void *) &_gdts[coreid][8], 0, 0, + SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X); + write_segment_descriptor((void *) &_gdts[coreid][16], 0, 0, + SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW); + write_segment_descriptor((void *) &_gdts[coreid][24], 0, 0, + SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X); + write_segment_descriptor((void *) &_gdts[coreid][32], 0, 0, + SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW); + + write_segment_descriptor((void *) &_gdts[coreid][40], 0, 0xFFFFF, + SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | + SEG_TYPE_CODE_X); + write_segment_descriptor((void *) &_gdts[coreid][48], 0, 0xFFFFF, + SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | + SEG_TYPE_DATA_RW); + write_segment_descriptor((void *) &_gdts[coreid][56], 0, 0xFFFFF, + SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | + SEG_TYPE_CODE_X); + write_segment_descriptor((void *) &_gdts[coreid][64], 0, 0xFFFFF, + SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | + SEG_TYPE_DATA_RW); + _gdt_ptrs[coreid].base = (uint64) &_gdts[coreid]; + _gdt_ptrs[coreid].limit = GDT_ENTRY_NUM * GDT_ENTRY_SIZE - 1; + arch_flush_gdt(&_gdt_ptrs[coreid], seg_selector(1, 0), seg_selector(2, 0)); +} diff --git a/arch/cpu.h b/arch/cpu.h new file mode 100644 index 0000000..3981c30 --- /dev/null +++ b/arch/cpu.h @@ -0,0 +1,92 @@ +#pragma once + +#include <kern/cdef.h> + +#define HAL_CORE_COUNT 1 +struct ATTR_PACKED hal_gdt_ptr { + uint16 limit; + uint64 base; +}; + +struct ATTR_PACKED hal_idt_ptr { + uint16 limit; + uint64 base; +}; + +void KABI out_8(uint16 port, uint8 data); + +void KABI out_16(uint16 port, uint16 data); + +void KABI out_32(uint16 port, uint32 data); + +uint8 KABI in_8(uint16 port); + +uint16 KABI in_16(uint16 port); + +uint32 KABI in_32(uint16 port); + +void KABI flush_gdt(void *gdt_ptr, uint16 code_slct, uint16 data_slct); + +void KABI flush_idt(void *idt_ptr); + +void KABI flush_tss(uint16 tss_slct); + +void KABI cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx); + +void KABI read_msr(uint32 *ecx, uint32 *edx, uint32 *eax); + +void KABI write_msr(uint32 *ecx, uint32 *edx, uint32 *eax); + +void KABI sti(); + +void KABI cli(); + +uint64 KABI read_cr8(); + +void KABI write_cr8(uint64 val); + +uint64 KABI read_cr3(); + +void KABI write_cr3(uint64 val); + +void KABI flush_tlb(); + + +/** + * ASM declaration + */ +void KABI arch_cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx); + +void KABI arch_halt(void); + +void KABI arch_flush_gdt(struct hal_gdt_ptr *gdt_ptr, uint64 code_slct, uint64 data_slct); + +void KABI arch_flush_tlb(void); + +void KABI arch_flush_idt(struct hal_idt_ptr *idt_ptr); + +void KABI arch_read_idt(struct hal_idt_ptr **idt_ptr); + +void KABI arch_read_msr(uint32 *ecx, uint32 *edx, uint32 *eax); + +void KABI arch_write_msr(uint32 *ecx, uint32 *edx, uint32 *eax); + +void KABI arch_write_cr3(uint64 base); + +uint64 KABI arch_read_cr3(void); + +void KABI arch_write_cr8(uint64 pri); + +uint64 KABI arch_read_cr8(void); + +int8 KABI arch_read_port_8(uint16 port); + +int16 KABI arch_read_port_16(uint16 port); + +int32 KABI arch_read_port_32(uint16 port); + +void KABI arch_write_port_8(uint16 port, uint8 data); + +void KABI arch_write_port_16(uint16 port, uint16 data); + +void KABI arch_write_port_32(uint16 port, uint32 data); diff --git a/hal/boot.c b/arch/init.c similarity index 67% rename from hal/boot.c rename to arch/init.c index d5f3736..103088d 100644 --- a/hal/boot.c +++ b/arch/init.c @@ -1,30 +1,21 @@ -#include "mem.h" -#include "print.h" -#include "intr.h" -#include "cpu.h" -#include "kernel.h" -#include "hal.h" +#include <kern/cdef.h> +#include <kern/print.h> +#include <arch/print.h> +#include <arch/brute.h> + +// private headers #include "multiboot2.h" -//static void -//halp_obtain_cpu_info(struct boot_info *hal_info) -//{ -// if (hal_info == NULL) -// { -// return; -// } -// uint32 eax = 0, ebx = 0, ecx = 0, edx = 0; -// hal_cpuid(&eax, &ebx, &ecx, &edx); -// mem_cpy(&ebx, &hal_info->cpu_vd_str[0], sizeof(uint32)); -// mem_cpy(&edx, &hal_info->cpu_vd_str[4], sizeof(uint32)); -// mem_cpy(&ecx, &hal_info->cpu_vd_str[8], sizeof(uint32)); -// hal_info->cpu_vd_str[12] = 0; -//} - -void HABI -hmain(struct multiboot_tag *mb_info) +void arch_main(ATTR_UNUSED void* mb_info) { - if (mb_info == NULL) + /* init printf related stuff */ + arch_print_init(); + + kprintf("Initializing arch layer...\n"); + + arch_brute(); + +/* if (mb_info == NULL) { goto err; } @@ -76,5 +67,5 @@ hmain(struct multiboot_tag *mb_info) kmain(boot_info); err: - hal_halt_cpu(); + hal_halt_cpu(); */ } diff --git a/hal/intr.asm b/arch/intr.asm similarity index 98% rename from hal/intr.asm rename to arch/intr.asm index d6db533..b2db823 100644 --- a/hal/intr.asm +++ b/arch/intr.asm @@ -1,15 +1,3 @@ -global hal_disable_interrupt -global hal_enable_interrupt - -hal_disable_interrupt: -cli -ret - -hal_enable_interrupt: -sti -ret - - %macro PUSHAQ 0 push rax ;save current rax push rbx ;save current rbx @@ -37,7 +25,7 @@ ret pop r10 ;restore current r10 pop r9 ;restore current r9 pop r8 ;restore current r8 - pop rsi ;restore current rsi + pop rsi ;restore current rsix pop rdi ;restore current rdi pop rbp ;restore current rbp pop rdx ;restore current rdx @@ -85,6 +73,7 @@ hal_interrupt_handler_%1: ; +0 RBP push rbp mov rbp,rsp + PUSHAQ cld mov rdi, %1 ; INT VEC # diff --git a/arch/intr.c b/arch/intr.c new file mode 100644 index 0000000..6f3c7e9 --- /dev/null +++ b/arch/intr.c @@ -0,0 +1,121 @@ +#include <arch/intr.h> +#include <arch/mem.h> +#include <arch/print.h> +#include <kern/print.h> +#include <kern/status.h> +#include <kern/brute.h> + +#include "cpu.h" + +#define HAL_CORE_COUNT 1 + +static uint8 cpu_idts[HAL_CORE_COUNT][IDT_ENTRY_NUM * IDT_ENTRY_SIZE]; +static struct hal_idt_ptr cpu_idt_ptrs[HAL_CORE_COUNT]; + +static void *k_intr_disps[HAL_CORE_COUNT]; + +int +arch_raise_irql(ATTR_UNUSED int irql) +{ + return 0; +} + +int +arch_lower_irql(ATTR_UNUSED int irql) +{ + return 0; +} + +int +arch_get_irql() +{ + return 0; +} + +void +hal_write_gate(void *gate, const uint64 offset, const uint32 selector, uint32 const attr) +{ + ((uint8 *) gate)[0] = (uint8) (offset & 0xFFu); + ((uint8 *) gate)[1] = (uint8) ((offset >> 8u) & 0xFFu); + ((uint8 *) gate)[2] = (uint8) (selector & 0xFFu); + ((uint8 *) gate)[3] = (uint8) ((selector >> 8u) & 0xFFu); + ((uint8 *) gate)[4] = (uint8) (attr & 0xFFu); + ((uint8 *) gate)[5] = (uint8) ((attr >> 8u) & 0xFFu); + ((uint8 *) gate)[6] = (uint8) ((offset >> 16u) & 0xFFu); + ((uint8 *) gate)[7] = (uint8) ((offset >> 24u) & 0xFFu); + ((uint8 *) gate)[8] = (uint8) ((offset >> 32u) & 0xFFu); + ((uint8 *) gate)[9] = (uint8) ((offset >> 40u) & 0xFFu); + ((uint8 *) gate)[10] = (uint8) ((offset >> 48u) & 0xFFu); + ((uint8 *) gate)[11] = (uint8) ((offset >> 56u) & 0xFFu); + ((uint8 *) gate)[12] = 0; + ((uint8 *) gate)[13] = 0; + ((uint8 *) gate)[14] = 0; + ((uint8 *) gate)[15] = 0; +} + +void KABI +hal_interrupt_dispatcher(uint64 int_vec, struct interrupt_context *context) +{ + uint32 coreid = 0; + if (k_intr_disps[coreid] == NULL) { + kprintf("Unhandled interrupt %ld at 0x%lx.\n", int_vec, context->rip); + } + /*else + { + k_intr_disps[coreid]((uint32) int_vec, context); + }*/ +} + +static void +populate_idt(void) +{ + +} + +void +arch_intr_init(void) +{ + uint32 coreid; + uint32 eax; + uint32 ebx; + uint32 ecx; + uint32 edx; + + // detect APIC first + eax = 1; + arch_cpuid(&eax, &ebx, &ecx, &edx); + if (!(edx & (1u << 9u))) { + BRUTE("ERROR: APIC is not present.\n"); + } + + coreid = 0; + + // get idt ptr ready + cpu_idt_ptrs[coreid].base = (uint64) &cpu_idts[coreid]; + cpu_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1; + + // clear dispatch table + k_intr_disps[coreid] = NULL; + + // hook asm interrupt handlers + populate_idt(); + + arch_flush_idt(&cpu_idt_ptrs[coreid]); + + // disable PIC + arch_write_port_8(0xa1, 0xff); + arch_write_port_8(0x21, 0xff); + + uint64 apic_base_reg = 0; + ATTR_UNUSED uint64 apic_base = 0; + ecx = 0; + arch_read_msr(&ecx, &edx, &eax); + apic_base_reg = ((uint64) edx << 32u) + (uint64) eax; + //apic_base = apic_base_reg & bit_field_mask(12, 35); + + + // hardware enable APIC + ecx = 0; + // eax = (uint32) ((apic_base_reg & bit_field_mask(0, 31)) | (1 << 11)); + arch_write_msr(&ecx, &edx, &eax); +} diff --git a/hal/mb_hdr.asm.in b/arch/mb_hdr.asm similarity index 97% rename from hal/mb_hdr.asm.in rename to arch/mb_hdr.asm index 542a0d2..cd90ab6 100644 --- a/hal/mb_hdr.asm.in +++ b/arch/mb_hdr.asm @@ -1,6 +1,6 @@ #define ASM_FILE #include "multiboot2.h" -#include "mlayout.h" +#include <arch/mlayout.h> extern hmain global hal_main_32 diff --git a/hal/inc/mem.h b/arch/mem.c similarity index 50% rename from hal/inc/mem.h rename to arch/mem.c index bb1e8b3..91a7ddd 100644 --- a/hal/inc/mem.h +++ b/arch/mem.c @@ -1,33 +1,6 @@ -#pragma once - -#include "cdef.h" -#include "mem.h" -#include "multiboot2.h" - -/** - Global Descriptors Table Definitions -**/ - -#define GDT_ENTRY_SIZE 8 -#define GDT_ENTRY_NUM 9 - -#define SEG_GRANULARITY (1ull << 55) -#define SEG_LONG (1ull << 53) -#define SEG_DPL_0 (0ull << 45) -#define SEG_DPL_1 (1ull << 45) -#define SEG_DPL_2 (2ull << 45) -#define SEG_DPL_3 (3ull << 45) -#define SEG_PRESENT (1ull << 47) -#define SEG_CODE_DATA (1ull << 44) -#define SEG_TYPE_DATA_RW (2ull << 40) -#define SEG_TYPE_DATA_R (0ull << 40) -#define SEG_TYPE_CODE_X (8ull << 40) -#define SEG_TYPE_CODE_XR (10ull << 40) -#define SEG_TYPE_CODE_XC (12ull << 40) -#define SEG_TYPE_CODE_XRC (14ull << 40) -#define SEG_AVAILABLE (1ull << 52) -#define SEG_32_BITS (1ull << 54) - +#include <kern/cdef.h> +#include <arch/mem.h> +#include <arch/mlayout.h> /** Page Table Definitions @@ -73,39 +46,21 @@ #define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF) #define PT_ENTRY_NUM(vaddr) (((vaddr) >> 12) & 0x1FF) -static inline uint32 seg_selector(uint32 index, uint32 rpl) +void +write_page_tbl(void *base, uintptr pdpt_addr, uint64 attr) { - return (index << 3) + rpl; + if (base == NULL) + { + return; + } + uint64 entry = (pdpt_addr & 0xFFFFFFFFFF000ul) | attr; + ((uint8 *) base)[0] = (uint8) (entry & 0xFFul); + ((uint8 *) base)[1] = (uint8) ((entry >> 8u) & 0xFFu); + ((uint8 *) base)[2] = (uint8) ((entry >> 16u) & 0xFFu); + ((uint8 *) base)[3] = (uint8) ((entry >> 24u) & 0xFFu); + ((uint8 *) base)[4] = (uint8) ((entry >> 32u) & 0xFFu); + ((uint8 *) base)[5] = (uint8) ((entry >> 40u) & 0xFFu); + ((uint8 *) base)[6] = (uint8) ((entry >> 48u) & 0xFFu); + ((uint8 *) base)[7] = (uint8) ((entry >> 56u) & 0xFFu); } -void -hal_write_segment_descriptor(void *gdt, uint32 base, uint32 limit, uint64 attr); - -void -hal_write_pml4(void *base, uintptr pdpt_addr, uint64 attr); - -void -hal_write_pdpt(void *base, uintptr pd_addr, uint64 attr); - -void -hal_write_pd(void *base, uintptr pt_addr, uint64 attr); - -void -hal_write_pt(void *base, uintptr p_addr, uint64 attr); - -uint32 -hal_write_initial_page_table(void *multiboot_info); - -/** - Function Defn -**/ - -void * -halloc(uint32 size); - -void -hfree(void *ptr); - -void -hal_mem_init(struct multiboot_tag_mmap *info); - diff --git a/hal/inc/multiboot2.h b/arch/multiboot2.h similarity index 100% rename from hal/inc/multiboot2.h rename to arch/multiboot2.h diff --git a/arch/print.c b/arch/print.c new file mode 100644 index 0000000..87eaed3 --- /dev/null +++ b/arch/print.c @@ -0,0 +1,60 @@ +#include <kern/cdef.h> +#include <arch/mem.h> +#include <kern/libkern.h> + +#define FB_PADDR (0xb8000) +#define FB_ROW (25) +#define FB_COL (80) +#define BYTE_PER_CHAR (2) +#define FB_SZ (FB_ROW * FB_COL * BYTE_PER_CHAR) +#define DEFAULT_COLOR (0x07) + +static char *base; +static uint text_pos; + +static void +_fb_scroll() +{ + memmove(base, base + FB_COL * BYTE_PER_CHAR, FB_SZ - (FB_COL * BYTE_PER_CHAR)); + text_pos = FB_SZ - (FB_COL * BYTE_PER_CHAR); +} + +static void +_print_newline(void) +{ + text_pos += FB_COL * BYTE_PER_CHAR - text_pos % (FB_COL * BYTE_PER_CHAR); + + if (text_pos >= FB_SZ) { + _fb_scroll(); + } +} + +void +arch_print_init(void) +{ + // 0 here since it doesn't matter direct mapped + base = arch_pmap_map(FB_PADDR, FB_SZ); + text_pos = 0; +} + +void +arch_cls() +{ + memset(base, 0, FB_SZ); +} + +void +arch_putc(const char c) +{ + if (c == '\n') { + _print_newline(); + return; + } + + if (text_pos >= FB_SZ) { + _fb_scroll(); + } + + base[text_pos++] = c; + base[text_pos++] = DEFAULT_COLOR; +} diff --git a/bootstrap_deb.sh b/bootstrap_deb.sh deleted file mode 100644 index eeba4ea..0000000 --- a/bootstrap_deb.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# Bootstrap debian 9 + clang-6.0 backport environment -# Personal use only -export CC_ENV=clang-6.0 -export LD_ENV=lld-6.0 -export DAS_ENV=llvm-objdump-6.0 -export AS_ENV=nasm \ No newline at end of file diff --git a/common/Rules.mk b/common/Rules.mk deleted file mode 100644 index 2340d0a..0000000 --- a/common/Rules.mk +++ /dev/null @@ -1,9 +0,0 @@ -include $(MK)/prologue.mk - -MOD:=COMMON - -SRC_$(d) := $(d)/clib.c - -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/common/clib.c b/common/clib.c deleted file mode 100644 index 7211919..0000000 --- a/common/clib.c +++ /dev/null @@ -1,121 +0,0 @@ - -#include "cdef.h" -#include "clib.h" - -void -mem_cpy(void *src, void *dst, uint64 size) -{ - if (src == NULL || dst == NULL) - { - return; - } - char *cSrc = (char *) src; - char *cDst = (char *) dst; - while (size--) - { - *(cDst++) = *(cSrc++); - } -} - -void -mem_set(void *src, uint8 val, uint64 size) -{ - if (src == NULL) - { - return; - } - while (size--) - { - *(uint8 *) src = val; - src = (void *) ((uintptr) src + 1); - } -} - -void -mem_mv(void *src, void *dst, uint64 size) -{ - if (src == NULL || dst == NULL) - { - return; - } - if (src >= dst) - { - mem_cpy(src, dst, size); - return; - } - src = (void *) ((uintptr) src + size - 1); - dst = (void *) ((uintptr) dst + size - 1); - while (size--) - { - *(char *) dst = *(char *) src; - dst = (void *) ((uintptr) dst - 1); - src = (void *) ((uintptr) src - 1); - } -} - -// -// Random Generator -// -static uint32 seed = 1; -static uint32 max = 16777215; - -uint32 -lb_rand(void) -{ - seed = seed * 1103512986 + 29865; - return (unsigned int) (seed / 65536) % (max + 1); -} - -void -lb_srand(uint32 _seed) -{ - seed = _seed; -} - -void -lb_mrand(uint32 _max) -{ - max = _max; -} - -// -// String Library -// - -uint64 -str_len(char const *str) -{ - uint64 length = 0; - if (str == NULL) - { - return 0; - } - while (*str != 0) - { - str++; - length++; - } - return length; -} - -uint64 -str_cmp(char const *str1, char const *str2) -{ - if (str1 == NULL || str2 == NULL) - { - return 0; - } - uint64 length = str_len(str1); - if (length != str_len(str2)) - { - return 0; - } - while (length--) - { - if (*(str1 + length) != *(str2 + length)) - { - return 0; - } - } - return 1; -} diff --git a/gdbq b/gdbq deleted file mode 100644 index 5ca3e04..0000000 --- a/gdbq +++ /dev/null @@ -1,4 +0,0 @@ -file out/secxkrnl.elf -set arch i386:x86-64 -target remote localhost:1234 -break hmain \ No newline at end of file diff --git a/gdbw b/gdbw deleted file mode 100644 index e5e8d74..0000000 --- a/gdbw +++ /dev/null @@ -1,3 +0,0 @@ -disconnect -set arch i386:x86-64:intel -target remote localhost:1234 \ No newline at end of file diff --git a/hal/Rules.mk b/hal/Rules.mk deleted file mode 100644 index 067ee76..0000000 --- a/hal/Rules.mk +++ /dev/null @@ -1,36 +0,0 @@ -include $(MK)/prologue.mk - -MOD:=HAL -C_FLAGS_$(MOD):=$(addprefix -I, $(d)/inc) -AS_FLAGS_$(MOD):=$(addprefix -I, $(d)/inc) - -SRC_$(d) := $(d)/boot.c \ - $(d)/intr.c \ - $(d)/mem.c \ - $(d)/print.c \ - $(d)/hal.c - -SRCAS_$(d) := $(d)/cpu.asm \ - $(d)/intr.asm \ - $(d)/io.asm \ - $(d)/atomic.asm - -SRCIN_$(d) := $(d)/boot.asm.in \ - $(d)/mb_hdr.asm.in - -#special rules for preprocessed asm files -$(OUT)/$(d)/mb_hdr.a: $(OUT)/$(d)/mb_hdr.asm - $(MKDIR) - $(COMPAS) - -$(OUT)/$(d)/boot.a: $(OUT)/$(d)/boot.asm - $(MKDIR) - $(COMPAS) - -OBJ := $(OBJ) $(OUT)/$(d)/boot.a $(OUT)/$(d)/mb_hdr.a -CLEAN := $(CLEAN) $(OUT)/$(d)/boot.a $(OUT)/$(d)/mb_hdr.a - -# include this at last -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/hal/atomic.asm b/hal/atomic.asm deleted file mode 100644 index 827472e..0000000 --- a/hal/atomic.asm +++ /dev/null @@ -1,28 +0,0 @@ - -section .text -bits 64 -; ============================ -; int32 KAPI hal_interlocked_exchange_32(int32 *target, int32 val) -global hal_interlocked_exchange_32 -hal_interlocked_exchange_32: -lock xchg dword [rdi], esi -xor rax, rax -mov eax, esi -ret - -; ============================ -; int32 KAPI hal_interlocked_compare_exchange_32(int32 *dst, int32 test_node_compare, int32 val); -global hal_interlocked_compare_exchange_32 -hal_interlocked_compare_exchange_32: -mov eax, esi; eax = test_node_compare -lock cmpxchg dword [rdi], edx ; edx = val, rdi = ptr to dst -ret - -; ============================ -; int32 KAPI hal_interlocked_increment_32(int32 *target, int32 increment); -global hal_interlocked_increment_32 -hal_interlocked_increment_32: -lock xadd dword [rdi], esi ; [rdi] = [rdi] + esi, esi = old [rdi] -xor rax, rax -mov eax, esi -ret diff --git a/hal/cpu.asm b/hal/cpu.asm deleted file mode 100644 index fe305be..0000000 --- a/hal/cpu.asm +++ /dev/null @@ -1,143 +0,0 @@ -;Functions preserve the registers rbx, rsp, rbp, r12, r13, r14, and 15 -;rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers. -;function parameter: rdi,rsi,rdx,rcx,r8,r9 - -global hal_flush_gdt -global hal_flush_tlb -global hal_flush_idt -global hal_read_idt -global hal_read_cr3 -global hal_write_cr3 -global hal_read_cr8 -global hal_write_cr8 -global hal_cpuid -global hal_halt_cpu -global hal_read_msr -global hal_write_msr - - -section .text -bits 64 - -hal_flush_gdt: -push rbp -mov rbp,rsp -lgdt [rdi] -;reload cs - -push rdx ; data_slct : ss -push rbp ; rsp - -pushfq -pop rax -push rax ; eflags - -push rsi ; cs -mov rax, .reload -push rax ;rip -iretq -.reload: -mov es,dx -mov fs,dx -mov gs,dx -mov ds,dx -pop rbp -ret - - -hal_flush_tlb: -mov rax,cr3 -mov cr3,rax -ret - - -hal_flush_idt: -lidt [rdi] -ret - -;====================== -global hal_read_idt -hal_read_idt: -sidt [rdi] -ret - -;====================== -global hal_read_cr3 -hal_read_cr3: -mov rax,cr3 -ret - -;====================== -global hal_write_cr3 -hal_write_cr3: -mov cr3,rdi -ret - -;====================== -global hal_read_cr8 -hal_read_cr8: -mov rax,cr8 -ret - -;====================== -global hal_write_cr8 -hal_write_cr8: -mov cr8,rdi -ret - -; ============================ -; extern void KAPI hal_cpuid(uint32* eax, uint32* ebx, uint32* ecx, uint32* edx); -global hal_cpuid -hal_cpuid: -push rbp -mov rbp,rsp -; preserve rbx,rcx,rdx -push rbx -push rcx -push rdx -; cpuid parameters eax,ecx -mov eax, dword [rdi] -mov ecx, dword [rdx] -cpuid -; write results back to memory -mov dword [rdi], eax -mov dword [rsi], ebx -pop r11 -mov dword [r11], ecx -pop r11 -mov dword [r11], edx -pop rbx -mov rsp,rbp -pop rbp -ret - -;==================== -global hal_halt_cpu -hal_halt_cpu: -.loop: -hlt -jmp .loop - -;==================== -;(uint32 *ecx, uint32* edx, uint32* eax) -global hal_read_msr -hal_read_msr: -; preserve rdx -push rdx -mov ecx, dword [rdi] -rdmsr -mov dword [rdi], ecx -mov dword [rsi], edx -pop r11 -mov dword [r11], eax -ret - -;==================== -;(uint32 *ecx, uint32* edx, uint32* eax) -global hal_write_msr -hal_write_msr: -mov ecx, dword [rdi] -mov eax, dword [rdx] -mov edx, dword [rsi] -wrmsr -ret \ No newline at end of file diff --git a/hal/hal.c b/hal/hal.c deleted file mode 100644 index f4c0971..0000000 --- a/hal/hal.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "hal.h" -#include "cpu.h" -#include "intr.h" -#include "io.h" -#include "mem.h" -#include "atomic.h" - -/** - * Provides implementations to HAL functions - * required by kernel in hal.h - */ - -int32 KABI -hal_atomic_xchg_32(int32 *target, int32 val) -{ - return hal_interlocked_exchange_32(target, val); -} - -int32 KABI -hal_atomic_inc_32(int32 *target, int32 increment) -{ - return hal_interlocked_increment_32(target, increment); -} - -int32 KABI -hal_atomic_cmpxchg_32(int32 *target, int32 compare, int32 val) -{ - return hal_interlocked_compare_exchange_32(target, compare, val); -} - -uint32 KABI -hal_set_irql(uint32 irql) -{ - return impl_hal_set_irql(irql); -} - -uint32 KABI -hal_get_irql(void) -{ - return impl_hal_get_irql(); -} - -void KABI -hal_halt(void) -{ - hal_halt_cpu(); -} - -void KABI -hal_issue_intr(uint32 core, uint32 vector) -{ - impl_hal_issue_intr(core, vector); -} - -void KABI -hal_set_intr_dispatcher(k_intr_dispatcher handler) -{ - impl_hal_set_intr_dispatcher(handler); -} - -void KABI -hal_set_exc_dispatcher(k_exc_dispatcher handler) -{ - impl_hal_set_exc_dispatcher(handler); -} - -uint32 KABI -hal_get_core_id(void) -{ - return impl_hal_get_core_id(); -} diff --git a/hal/inc/atomic.h b/hal/inc/atomic.h deleted file mode 100644 index aedd6cb..0000000 --- a/hal/inc/atomic.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "hdef.h" - -/** - * ASM declaration - */ - -int32 HABI hal_interlocked_exchange_32(int32 *target, int32 val); - -int32 HABI hal_interlocked_compare_exchange_32(int32 *dst, int32 test_node_compare, int32 val); - -int32 HABI hal_interlocked_increment_32(int32 *target, int32 increment); diff --git a/hal/inc/cpu.h b/hal/inc/cpu.h deleted file mode 100644 index ade7a1d..0000000 --- a/hal/inc/cpu.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "hdef.h" - -#define HAL_CORE_COUNT 1 - -struct PRAGMA_PACKED hal_gdt_ptr -{ - uint16 limit; - uint64 base; -}; - -struct PRAGMA_PACKED hal_idt_ptr -{ - uint16 limit; - uint64 base; -}; - -/** - * ASM declaration - */ - -void HABI hal_cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx); - -void HABI hal_halt_cpu(void); - -void HABI hal_flush_gdt(struct hal_gdt_ptr *gdt_ptr, uint64 code_slct, uint64 data_slct); - -void HABI hal_flush_tlb(void); - -void HABI hal_flush_idt(struct hal_idt_ptr *idt_ptr); - -void HABI hal_read_idt(struct hal_idt_ptr **idt_ptr); - -#define MSR_IA32_APIC_BASE 0x1B - -void HABI hal_read_msr(uint32 *ecx, uint32 *edx, uint32 *eax); - -void HABI hal_write_msr(uint32 *ecx, uint32 *edx, uint32 *eax); - -void HABI hal_write_cr3(uint64 base); - -uint64 HABI hal_read_cr3(void); - -void HABI hal_write_cr8(uint64 pri); - -uint64 HABI hal_read_cr8(void); - diff --git a/hal/inc/hdef.h b/hal/inc/hdef.h deleted file mode 100644 index 5063525..0000000 --- a/hal/inc/hdef.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "cdef.h" - -#define HABI KABI diff --git a/hal/inc/intr.h b/hal/inc/intr.h deleted file mode 100644 index fdc7756..0000000 --- a/hal/inc/intr.h +++ /dev/null @@ -1,1102 +0,0 @@ -#pragma once - -#include "hdef.h" -#include "intr.h" -#include "kernel.h" -#include "clib.h" -#include "hal.h" - -/** - * Interrupt context structure - */ -struct interrupt_context -{ - const uint64 rip; - const uint64 cs; - const uint64 rflags; - const uint64 rsp; - const uint64 ss; -}; - -/** - * IDT Defns - */ -#define GATE_DPL_0 (0ull << 13) -#define GATE_DPL_1 (1ull << 13) -#define GATE_DPL_2 (2ull << 13) -#define GATE_DPL_3 (3ull << 13) -#define GATE_PRESENT (1ull << 15) -#define GATE_TYPE_CALL (12ull << 8) -#define GATE_TYPE_INTERRUPT (14ull << 8) -#define GATE_TYPE_TRAP (15ull << 8) - -#define IDT_ENTRY_NUM 256 -#define IDT_ENTRY_SIZE 16 - -/** - * C declaration - */ -int32 -hal_interrupt_init(void); - -void -hal_write_gate(void * gate, uint64 offset, uint32 selector, uint32 attr); - -void -hal_set_interrupt_handler(uint64 index, void (*handler)(void)); - -uint32 -impl_hal_set_irql(uint32 irql); - -uint32 -impl_hal_get_irql(void); - -void -impl_hal_issue_intr(uint32 target_core, uint32 vector); - -void -impl_hal_set_intr_dispatcher(k_intr_dispatcher handler); - -void -impl_hal_set_exc_dispatcher(k_exc_dispatcher handler); - -uint32 -impl_hal_get_core_id(void); - -/** - * Exported Dispatchers for asm code - */ -void HABI -hal_interrupt_dispatcher(uint64 int_vec, struct interrupt_context *context); - -void HABI -hal_exception_dispatcher(uint64 exc_vec, struct interrupt_context *context, uint32 errorcode); - -/** - * ASM declaration - */ - -void HABI hal_enable_interrupt(void); - -void HABI hal_disable_interrupt(void); - -/** - * System exception Handlers - */ -void HABI -hal_interrupt_handler_0(void); - -void HABI -hal_interrupt_handler_1(void); - -void HABI -hal_interrupt_handler_2(void); - -void HABI -hal_interrupt_handler_3(void); - -void HABI -hal_interrupt_handler_4(void); - -void HABI -hal_interrupt_handler_5(void); - -void HABI -hal_interrupt_handler_6(void); - -void HABI -hal_interrupt_handler_7(void); - -void HABI -hal_interrupt_handler_8(void); - -void HABI - -hal_interrupt_handler_9(void); - -void HABI - -hal_interrupt_handler_10(void); - -void HABI - -hal_interrupt_handler_11(void); - -void HABI - -hal_interrupt_handler_12(void); - -void HABI - -hal_interrupt_handler_13(void); - -void HABI - -hal_interrupt_handler_14(void); - -void HABI - -hal_interrupt_handler_15(void); - -void HABI - -hal_interrupt_handler_16(void); - -void HABI - -hal_interrupt_handler_17(void); - -void HABI - -hal_interrupt_handler_18(void); - -void HABI - -hal_interrupt_handler_19(void); - -void HABI - -hal_interrupt_handler_20(void); - -void HABI - -hal_interrupt_handler_21(void); - -void HABI - -hal_interrupt_handler_22(void); - -void HABI - -hal_interrupt_handler_23(void); - -void HABI - -hal_interrupt_handler_24(void); - -void HABI - -hal_interrupt_handler_25(void); - -void HABI - -hal_interrupt_handler_26(void); - -void HABI - -hal_interrupt_handler_27(void); - -void HABI - -hal_interrupt_handler_28(void); - -void HABI - -hal_interrupt_handler_29(void); - -void HABI - -hal_interrupt_handler_30(void); - -void HABI - -hal_interrupt_handler_31(void); - -/** - * Kernel defined interrupt handlers - */ -void HABI - -hal_interrupt_handler_32(void); - -void HABI - -hal_interrupt_handler_33(void); - -void HABI - -hal_interrupt_handler_34(void); - -void HABI - -hal_interrupt_handler_35(void); - -void HABI - -hal_interrupt_handler_36(void); - -void HABI - -hal_interrupt_handler_37(void); - -void HABI - -hal_interrupt_handler_38(void); - -void HABI - -hal_interrupt_handler_39(void); - -void HABI - -hal_interrupt_handler_40(void); - -void HABI - -hal_interrupt_handler_41(void); - -void HABI - -hal_interrupt_handler_42(void); - -void HABI - -hal_interrupt_handler_43(void); - -void HABI - -hal_interrupt_handler_44(void); - -void HABI - -hal_interrupt_handler_45(void); - -void HABI - -hal_interrupt_handler_46(void); - -void HABI - -hal_interrupt_handler_47(void); - -void HABI - -hal_interrupt_handler_48(void); - -void HABI - -hal_interrupt_handler_49(void); - -void HABI - -hal_interrupt_handler_50(void); - -void HABI - -hal_interrupt_handler_51(void); - -void HABI - -hal_interrupt_handler_52(void); - -void HABI - -hal_interrupt_handler_53(void); - -void HABI - -hal_interrupt_handler_54(void); - -void HABI - -hal_interrupt_handler_55(void); - -void HABI - -hal_interrupt_handler_56(void); - -void HABI - -hal_interrupt_handler_57(void); - -void HABI - -hal_interrupt_handler_58(void); - -void HABI - -hal_interrupt_handler_59(void); - -void HABI - -hal_interrupt_handler_60(void); - -void HABI - -hal_interrupt_handler_61(void); - -void HABI - -hal_interrupt_handler_62(void); - -void HABI - -hal_interrupt_handler_63(void); - -void HABI - -hal_interrupt_handler_64(void); - -void HABI - -hal_interrupt_handler_65(void); - -void HABI - -hal_interrupt_handler_66(void); - -void HABI - -hal_interrupt_handler_67(void); - -void HABI - -hal_interrupt_handler_68(void); - -void HABI - -hal_interrupt_handler_69(void); - -void HABI - -hal_interrupt_handler_70(void); - -void HABI - -hal_interrupt_handler_71(void); - -void HABI - -hal_interrupt_handler_72(void); - -void HABI - -hal_interrupt_handler_73(void); - -void HABI - -hal_interrupt_handler_74(void); - -void HABI - -hal_interrupt_handler_75(void); - -void HABI - -hal_interrupt_handler_76(void); - -void HABI - -hal_interrupt_handler_77(void); - -void HABI - -hal_interrupt_handler_78(void); - -void HABI - -hal_interrupt_handler_79(void); - -void HABI - -hal_interrupt_handler_80(void); - -void HABI - -hal_interrupt_handler_81(void); - -void HABI - -hal_interrupt_handler_82(void); - -void HABI - -hal_interrupt_handler_83(void); - -void HABI - -hal_interrupt_handler_84(void); - -void HABI - -hal_interrupt_handler_85(void); - -void HABI - -hal_interrupt_handler_86(void); - -void HABI - -hal_interrupt_handler_87(void); - -void HABI - -hal_interrupt_handler_88(void); - -void HABI - -hal_interrupt_handler_89(void); - -void HABI - -hal_interrupt_handler_90(void); - -void HABI - -hal_interrupt_handler_91(void); - -void HABI - -hal_interrupt_handler_92(void); - -void HABI - -hal_interrupt_handler_93(void); - -void HABI - -hal_interrupt_handler_94(void); - -void HABI - -hal_interrupt_handler_95(void); - -void HABI - -hal_interrupt_handler_96(void); - -void HABI - -hal_interrupt_handler_97(void); - -void HABI - -hal_interrupt_handler_98(void); - -void HABI - -hal_interrupt_handler_99(void); - -void HABI - -hal_interrupt_handler_100(void); - -void HABI - -hal_interrupt_handler_101(void); - -void HABI - -hal_interrupt_handler_102(void); - -void HABI - -hal_interrupt_handler_103(void); - -void HABI - -hal_interrupt_handler_104(void); - -void HABI - -hal_interrupt_handler_105(void); - -void HABI - -hal_interrupt_handler_106(void); - -void HABI - -hal_interrupt_handler_107(void); - -void HABI - -hal_interrupt_handler_108(void); - -void HABI - -hal_interrupt_handler_109(void); - -void HABI - -hal_interrupt_handler_110(void); - -void HABI - -hal_interrupt_handler_111(void); - -void HABI - -hal_interrupt_handler_112(void); - -void HABI - -hal_interrupt_handler_113(void); - -void HABI - -hal_interrupt_handler_114(void); - -void HABI - -hal_interrupt_handler_115(void); - -void HABI - -hal_interrupt_handler_116(void); - -void HABI - -hal_interrupt_handler_117(void); - -void HABI - -hal_interrupt_handler_118(void); - -void HABI - -hal_interrupt_handler_119(void); - -void HABI - -hal_interrupt_handler_120(void); - -void HABI - -hal_interrupt_handler_121(void); - -void HABI - -hal_interrupt_handler_122(void); - -void HABI - -hal_interrupt_handler_123(void); - -void HABI - -hal_interrupt_handler_124(void); - -void HABI - -hal_interrupt_handler_125(void); - -void HABI - -hal_interrupt_handler_126(void); - -void HABI - -hal_interrupt_handler_127(void); - -void HABI - -hal_interrupt_handler_128(void); - -void HABI - -hal_interrupt_handler_129(void); - -void HABI - -hal_interrupt_handler_130(void); - -void HABI - -hal_interrupt_handler_131(void); - -void HABI - -hal_interrupt_handler_132(void); - -void HABI - -hal_interrupt_handler_133(void); - -void HABI - -hal_interrupt_handler_134(void); - -void HABI - -hal_interrupt_handler_135(void); - -void HABI - -hal_interrupt_handler_136(void); - -void HABI - -hal_interrupt_handler_137(void); - -void HABI - -hal_interrupt_handler_138(void); - -void HABI - -hal_interrupt_handler_139(void); - -void HABI - -hal_interrupt_handler_140(void); - -void HABI - -hal_interrupt_handler_141(void); - -void HABI - -hal_interrupt_handler_142(void); - -void HABI - -hal_interrupt_handler_143(void); - -void HABI - -hal_interrupt_handler_144(void); - -void HABI - -hal_interrupt_handler_145(void); - -void HABI - -hal_interrupt_handler_146(void); - -void HABI - -hal_interrupt_handler_147(void); - -void HABI - -hal_interrupt_handler_148(void); - -void HABI - -hal_interrupt_handler_149(void); - -void HABI - -hal_interrupt_handler_150(void); - -void HABI - -hal_interrupt_handler_151(void); - -void HABI - -hal_interrupt_handler_152(void); - -void HABI - -hal_interrupt_handler_153(void); - -void HABI - -hal_interrupt_handler_154(void); - -void HABI - -hal_interrupt_handler_155(void); - -void HABI - -hal_interrupt_handler_156(void); - -void HABI - -hal_interrupt_handler_157(void); - -void HABI - -hal_interrupt_handler_158(void); - -void HABI - -hal_interrupt_handler_159(void); - -void HABI - -hal_interrupt_handler_160(void); - -void HABI - -hal_interrupt_handler_161(void); - -void HABI - -hal_interrupt_handler_162(void); - -void HABI - -hal_interrupt_handler_163(void); - -void HABI - -hal_interrupt_handler_164(void); - -void HABI - -hal_interrupt_handler_165(void); - -void HABI - -hal_interrupt_handler_166(void); - -void HABI - -hal_interrupt_handler_167(void); - -void HABI - -hal_interrupt_handler_168(void); - -void HABI - -hal_interrupt_handler_169(void); - -void HABI - -hal_interrupt_handler_170(void); - -void HABI - -hal_interrupt_handler_171(void); - -void HABI - -hal_interrupt_handler_172(void); - -void HABI - -hal_interrupt_handler_173(void); - -void HABI - -hal_interrupt_handler_174(void); - -void HABI - -hal_interrupt_handler_175(void); - -void HABI - -hal_interrupt_handler_176(void); - -void HABI - -hal_interrupt_handler_177(void); - -void HABI - -hal_interrupt_handler_178(void); - -void HABI - -hal_interrupt_handler_179(void); - -void HABI - -hal_interrupt_handler_180(void); - -void HABI - -hal_interrupt_handler_181(void); - -void HABI - -hal_interrupt_handler_182(void); - -void HABI - -hal_interrupt_handler_183(void); - -void HABI - -hal_interrupt_handler_184(void); - -void HABI - -hal_interrupt_handler_185(void); - -void HABI - -hal_interrupt_handler_186(void); - -void HABI - -hal_interrupt_handler_187(void); - -void HABI - -hal_interrupt_handler_188(void); - -void HABI - -hal_interrupt_handler_189(void); - -void HABI - -hal_interrupt_handler_190(void); - -void HABI - -hal_interrupt_handler_191(void); - -void HABI - -hal_interrupt_handler_192(void); - -void HABI - -hal_interrupt_handler_193(void); - -void HABI - -hal_interrupt_handler_194(void); - -void HABI - -hal_interrupt_handler_195(void); - -void HABI - -hal_interrupt_handler_196(void); - -void HABI - -hal_interrupt_handler_197(void); - -void HABI - -hal_interrupt_handler_198(void); - -void HABI - -hal_interrupt_handler_199(void); - -void HABI - -hal_interrupt_handler_200(void); - -void HABI - -hal_interrupt_handler_201(void); - -void HABI - -hal_interrupt_handler_202(void); - -void HABI - -hal_interrupt_handler_203(void); - -void HABI - -hal_interrupt_handler_204(void); - -void HABI - -hal_interrupt_handler_205(void); - -void HABI - -hal_interrupt_handler_206(void); - -void HABI - -hal_interrupt_handler_207(void); - -void HABI - -hal_interrupt_handler_208(void); - -void HABI - -hal_interrupt_handler_209(void); - -void HABI - -hal_interrupt_handler_210(void); - -void HABI - -hal_interrupt_handler_211(void); - -void HABI - -hal_interrupt_handler_212(void); - -void HABI - -hal_interrupt_handler_213(void); - -void HABI - -hal_interrupt_handler_214(void); - -void HABI - -hal_interrupt_handler_215(void); - -void HABI - -hal_interrupt_handler_216(void); - -void HABI - -hal_interrupt_handler_217(void); - -void HABI - -hal_interrupt_handler_218(void); - -void HABI - -hal_interrupt_handler_219(void); - -void HABI - -hal_interrupt_handler_220(void); - -void HABI - -hal_interrupt_handler_221(void); - -void HABI - -hal_interrupt_handler_222(void); - -void HABI - -hal_interrupt_handler_223(void); - -void HABI - -hal_interrupt_handler_224(void); - -void HABI - -hal_interrupt_handler_225(void); - -void HABI - -hal_interrupt_handler_226(void); - -void HABI - -hal_interrupt_handler_227(void); - -void HABI - -hal_interrupt_handler_228(void); - -void HABI - -hal_interrupt_handler_229(void); - -void HABI - -hal_interrupt_handler_230(void); - -void HABI - -hal_interrupt_handler_231(void); - -void HABI - -hal_interrupt_handler_232(void); - -void HABI - -hal_interrupt_handler_233(void); - -void HABI - -hal_interrupt_handler_234(void); - -void HABI - -hal_interrupt_handler_235(void); - -void HABI - -hal_interrupt_handler_236(void); - -void HABI - -hal_interrupt_handler_237(void); - -void HABI - -hal_interrupt_handler_238(void); - -void HABI - -hal_interrupt_handler_239(void); - -void HABI - -hal_interrupt_handler_240(void); - -void HABI - -hal_interrupt_handler_241(void); - -void HABI - -hal_interrupt_handler_242(void); - -void HABI - -hal_interrupt_handler_243(void); - -void HABI - -hal_interrupt_handler_244(void); - -void HABI - -hal_interrupt_handler_245(void); - -void HABI - -hal_interrupt_handler_246(void); - -void HABI - -hal_interrupt_handler_247(void); - -void HABI - -hal_interrupt_handler_248(void); - -void HABI - -hal_interrupt_handler_249(void); - -void HABI - -hal_interrupt_handler_250(void); - -void HABI - -hal_interrupt_handler_251(void); - -void HABI - -hal_interrupt_handler_252(void); - -void HABI - -hal_interrupt_handler_253(void); - -void HABI - -hal_interrupt_handler_254(void); - -void HABI - -hal_interrupt_handler_255(void); diff --git a/hal/inc/io.h b/hal/inc/io.h deleted file mode 100644 index 72058b4..0000000 --- a/hal/inc/io.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "hdef.h" - -/** - * ASM declarations - */ - -int8 HABI hal_read_port_8(uint16 port); - -int16 HABI hal_read_port_16(uint16 port); - -int32 HABI hal_read_port_32(uint16 port); - -void HABI hal_write_port_8(uint16 port, uint8 data); - -void HABI hal_write_port_16(uint16 port, uint16 data); - -void HABI hal_write_port_32(uint16 port, uint32 data); diff --git a/hal/inc/print.h b/hal/inc/print.h deleted file mode 100644 index 6392261..0000000 --- a/hal/inc/print.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "cdef.h" -#include "print.h" -#include "multiboot2.h" - -void -hal_assert(uint32 expression, char *message); - -void -hal_printf(const char *str, ...); - -void -hal_clear_screen(void); - -void -hal_print_init(struct multiboot_tag_framebuffer* info); diff --git a/hal/intr.c b/hal/intr.c deleted file mode 100644 index 77f2f1b..0000000 --- a/hal/intr.c +++ /dev/null @@ -1,442 +0,0 @@ - -#include "cpu.h" -#include "hdef.h" -#include "hal.h" -#include "intr.h" -#include "mem.h" -#include "print.h" -#include "io.h" - -static uint8 cpu_idts[HAL_CORE_COUNT][IDT_ENTRY_NUM * IDT_ENTRY_SIZE]; -static struct hal_idt_ptr cpu_idt_ptrs[HAL_CORE_COUNT]; - -static k_exc_dispatcher k_exc_disps[HAL_CORE_COUNT]; -static k_intr_dispatcher k_intr_disps[HAL_CORE_COUNT]; - -uint32 -impl_hal_set_irql(uint32 irql) -{ - UNREFERENCED(irql) - hal_halt_cpu(); - return 0; -} - -uint32 -impl_hal_get_irql(void) -{ - hal_halt_cpu(); - return 0; -} - - -void -hal_write_gate(void *const gate, uint64 const offset, uint32 const selector, uint32 const attr) -{ - ((uint8 *) gate)[0] = (uint8) (offset & 0xFF); - ((uint8 *) gate)[1] = (uint8) ((offset >> 8) & 0xFF); - ((uint8 *) gate)[2] = (uint8) (selector & 0xFF); - ((uint8 *) gate)[3] = (uint8) ((selector >> 8) & 0xFF); - ((uint8 *) gate)[4] = (uint8) (attr & 0xFF); - ((uint8 *) gate)[5] = (uint8) ((attr >> 8) & 0xFF); - ((uint8 *) gate)[6] = (uint8) ((offset >> 16) & 0xFF); - ((uint8 *) gate)[7] = (uint8) ((offset >> 24) & 0xFF); - ((uint8 *) gate)[8] = (uint8) ((offset >> 32) & 0xFF); - ((uint8 *) gate)[9] = (uint8) ((offset >> 40) & 0xFF); - ((uint8 *) gate)[10] = (uint8) ((offset >> 48) & 0xFF); - ((uint8 *) gate)[11] = (uint8) ((offset >> 56) & 0xFF); - ((uint8 *) gate)[12] = 0; - ((uint8 *) gate)[13] = 0; - ((uint8 *) gate)[14] = 0; - ((uint8 *) gate)[15] = 0; -} - -void -hal_set_interrupt_handler(uint64 index, void (*handler)(void)) -{ - if (index < IDT_ENTRY_NUM) - { - hal_write_gate(cpu_idts[hal_get_core_id()] + 16 * index, (uintptr) handler, seg_selector(1, 0), - GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT); - } -} - -void -impl_hal_issue_intr(uint32 target_core, uint32 vector) -{ - UNREFERENCED(target_core); - UNREFERENCED(vector); - hal_halt_cpu(); -} - -void -impl_hal_set_intr_dispatcher(k_intr_dispatcher handler) -{ - k_intr_disps[hal_get_core_id()] = handler; -} - -void -impl_hal_set_exc_dispatcher(k_exc_dispatcher handler) -{ - k_exc_disps[hal_get_core_id()] = handler; -} - - -void HABI -hal_interrupt_dispatcher(uint64 int_vec, struct interrupt_context *context) -{ - uint32 coreid = hal_get_core_id(); - if (k_intr_disps[coreid] == NULL) - { - hal_printf("Unhandled interrupt %d at 0x%X.\n", int_vec, context->rip); - } - else - { - k_intr_disps[coreid]((uint32) int_vec, context); - } -} - -void HABI -hal_exception_dispatcher(uint64 exc_vec, struct interrupt_context *context, uint32 errorcode) -{ - uint32 coreid = hal_get_core_id(); - if (k_exc_disps[coreid] == NULL) - { - hal_printf("Unhandled exception %d at 0x%X.\n", exc_vec, context->rip); - } - else - { - k_exc_disps[coreid]((uint32)exc_vec, context->rip, errorcode, context); - } -} - -static void -populate_idt(void) -{ - hal_set_interrupt_handler(0, hal_interrupt_handler_0); - hal_set_interrupt_handler(1, hal_interrupt_handler_1); - hal_set_interrupt_handler(2, hal_interrupt_handler_2); - hal_set_interrupt_handler(3, hal_interrupt_handler_3); - hal_set_interrupt_handler(4, hal_interrupt_handler_4); - hal_set_interrupt_handler(5, hal_interrupt_handler_5); - hal_set_interrupt_handler(6, hal_interrupt_handler_6); - hal_set_interrupt_handler(7, hal_interrupt_handler_7); - hal_set_interrupt_handler(8, hal_interrupt_handler_8); - hal_set_interrupt_handler(9, hal_interrupt_handler_9); - hal_set_interrupt_handler(10, hal_interrupt_handler_10); - hal_set_interrupt_handler(11, hal_interrupt_handler_11); - hal_set_interrupt_handler(12, hal_interrupt_handler_12); - hal_set_interrupt_handler(13, hal_interrupt_handler_13); - hal_set_interrupt_handler(14, hal_interrupt_handler_14); - hal_set_interrupt_handler(15, hal_interrupt_handler_15); - hal_set_interrupt_handler(16, hal_interrupt_handler_16); - hal_set_interrupt_handler(17, hal_interrupt_handler_17); - hal_set_interrupt_handler(18, hal_interrupt_handler_18); - hal_set_interrupt_handler(19, hal_interrupt_handler_19); - hal_set_interrupt_handler(20, hal_interrupt_handler_20); - hal_set_interrupt_handler(21, hal_interrupt_handler_21); - hal_set_interrupt_handler(22, hal_interrupt_handler_22); - hal_set_interrupt_handler(23, hal_interrupt_handler_23); - hal_set_interrupt_handler(24, hal_interrupt_handler_24); - hal_set_interrupt_handler(25, hal_interrupt_handler_25); - hal_set_interrupt_handler(26, hal_interrupt_handler_26); - hal_set_interrupt_handler(27, hal_interrupt_handler_27); - hal_set_interrupt_handler(28, hal_interrupt_handler_28); - hal_set_interrupt_handler(29, hal_interrupt_handler_29); - hal_set_interrupt_handler(30, hal_interrupt_handler_30); - hal_set_interrupt_handler(31, hal_interrupt_handler_31); - hal_set_interrupt_handler(32, hal_interrupt_handler_32); - hal_set_interrupt_handler(33, hal_interrupt_handler_33); - hal_set_interrupt_handler(34, hal_interrupt_handler_34); - hal_set_interrupt_handler(35, hal_interrupt_handler_35); - hal_set_interrupt_handler(36, hal_interrupt_handler_36); - hal_set_interrupt_handler(37, hal_interrupt_handler_37); - hal_set_interrupt_handler(38, hal_interrupt_handler_38); - hal_set_interrupt_handler(39, hal_interrupt_handler_39); - hal_set_interrupt_handler(40, hal_interrupt_handler_40); - hal_set_interrupt_handler(41, hal_interrupt_handler_41); - hal_set_interrupt_handler(42, hal_interrupt_handler_42); - hal_set_interrupt_handler(43, hal_interrupt_handler_43); - hal_set_interrupt_handler(44, hal_interrupt_handler_44); - hal_set_interrupt_handler(45, hal_interrupt_handler_45); - hal_set_interrupt_handler(46, hal_interrupt_handler_46); - hal_set_interrupt_handler(47, hal_interrupt_handler_47); - hal_set_interrupt_handler(48, hal_interrupt_handler_48); - hal_set_interrupt_handler(49, hal_interrupt_handler_49); - hal_set_interrupt_handler(50, hal_interrupt_handler_50); - hal_set_interrupt_handler(51, hal_interrupt_handler_51); - hal_set_interrupt_handler(52, hal_interrupt_handler_52); - hal_set_interrupt_handler(53, hal_interrupt_handler_53); - hal_set_interrupt_handler(54, hal_interrupt_handler_54); - hal_set_interrupt_handler(55, hal_interrupt_handler_55); - hal_set_interrupt_handler(56, hal_interrupt_handler_56); - hal_set_interrupt_handler(57, hal_interrupt_handler_57); - hal_set_interrupt_handler(58, hal_interrupt_handler_58); - hal_set_interrupt_handler(59, hal_interrupt_handler_59); - hal_set_interrupt_handler(60, hal_interrupt_handler_60); - hal_set_interrupt_handler(61, hal_interrupt_handler_61); - hal_set_interrupt_handler(62, hal_interrupt_handler_62); - hal_set_interrupt_handler(63, hal_interrupt_handler_63); - hal_set_interrupt_handler(64, hal_interrupt_handler_64); - hal_set_interrupt_handler(65, hal_interrupt_handler_65); - hal_set_interrupt_handler(66, hal_interrupt_handler_66); - hal_set_interrupt_handler(67, hal_interrupt_handler_67); - hal_set_interrupt_handler(68, hal_interrupt_handler_68); - hal_set_interrupt_handler(69, hal_interrupt_handler_69); - hal_set_interrupt_handler(70, hal_interrupt_handler_70); - hal_set_interrupt_handler(71, hal_interrupt_handler_71); - hal_set_interrupt_handler(72, hal_interrupt_handler_72); - hal_set_interrupt_handler(73, hal_interrupt_handler_73); - hal_set_interrupt_handler(74, hal_interrupt_handler_74); - hal_set_interrupt_handler(75, hal_interrupt_handler_75); - hal_set_interrupt_handler(76, hal_interrupt_handler_76); - hal_set_interrupt_handler(77, hal_interrupt_handler_77); - hal_set_interrupt_handler(78, hal_interrupt_handler_78); - hal_set_interrupt_handler(79, hal_interrupt_handler_79); - hal_set_interrupt_handler(80, hal_interrupt_handler_80); - hal_set_interrupt_handler(81, hal_interrupt_handler_81); - hal_set_interrupt_handler(82, hal_interrupt_handler_82); - hal_set_interrupt_handler(83, hal_interrupt_handler_83); - hal_set_interrupt_handler(84, hal_interrupt_handler_84); - hal_set_interrupt_handler(85, hal_interrupt_handler_85); - hal_set_interrupt_handler(86, hal_interrupt_handler_86); - hal_set_interrupt_handler(87, hal_interrupt_handler_87); - hal_set_interrupt_handler(88, hal_interrupt_handler_88); - hal_set_interrupt_handler(89, hal_interrupt_handler_89); - hal_set_interrupt_handler(90, hal_interrupt_handler_90); - hal_set_interrupt_handler(91, hal_interrupt_handler_91); - hal_set_interrupt_handler(92, hal_interrupt_handler_92); - hal_set_interrupt_handler(93, hal_interrupt_handler_93); - hal_set_interrupt_handler(94, hal_interrupt_handler_94); - hal_set_interrupt_handler(95, hal_interrupt_handler_95); - hal_set_interrupt_handler(96, hal_interrupt_handler_96); - hal_set_interrupt_handler(97, hal_interrupt_handler_97); - hal_set_interrupt_handler(98, hal_interrupt_handler_98); - hal_set_interrupt_handler(99, hal_interrupt_handler_99); - hal_set_interrupt_handler(100, hal_interrupt_handler_100); - hal_set_interrupt_handler(101, hal_interrupt_handler_101); - hal_set_interrupt_handler(102, hal_interrupt_handler_102); - hal_set_interrupt_handler(103, hal_interrupt_handler_103); - hal_set_interrupt_handler(104, hal_interrupt_handler_104); - hal_set_interrupt_handler(105, hal_interrupt_handler_105); - hal_set_interrupt_handler(106, hal_interrupt_handler_106); - hal_set_interrupt_handler(107, hal_interrupt_handler_107); - hal_set_interrupt_handler(108, hal_interrupt_handler_108); - hal_set_interrupt_handler(109, hal_interrupt_handler_109); - hal_set_interrupt_handler(110, hal_interrupt_handler_110); - hal_set_interrupt_handler(111, hal_interrupt_handler_111); - hal_set_interrupt_handler(112, hal_interrupt_handler_112); - hal_set_interrupt_handler(113, hal_interrupt_handler_113); - hal_set_interrupt_handler(114, hal_interrupt_handler_114); - hal_set_interrupt_handler(115, hal_interrupt_handler_115); - hal_set_interrupt_handler(116, hal_interrupt_handler_116); - hal_set_interrupt_handler(117, hal_interrupt_handler_117); - hal_set_interrupt_handler(118, hal_interrupt_handler_118); - hal_set_interrupt_handler(119, hal_interrupt_handler_119); - hal_set_interrupt_handler(120, hal_interrupt_handler_120); - hal_set_interrupt_handler(121, hal_interrupt_handler_121); - hal_set_interrupt_handler(122, hal_interrupt_handler_122); - hal_set_interrupt_handler(123, hal_interrupt_handler_123); - hal_set_interrupt_handler(124, hal_interrupt_handler_124); - hal_set_interrupt_handler(125, hal_interrupt_handler_125); - hal_set_interrupt_handler(126, hal_interrupt_handler_126); - hal_set_interrupt_handler(127, hal_interrupt_handler_127); - hal_set_interrupt_handler(128, hal_interrupt_handler_128); - hal_set_interrupt_handler(129, hal_interrupt_handler_129); - hal_set_interrupt_handler(130, hal_interrupt_handler_130); - hal_set_interrupt_handler(131, hal_interrupt_handler_131); - hal_set_interrupt_handler(132, hal_interrupt_handler_132); - hal_set_interrupt_handler(133, hal_interrupt_handler_133); - hal_set_interrupt_handler(134, hal_interrupt_handler_134); - hal_set_interrupt_handler(135, hal_interrupt_handler_135); - hal_set_interrupt_handler(136, hal_interrupt_handler_136); - hal_set_interrupt_handler(137, hal_interrupt_handler_137); - hal_set_interrupt_handler(138, hal_interrupt_handler_138); - hal_set_interrupt_handler(139, hal_interrupt_handler_139); - hal_set_interrupt_handler(140, hal_interrupt_handler_140); - hal_set_interrupt_handler(141, hal_interrupt_handler_141); - hal_set_interrupt_handler(142, hal_interrupt_handler_142); - hal_set_interrupt_handler(143, hal_interrupt_handler_143); - hal_set_interrupt_handler(144, hal_interrupt_handler_144); - hal_set_interrupt_handler(145, hal_interrupt_handler_145); - hal_set_interrupt_handler(146, hal_interrupt_handler_146); - hal_set_interrupt_handler(147, hal_interrupt_handler_147); - hal_set_interrupt_handler(148, hal_interrupt_handler_148); - hal_set_interrupt_handler(149, hal_interrupt_handler_149); - hal_set_interrupt_handler(150, hal_interrupt_handler_150); - hal_set_interrupt_handler(151, hal_interrupt_handler_151); - hal_set_interrupt_handler(152, hal_interrupt_handler_152); - hal_set_interrupt_handler(153, hal_interrupt_handler_153); - hal_set_interrupt_handler(154, hal_interrupt_handler_154); - hal_set_interrupt_handler(155, hal_interrupt_handler_155); - hal_set_interrupt_handler(156, hal_interrupt_handler_156); - hal_set_interrupt_handler(157, hal_interrupt_handler_157); - hal_set_interrupt_handler(158, hal_interrupt_handler_158); - hal_set_interrupt_handler(159, hal_interrupt_handler_159); - hal_set_interrupt_handler(160, hal_interrupt_handler_160); - hal_set_interrupt_handler(161, hal_interrupt_handler_161); - hal_set_interrupt_handler(162, hal_interrupt_handler_162); - hal_set_interrupt_handler(163, hal_interrupt_handler_163); - hal_set_interrupt_handler(164, hal_interrupt_handler_164); - hal_set_interrupt_handler(165, hal_interrupt_handler_165); - hal_set_interrupt_handler(166, hal_interrupt_handler_166); - hal_set_interrupt_handler(167, hal_interrupt_handler_167); - hal_set_interrupt_handler(168, hal_interrupt_handler_168); - hal_set_interrupt_handler(169, hal_interrupt_handler_169); - hal_set_interrupt_handler(170, hal_interrupt_handler_170); - hal_set_interrupt_handler(171, hal_interrupt_handler_171); - hal_set_interrupt_handler(172, hal_interrupt_handler_172); - hal_set_interrupt_handler(173, hal_interrupt_handler_173); - hal_set_interrupt_handler(174, hal_interrupt_handler_174); - hal_set_interrupt_handler(175, hal_interrupt_handler_175); - hal_set_interrupt_handler(176, hal_interrupt_handler_176); - hal_set_interrupt_handler(177, hal_interrupt_handler_177); - hal_set_interrupt_handler(178, hal_interrupt_handler_178); - hal_set_interrupt_handler(179, hal_interrupt_handler_179); - hal_set_interrupt_handler(180, hal_interrupt_handler_180); - hal_set_interrupt_handler(181, hal_interrupt_handler_181); - hal_set_interrupt_handler(182, hal_interrupt_handler_182); - hal_set_interrupt_handler(183, hal_interrupt_handler_183); - hal_set_interrupt_handler(184, hal_interrupt_handler_184); - hal_set_interrupt_handler(185, hal_interrupt_handler_185); - hal_set_interrupt_handler(186, hal_interrupt_handler_186); - hal_set_interrupt_handler(187, hal_interrupt_handler_187); - hal_set_interrupt_handler(188, hal_interrupt_handler_188); - hal_set_interrupt_handler(189, hal_interrupt_handler_189); - hal_set_interrupt_handler(190, hal_interrupt_handler_190); - hal_set_interrupt_handler(191, hal_interrupt_handler_191); - hal_set_interrupt_handler(192, hal_interrupt_handler_192); - hal_set_interrupt_handler(193, hal_interrupt_handler_193); - hal_set_interrupt_handler(194, hal_interrupt_handler_194); - hal_set_interrupt_handler(195, hal_interrupt_handler_195); - hal_set_interrupt_handler(196, hal_interrupt_handler_196); - hal_set_interrupt_handler(197, hal_interrupt_handler_197); - hal_set_interrupt_handler(198, hal_interrupt_handler_198); - hal_set_interrupt_handler(199, hal_interrupt_handler_199); - hal_set_interrupt_handler(200, hal_interrupt_handler_200); - hal_set_interrupt_handler(201, hal_interrupt_handler_201); - hal_set_interrupt_handler(202, hal_interrupt_handler_202); - hal_set_interrupt_handler(203, hal_interrupt_handler_203); - hal_set_interrupt_handler(204, hal_interrupt_handler_204); - hal_set_interrupt_handler(205, hal_interrupt_handler_205); - hal_set_interrupt_handler(206, hal_interrupt_handler_206); - hal_set_interrupt_handler(207, hal_interrupt_handler_207); - hal_set_interrupt_handler(208, hal_interrupt_handler_208); - hal_set_interrupt_handler(209, hal_interrupt_handler_209); - hal_set_interrupt_handler(210, hal_interrupt_handler_210); - hal_set_interrupt_handler(211, hal_interrupt_handler_211); - hal_set_interrupt_handler(212, hal_interrupt_handler_212); - hal_set_interrupt_handler(213, hal_interrupt_handler_213); - hal_set_interrupt_handler(214, hal_interrupt_handler_214); - hal_set_interrupt_handler(215, hal_interrupt_handler_215); - hal_set_interrupt_handler(216, hal_interrupt_handler_216); - hal_set_interrupt_handler(217, hal_interrupt_handler_217); - hal_set_interrupt_handler(218, hal_interrupt_handler_218); - hal_set_interrupt_handler(219, hal_interrupt_handler_219); - hal_set_interrupt_handler(220, hal_interrupt_handler_220); - hal_set_interrupt_handler(221, hal_interrupt_handler_221); - hal_set_interrupt_handler(222, hal_interrupt_handler_222); - hal_set_interrupt_handler(223, hal_interrupt_handler_223); - hal_set_interrupt_handler(224, hal_interrupt_handler_224); - hal_set_interrupt_handler(225, hal_interrupt_handler_225); - hal_set_interrupt_handler(226, hal_interrupt_handler_226); - hal_set_interrupt_handler(227, hal_interrupt_handler_227); - hal_set_interrupt_handler(228, hal_interrupt_handler_228); - hal_set_interrupt_handler(229, hal_interrupt_handler_229); - hal_set_interrupt_handler(230, hal_interrupt_handler_230); - hal_set_interrupt_handler(231, hal_interrupt_handler_231); - hal_set_interrupt_handler(232, hal_interrupt_handler_232); - hal_set_interrupt_handler(233, hal_interrupt_handler_233); - hal_set_interrupt_handler(234, hal_interrupt_handler_234); - hal_set_interrupt_handler(235, hal_interrupt_handler_235); - hal_set_interrupt_handler(236, hal_interrupt_handler_236); - hal_set_interrupt_handler(237, hal_interrupt_handler_237); - hal_set_interrupt_handler(238, hal_interrupt_handler_238); - hal_set_interrupt_handler(239, hal_interrupt_handler_239); - hal_set_interrupt_handler(240, hal_interrupt_handler_240); - hal_set_interrupt_handler(241, hal_interrupt_handler_241); - hal_set_interrupt_handler(242, hal_interrupt_handler_242); - hal_set_interrupt_handler(243, hal_interrupt_handler_243); - hal_set_interrupt_handler(244, hal_interrupt_handler_244); - hal_set_interrupt_handler(245, hal_interrupt_handler_245); - hal_set_interrupt_handler(246, hal_interrupt_handler_246); - hal_set_interrupt_handler(247, hal_interrupt_handler_247); - hal_set_interrupt_handler(248, hal_interrupt_handler_248); - hal_set_interrupt_handler(249, hal_interrupt_handler_249); - hal_set_interrupt_handler(250, hal_interrupt_handler_250); - hal_set_interrupt_handler(251, hal_interrupt_handler_251); - hal_set_interrupt_handler(252, hal_interrupt_handler_252); - hal_set_interrupt_handler(253, hal_interrupt_handler_253); - hal_set_interrupt_handler(254, hal_interrupt_handler_254); - hal_set_interrupt_handler(255, hal_interrupt_handler_255); -} - -uint32 -impl_hal_get_core_id(void) -{ - // TODO - return 0; -} - -int32 -hal_interrupt_init(void) -{ - uint32 coreid; - uint32 eax; - uint32 ebx; - uint32 ecx; - uint32 edx; - - // detect APIC first - eax = 1; - hal_cpuid(&eax, &ebx, &ecx, &edx); - if (!(edx & (1 << 9))) - { - hal_printf("ERROR: APIC is not present.\n"); - return 1; - } - - coreid = hal_get_core_id(); - - // get idt ptr ready - cpu_idt_ptrs[coreid].base = (uint64) &cpu_idts[coreid]; - cpu_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1; - - // clear dispatch table - k_exc_disps[coreid] = NULL; - k_intr_disps[coreid] = NULL; - - // hook asm interrupt handlers - populate_idt(); - - hal_flush_idt(&cpu_idt_ptrs[coreid]); - - // disable PIC - hal_write_port_8(0xa1, 0xff); - hal_write_port_8(0x21, 0xff); - - uint64 apic_base_reg = 0; - uint64 apic_base = 0; - ecx = MSR_IA32_APIC_BASE; - hal_read_msr(&ecx, &edx, &eax); - apic_base_reg = ((uint64) edx << 32) + (uint64) eax; - apic_base = apic_base_reg & bit_field_mask(12, 35); - UNREFERENCED(apic_base); - - //hal_printf("APIC Base: 0x%X\n", apic_base); - //hal_printf("APIC Enabled: %s\n", apic_base_reg & bit_mask_64(11) ? "Yes" : "No"); - //hal_printf("BSP: %s\n", apic_base_reg & bit_mask_64(8) ? "Yes" : "No"); - //hal_printf("APIC Spour: 0x%X\n", *(uint32 *) ((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET)); - - // hardware enable APIC - ecx = MSR_IA32_APIC_BASE; - eax = (uint32) ((apic_base_reg & bit_field_mask(0, 31)) | bit_mask(11)); - hal_write_msr(&ecx, &edx, &eax); - - // software enable APIC - // hal_write_mem_32((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET, *(uint32 *) (apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET) | (uint32)bit_mask(8)); - -// hal_issue_interrupt(1, 255); -// hal_enable_interrupt(); - - return 0; -} diff --git a/hal/io.asm b/hal/io.asm deleted file mode 100644 index 057fe47..0000000 --- a/hal/io.asm +++ /dev/null @@ -1,67 +0,0 @@ -section .text -bits 64 - -global hal_write_port_16 -global hal_write_port_32 -global hal_write_port_8 -global hal_read_port_8 -global hal_read_port_16 -global hal_read_port_32 - -hal_write_port_32: -mov rdx,rdi -mov rax,rsi -out dx,eax -nop -nop -nop -ret - - -hal_write_port_16: -mov rdx,rdi -mov rax,rsi -out dx,ax -nop -nop -nop -ret - - -hal_write_port_8: -mov rdx,rdi -mov rax,rsi -out dx,al -nop -nop -nop -ret - - -hal_read_port_8: -mov rdx,rdi -xor rax,rax -in al,dx -nop -nop -nop -ret - -hal_read_port_16: -mov rdx,rdi -xor rax,rax -in ax,dx -nop -nop -nop -ret - - -hal_read_port_32: -mov rdx,rdi -xor rax,rax -in eax,dx -nop -nop -nop -ret \ No newline at end of file diff --git a/hal/mem.c b/hal/mem.c deleted file mode 100644 index 2bd98d4..0000000 --- a/hal/mem.c +++ /dev/null @@ -1,208 +0,0 @@ - -#include "cdef.h" -#include "cpu.h" -#include "mem.h" -#include "intr.h" -#include "hal.h" - -static uint8 _gdts[HAL_CORE_COUNT][GDT_ENTRY_NUM * GDT_ENTRY_SIZE]; -static struct hal_gdt_ptr _gdt_ptrs[HAL_CORE_COUNT]; - -#define HAL_HEAP_SIZE 8192 -static uint32 hal_heap_used; -static char hal_heap[HAL_HEAP_SIZE]; - -uint32 -hal_write_initial_page_table(void *multiboot_info) -{ - UNREFERENCED(multiboot_info); - - /* - // still identity mapping - uint32 pt_num = 0; - uint32 pd_num = 0; - uint32 pdpt_num = 0; - uint32 pml4_num = 0; - - // calculate the number of page tables required: - u64 k_size = (uintptr)KERNEL_IMAGE_END_VADDR - (uintptr)KERNEL_IMAGE_VADDR; - // see multiboot boot info header - uint32 m_size = *(uint32 *)multiboot_info; - - // how many pages do we need to hold the entries - // 512 page table entries per 4k page - pt_num = (1 + (uint32)((k_size + m_size - 1) / KERNEL_PAGE_SIZE)) / 512; - pd_num = 1 + (pt_num - 1) / 512; - pdpt_num = 1 + (pd_num - 1) / 512; - pml4_num = 1 + (pdpt_num - 1) / 512; - - // calculate the # of page tables - if ((((uintptr)(pt_end) - (uintptr)(pt_base)) / KERNEL_PAGE_SIZE) < (pt_num + pd_num + pdpt_num + pml4_num)) - { - return STATUS_FAIL; - } - - // map kernel first - KERNEL_IMAGE_VADDR = ; - - // map kernel dynamic - KERNEL_DYNAMIC_SIZE = ; - - // map recursive page tables - hal_write_pml4(pt_base, (uintptr)pt_base, PML4_PRESENT | PML4_WRITE); - */ - - return 0; -} - - -void -hal_write_pt(void *const base, uintptr const p_addr, uint64 const attr) -{ - if (base == NULL) - { - return; - } - uint64 entry = (p_addr & 0xFFFFFFFFFF000) | attr; - ((uint8 *) base)[0] = (uint8) (entry & 0xFF); - ((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF); - ((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF); - ((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF); - ((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF); - ((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF); - ((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF); - ((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF); -} - -void -hal_write_pd(void *const base, uintptr const pt_addr, uint64 const attr) -{ - if (base == NULL) - { - return; - } - uint64 entry = (pt_addr & 0xFFFFFFFFFF000) | attr; - ((uint8 *) base)[0] = (uint8) (entry & 0xFF); - ((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF); - ((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF); - ((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF); - ((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF); - ((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF); - ((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF); - ((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF); -} - -void -hal_write_pdpt(void *const base, uintptr const pd_addr, uint64 const attr) -{ - if (base == NULL) - { - return; - } - uint64 entry = (pd_addr & 0xFFFFFFFFFF000) | attr; - ((uint8 *) base)[0] = (uint8) (entry & 0xFF); - ((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF); - ((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF); - ((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF); - ((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF); - ((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF); - ((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF); - ((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF); -} - -void -hal_write_pml4(void *const base, uintptr const pdpt_addr, uint64 const attr) -{ - if (base == NULL) - { - return; - } - uint64 const entry = (pdpt_addr & 0xFFFFFFFFFF000) | attr; - ((uint8 *) base)[0] = (uint8) (entry & 0xFF); - ((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF); - ((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF); - ((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF); - ((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF); - ((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF); - ((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF); - ((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF); -} - -void -hal_write_segment_descriptor(void *const gdt, uint32 const base, uint32 const limit, uint64 const attr) -{ - if (gdt == NULL) - { - return; - } - uint64 const seg_desc = (((uint64) base & 0xFFFF) << 16) | ((((uint64) base >> 16) & 0xFF) << 32) | - ((((uint64) base >> 24) & 0xFF) << 56) | ((uint64) limit & 0xFFFF) | - ((((uint64) limit >> 16) & 0xF) << 48) | attr; - ((uint8 *) gdt)[0] = (uint8) (seg_desc & 0xFF); - ((uint8 *) gdt)[1] = (uint8) ((seg_desc >> 8) & 0xFF); - ((uint8 *) gdt)[2] = (uint8) ((seg_desc >> 16) & 0xFF); - ((uint8 *) gdt)[3] = (uint8) ((seg_desc >> 24) & 0xFF); - ((uint8 *) gdt)[4] = (uint8) ((seg_desc >> 32) & 0xFF); - ((uint8 *) gdt)[5] = (uint8) ((seg_desc >> 40) & 0xFF); - ((uint8 *) gdt)[6] = (uint8) ((seg_desc >> 48) & 0xFF); - ((uint8 *) gdt)[7] = (uint8) ((seg_desc >> 56) & 0xFF); -} - -void hal_init_gdt(void) -{ - uint32 coreid = hal_get_core_id(); - // get gdt ready - hal_write_segment_descriptor((void *) &_gdts[coreid][0], 0, 0, 0); - hal_write_segment_descriptor((void *) &_gdts[coreid][8], 0, 0, - SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X); - hal_write_segment_descriptor((void *) &_gdts[coreid][16], 0, 0, - SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW); - hal_write_segment_descriptor((void *) &_gdts[coreid][24], 0, 0, - SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X); - hal_write_segment_descriptor((void *) &_gdts[coreid][32], 0, 0, - SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW); - - hal_write_segment_descriptor((void *) &_gdts[coreid][40], 0, 0xFFFFF, - SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | - SEG_TYPE_CODE_X); - hal_write_segment_descriptor((void *) &_gdts[coreid][48], 0, 0xFFFFF, - SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | - SEG_TYPE_DATA_RW); - hal_write_segment_descriptor((void *) &_gdts[coreid][56], 0, 0xFFFFF, - SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | - SEG_TYPE_CODE_X); - hal_write_segment_descriptor((void *) &_gdts[coreid][64], 0, 0xFFFFF, - SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS | - SEG_TYPE_DATA_RW); - _gdt_ptrs[coreid].base = (uint64) &_gdts[coreid]; - _gdt_ptrs[coreid].limit = GDT_ENTRY_NUM * GDT_ENTRY_SIZE - 1; - hal_flush_gdt(&_gdt_ptrs[coreid], seg_selector(1, 0), seg_selector(2, 0)); -} - -void -hal_mem_init(struct multiboot_tag_mmap *info) -{ - UNREFERENCED(info); -} - -void * -halloc(uint32 size) -{ - void *ret; - ret = NULL; - if (hal_heap_used + size < HAL_HEAP_SIZE) - { - ret = (void *) ((uintptr) hal_heap + hal_heap_used); - hal_heap_used += size; - } - return ret; -} - -void -hfree(void *ptr) -{ - /** - * Do nothing for now since salloc not available in HAL - */ - UNREFERENCED(ptr); -} diff --git a/hal/print.c b/hal/print.c deleted file mode 100644 index 224c5a9..0000000 --- a/hal/print.c +++ /dev/null @@ -1,221 +0,0 @@ -#include "cdef.h" -#include "cpu.h" -#include "print.h" -#include "clib.h" - -// #define get_column(pos) ((pos) % 80) -#define get_row(pos) ((pos) / 80) -#define get_pos(row, col) ((row) * 80 + (col)) - -static uint64 text_pos; - -void -hal_print_init(struct multiboot_tag_framebuffer* info) -{ - UNREFERENCED(info); -} - -static void -halp_print_scroll(void) -{ - mem_mv((void *) (0xb8000 + get_pos(1, 0) * 2), (void *) (0xb8000 + get_pos(0, 0) * 2), (80 * 24) * 2); -} - -static void -halp_print_str(char const *str) -{ - if (str == NULL) - { - return; - } - while (*str != 0) - { - if (*str == '\n') - { - text_pos = 80 * (get_row(text_pos) + 1); - if (text_pos > 80 * 25 - 1) - { - //can't hold - halp_print_scroll(); - mem_set((void *) (0xb8000 + 80 * 24 * 2), 0, 80 * 2); // clear last row - text_pos = 80 * 24; - } - str++; - } - else - { - if (text_pos > 80 * 25 - 1) - { - //can't hold - halp_print_scroll(); - text_pos = 80 * 24; - } - *((char *) (0xb8000) + text_pos * 2) = *str; - *((char *) (0xb8000) + text_pos * 2 + 1) = 7; - str++; - text_pos++; - } - } -} - -static void -halp_print_uint(uint64 number) -{ - char arr[21]; // do not need to initialize - arr[20] = 0; //zero-terminated - uint32 index = 19; - uint32 const div = 10; - while (1) - { - uint64 quo = number / div; - uint64 rmd = number % div; - number = quo; - arr[index--] = (char) ('0' + rmd); - if (number == 0) - { - break; - } - } - halp_print_str(&(arr[index + 1])); -} - -static void -halp_print_int(int64 number) -{ - char arr[21]; // do not need to initialize - arr[20] = 0; //zero-terminated - uint32 index = 19; - uint32 isNegative = 0; - uint32 const div = 10; - if (number < 0) - { - isNegative = 1; - number *= -1; - } - while (1) - { - int64 quo = number / div; - int64 rmd = number % div; - number = quo; - arr[index--] = (char) ('0' + rmd); - if (number == 0) - { - break; - } - } - if (isNegative) - { - arr[index--] = '-'; - } - halp_print_str(&(arr[index + 1])); -} - -static void -halp_print_hex(uint64 number, uint64 capital) -{ - char const lookup_table_cap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - char const lookup_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - char const *const look_up = capital == 1 ? &lookup_table_cap[0] : &lookup_table[0]; - char arr[17]; - arr[16] = 0; //zero-terminated - uint32 index = 15; - uint32 const div = 16; - while (1) - { - uint64 quo = number / div; - uint64 rmd = number % div; - number = quo; - arr[index--] = look_up[rmd]; - if (number == 0) - { - break; - } - } - halp_print_str(&(arr[index + 1])); -} - -void -hal_clear_screen(void) -{ - text_pos = 0; // reset text_pos - mem_set((void *) 0xb8000, 0, 25 * 80 * 2); -} - -static void -halp_vprintf(char const *format, va_list args) -{ - char buf[2]; - int64 d; - uint64 u; - char *s; - char c; - - buf[1] = '\0'; - for (; *format != '\0'; format++) - { - if (*format != '%') - { - buf[0] = *format; - halp_print_str(buf); - continue; - } - format++; - switch (*format) - { - case 'd': - d = va_arg(args, int64); - halp_print_int(d); - break; - case 'u': - u = va_arg(args, uint64); - halp_print_uint(u); - break; - case 's': - s = va_arg(args, char *); - halp_print_str(s); - break; - case 'c': - c = (char) va_arg(args, int64); - buf[0] = c; - halp_print_str(buf); - break; - case 'x': - u = va_arg(args, uint64); - halp_print_hex(u, 0); - break; - case 'X': - u = va_arg(args, uint64); - halp_print_hex(u, 1); - break; - case '%': - buf[0] = '%'; - halp_print_str(buf); - break; - default: - buf[0] = '%'; - halp_print_str(buf); - format--; - break; - } - } -} - -void -hal_printf(char const *format, ...) -{ - va_list args; - va_start(args, format); - halp_vprintf(format, args); - va_end(args); -} - -void -hal_assert(uint32 expression, char *message) -{ - if (!expression) - { - hal_printf("HAL: Assertion failed. Detail: %s", message == NULL ? "NULL" : message); - - hal_halt_cpu(); - } -} diff --git a/inc/arch/brute.h b/inc/arch/brute.h new file mode 100644 index 0000000..1552120 --- /dev/null +++ b/inc/arch/brute.h @@ -0,0 +1,3 @@ +#pragma once + +void arch_brute(); diff --git a/inc/arch/intr.h b/inc/arch/intr.h new file mode 100644 index 0000000..d6e34bd --- /dev/null +++ b/inc/arch/intr.h @@ -0,0 +1,60 @@ +#pragma once + +#include <arch/intr.h> +#include <kern/status.h> + +/** + * Interrupt context structure + */ +struct interrupt_context +{ + const uint64 rip; + const uint64 cs; + const uint64 rflags; + const uint64 rsp; + const uint64 ss; +}; + +/** + * IDT Defns + */ +#define GATE_DPL_0 (0ull << 13) +#define GATE_DPL_1 (1ull << 13) +#define GATE_DPL_2 (2ull << 13) +#define GATE_DPL_3 (3ull << 13) +#define GATE_PRESENT (1ull << 15) +#define GATE_TYPE_CALL (12ull << 8) +#define GATE_TYPE_INTERRUPT (14ull << 8) +#define GATE_TYPE_TRAP (15ull << 8) + +#define IDT_ENTRY_NUM 256 +#define IDT_ENTRY_SIZE 16 + +#define IRQL_DPC (1) + +/** + * C declaration + */ +void +arch_intr_init(void); + +/** + * Exported Dispatchers for asm code + */ +void KABI +arch_intr_disp(uint64 int_vec, struct interrupt_context *context); + +void KABI +arch_exc_disp(uint64 exc_vec, struct interrupt_context *context, uint32 errorcode); + +/** + * ASM declaration + */ +int +arch_raise_irql(int irql); + +int +arch_lower_irql(int irql); + +int +arch_get_irql(); diff --git a/inc/arch/mem.h b/inc/arch/mem.h new file mode 100644 index 0000000..db6f8d8 --- /dev/null +++ b/inc/arch/mem.h @@ -0,0 +1,10 @@ +#pragma once + +#include <kern/cdef.h> +#include <arch/mlayout.h> + +static inline void * +arch_pmap_map(uintptr paddr, ATTR_UNUSED usize size) +{ + return (void*)(paddr + KERNEL_PMAP_VADDR); +} diff --git a/inc/arch/mlayout.h b/inc/arch/mlayout.h new file mode 100644 index 0000000..074e171 --- /dev/null +++ b/inc/arch/mlayout.h @@ -0,0 +1,34 @@ +#pragma once + +/** + * Kernel Memory Layout + * ----------------------- 0x0000,0000,0000,0000 - User Space + * Application SIZE: 0x0000,8000,0000,0000 (256x PML4) + * ----------------------- 0x0000,8000,0000,0000 + * Non-canonical + * ----------------------- 0xFFFF,8000,0000,0000 - Kernel Space + * PMAP SIZE: 0x0000,4000,0000,0000 (128x PML4) + * ----------------------- 0xFFFF,C000,0000,0000 + * Kernel Dynamic SIZE: 0x0000,3000,0000,0000 + * ----------------------- 0xFFFF,F000,0000,0000 + * Unused + * ----------------------- 0xFFFF,FFFF,8000,0000 + * Kernel Image SIZE: 0x0000,0000,8000,0000 (2GB) + * ----------------------- 0xFFFF,FFFF,FFFF,FFFF +**/ + +/** + * kernel loaded at physical address 16MB + * 0x1000000 = 16777216 = 16 * 1024 * 1024 + */ +#define KERNEL_IMG_PADDR (0x1000000) +#define KERNEL_PAGE_SIZE (0x1000) + +#define KERNEL_SPACE_VADDR (0xFFFF800000000000) +#define KERNEL_PMAP_VADDR (0xFFFF800000000000) +#define KERNEL_PMAP_SIZE (0x0000400000000000) +#define KERNEL_DYN_VADDR (0xFFFFFF8000000000) +#define KERNEL_DYN_SIZE (0x0000300000000000) +#define KERNEL_IMG_VADDR (0xFFFFFFFF80000000) +#define KERNEL_IMG_SIZE (0x000000007FFFFFFF) + diff --git a/inc/arch/print.h b/inc/arch/print.h new file mode 100644 index 0000000..8c15112 --- /dev/null +++ b/inc/arch/print.h @@ -0,0 +1,12 @@ +#pragma once +#include <kern/cdef.h> +#include <arch/print.h> + +void +arch_cls(); + +void +arch_print_init(); + +void +arch_putc(char c); diff --git a/inc/cdef.h b/inc/cdef.h deleted file mode 100644 index 9687987..0000000 --- a/inc/cdef.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <stdarg.h> -#include <stddef.h> - -typedef uint32_t uint32; -typedef int32_t int32; -typedef uint64_t uint64; -typedef int64_t int64; -typedef uintptr_t uintptr; -typedef uint16_t uint16; -typedef int16_t int16; -typedef uint8_t uint8; -typedef int8_t int8; - -typedef _Bool bool; -#define TRUE (1) -#define FALSE (0) - -#define PRAGMA_PACKED __attribute__((packed)) - -#define PRAGMA_SECTION(x) __attribute__ ((section (x))) - -#define PRAGMA_ALIGN(x) __attribute__ ((aligned(x))) - -#define ALIGN(type, num, align) (((type)(num) + ((type)align - 1)) & ~((type)align - 1)) - -#define UNREFERENCED(x) {(x) = (x);} - -#define KABI __attribute__((sysv_abi)) - - diff --git a/inc/clib.h b/inc/clib.h deleted file mode 100644 index 81bd1ca..0000000 --- a/inc/clib.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "cdef.h" - -/** - * Common macros, etc - */ - -#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr)(member_addr) - (uintptr)(&(((struct_name*)0)->member_name)))) - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -#define SWAP(a, b, T) do { T temp = *(a); *(a) = *(b); *(b) = temp; } while(0); - -uint32 -lb_rand(void); - -void -lb_srand(uint32 _seed); - -void -lb_mrand(uint32 max); - -uint64 -str_len(char const *str); - - -uint64 -str_cmp(char const *str1, char const *str2); - - -void -mem_cpy(void *src, void *dst, uint64 size); - - -void -mem_mv(void *src, void *dst, uint64 size); - - -void -mem_set(void *src, uint8 val, uint64 size); - - -static inline uint64 -bit_mask(uint32 bit) -{ - return (uint64) 1 << bit; -} - -static inline uint64 -bit_field_mask(uint32 low, uint32 high) -{ - return ~(~(uint64) 0 << high << 1) << low; -} diff --git a/inc/hal.h b/inc/hal.h deleted file mode 100644 index 21992ca..0000000 --- a/inc/hal.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "cdef.h" - -int32 KABI -hal_atomic_xchg_32(int32 *target, int32 val); - -int32 KABI -hal_atomic_inc_32(int32 *target, int32 increment); - -int32 KABI -hal_atomic_cmpxchg_32(int32 *target, int32 compare, int32 val); - -uint32 KABI -hal_set_irql(uint32 irql); - -uint32 KABI -hal_get_irql(void); - -void KABI -hal_halt(void); - -void KABI -hal_issue_intr(uint32 core, uint32 vector); - -typedef void (KABI *k_intr_dispatcher)(uint32 intr_vec, void *h_context); - -void KABI -hal_set_intr_dispatcher(k_intr_dispatcher handler); - -typedef void (KABI *k_exc_dispatcher)(uint32 exc_vec, uintptr exc_addr, uint32 err_code, void *h_context); - -void KABI -hal_set_exc_dispatcher(k_exc_dispatcher handler); - -uint32 KABI -hal_get_core_id(void); - diff --git a/inc/kern/avl_tree.h b/inc/kern/avl_tree.h new file mode 100644 index 0000000..869adb8 --- /dev/null +++ b/inc/kern/avl_tree.h @@ -0,0 +1,86 @@ +#pragma once + +#include <kern/cdef.h> + +struct avl_node +{ + struct avl_node *left; + struct avl_node *right; + int height; +}; + +/* +* A comparison function between self (yours) and other +* Returns: +* < 0 if other < self +* = 0 if other = self +* > 0 if other > self +*/ +typedef int (*avl_cmpf)(struct avl_node *tree_node, struct avl_node *self); + +struct avl_root +{ + avl_cmpf cmpf; + struct avl_node *root; +}; + + +/* + * init operations + */ + +static inline void +avl_init(struct avl_root *root, avl_cmpf cmpf) +{ + root->root = NULL; + root->cmpf = cmpf; +} + +static inline int +avl_empty(struct avl_root *root) +{ + return (root->root == NULL); +} + +/* + * tree operations + */ + +struct avl_node * +avl_search(struct avl_root *root, struct avl_node *node); + + +struct avl_node * +avl_insert(struct avl_root *root, struct avl_node *node); + + +struct avl_node * +avl_remove(struct avl_root *root, struct avl_node *node); + + +/* + * traversal operations + */ + +struct avl_node * +avl_first(struct avl_root *root); + +struct avl_node * +avl_last(struct avl_root *root); + +struct avl_node * +avl_next(struct avl_root *root, struct avl_node *node); + +struct avl_node * +avl_prev(struct avl_root *root, struct avl_node *node); + + +/* + * internal operations (testing only) + */ + +int +avl_validate(struct avl_root *root); + +usize +avl_size(struct avl_root *root); diff --git a/inc/kern/bitset.h b/inc/kern/bitset.h new file mode 100644 index 0000000..b3beabc --- /dev/null +++ b/inc/kern/bitset.h @@ -0,0 +1,37 @@ +#pragma once + +#define BITSET_DEFINE(sz) + +static inline uint64 +bit_mask(uint32 bit) +{ + return (uint64) 1 << bit; +} + +static inline uint64 +bit_field_mask(uint32 low, uint32 high) +{ + return ~(~(uint64) 0 << high << 1) << low; +} + +static inline uint8* bit_byte(void* base, uint32 bit) +{ + return (uint8 *) ((uintptr) (base) + (bit & (~(sizeof(uint8) - 1)))); +} + +static inline uint8 bit_in_byte(uint32 bit) +{ + return bit & (sizeof(uint8) - 1); +} + +static inline uint8 bit_read(void *base, uint32 bit) +{ + uint8* target = bit_byte(base, bit); + return (uint8)((*target >> bit_in_byte(bit)) & 1); +} + +static inline void bit_set(void *base, uint32 bit, uint8 val) +{ + uint8* target = bit_byte(base, bit); + *target = *target & (uint8)(~((val & 1) << bit_in_byte(bit))); +} diff --git a/inc/kern/brute.h b/inc/kern/brute.h new file mode 100644 index 0000000..e91bb68 --- /dev/null +++ b/inc/kern/brute.h @@ -0,0 +1,16 @@ +#pragma once + +#include <kern/cdef.h> +#include <kern/print.h> +#include <arch/brute.h> + +#define BRUTE(fmt, ...) do { \ + kprintf("Kernel brute: " fmt "\n", ##__VA_ARGS__); \ + arch_brute(); \ +} while(0) + +#define KASSERT(expr, msg, ...) do { \ + if (!(expr)) { \ + BRUTE("Assertion \"" #expr "\" failed at %s:%d: " msg , __FILE__, __LINE__ , ##__VA_ARGS__); \ + } \ +} while(0) diff --git a/inc/kern/cdef.h b/inc/kern/cdef.h new file mode 100644 index 0000000..8692d56 --- /dev/null +++ b/inc/kern/cdef.h @@ -0,0 +1,37 @@ +#pragma once + +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdatomic.h> + +typedef uintmax_t uintmax; +typedef intmax_t intmax; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint64_t uint64; +typedef int64_t int64; +typedef uintptr_t uintptr; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint8_t uint8; +typedef int8_t int8; +typedef size_t usize; +typedef unsigned char uchar; +typedef unsigned long ulong; +typedef unsigned int uint; +#define KABI __attribute__((sysv_abi)) + +#define STATIC_ASSERT(cond, msg) _Static_assert((cond), msg) +#define TYPEOF(type) __typeof__(type) + +/* Declarations */ +#define DECL_ATOMIC(type) _Atomic type + +/* Attributes */ +#define ATTR_PACKED __attribute__((packed)) +#define ATTR_UNUSED __attribute__((unused)) +#define ATTR_USED __attribute__((used)) +#define ATTR_SECTION(x) __attribute__ ((section (#x))) +#define ATTR_ALIGN(x) _Alignas(x) +#define ATTR_FMT_PRINTF __attribute__((format (printf, 1, 2))) diff --git a/inc/kern/kinit.h b/inc/kern/kinit.h new file mode 100644 index 0000000..a3dd42e --- /dev/null +++ b/inc/kern/kinit.h @@ -0,0 +1,33 @@ +#pragma once + +#include <kern/lds.h> + +typedef void (kinitf)(void*); + +struct kinit { + void* args; + kinitf* func; + int pri; + int subsys; + const char* name; +}; + +#define KINIT_START (struct kinit **)LDS_START(kinit) +#define KINIT_STOP (struct kinit **)LDS_STOP(kinit) + +LDS_DECL(kinit); + +#define KINIT_DECL(_name, _subsys, _pri, _func, _args) \ + static const struct kinit _kinit_##name = { \ + .args = _args, \ + .func = _func, \ + .subsys = _subsys, \ + .pri= _pri, \ + .name = #_name \ + }; \ + LDS_ATTR(kinit) ATTR_USED static const struct kinit * _kinit_lds_##name = &_kinit_##name + +enum { + KINIT_SUBSYS_KERN = 0, + KINIT_SUBSYS_KTEST = 1 +}; diff --git a/inc/kern/lds.h b/inc/kern/lds.h new file mode 100644 index 0000000..44f7fc5 --- /dev/null +++ b/inc/kern/lds.h @@ -0,0 +1,11 @@ +#pragma once + +#include <kern/cdef.h> + +#define LDS_DECL(name) \ + extern const char __start_##name[]; \ + extern const char __stop_##name[] + +#define LDS_START(name) ((void*)__start_##name) +#define LDS_STOP(name) ((void*)__stop_##name) +#define LDS_ATTR(name) ATTR_SECTION(name) diff --git a/inc/kern/libkern.h b/inc/kern/libkern.h new file mode 100644 index 0000000..7e64cb2 --- /dev/null +++ b/inc/kern/libkern.h @@ -0,0 +1,77 @@ +#pragma once + +#include <kern/cdef.h> + +/* + * Common macros, etc + */ + +#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr)(member_addr) - (uintptr)(&(((struct_name*)0)->member_name)))) + +#define CEIL(num, div) \ + ({ __typeof__(num) _num = (num); \ + __typeof__(div) _div = (div); \ + ((_num + _div - 1) / _div); }) + +#define MIN(a, b) \ + ({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (_a) < (_b) ? (_a) : (_b); }) + +#define MAX(a, b) \ + ({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (_a) > (_b) ? (_a) : (_b); }) + +#define SWAP(a, b) do { \ + __typeof__(*a) temp = *(a); \ + *(a) = *(b); \ + *(b) = temp; \ + } while(0) + +#define BIT_FIELD_MASK(low, high) ((1ul >> (high)) - 1) +#define BIT_MASK(bit) (1ul >> (bit)) + +void +memswp(void *dst, void *src, usize size); + +void * +memcpy(void *dst, const void *src, usize size); + +void * +memset(void *dst, int val, usize size); + +void +qsort(void *base, usize num, usize sz, int (*cmpf)(const void *, const void *)); + +void * +memmove(void *dst, const void *src, usize size); + +static inline +int toupper(int c) +{ + if (c >= 'a' && c <= 'z') { + return c - ('a' - 'A'); + } else { + return c; + } +} + +/* convert a max 15 d to its character, otherwise d is returned */ +static inline +uint dtoa(uint d) +{ + if (d < 10) { + return d + '0'; + } else if (d < 16) { + return d - 10 + 'a'; + } + return d; +} + +ulong +krand(); + +void +ksrand(ulong sd); + diff --git a/inc/kern/list.h b/inc/kern/list.h new file mode 100644 index 0000000..9c18102 --- /dev/null +++ b/inc/kern/list.h @@ -0,0 +1,90 @@ +#pragma once + +#include <kern/cdef.h> +#include <kern/poison.h> +#include <kern/brute.h> + +struct list_entry { + struct list_entry *prev; + struct list_entry *next; +}; + +/* + * Init Operations + */ +static inline void +list_init(struct list_entry *head) +{ + head->next = head; + head->prev = head; +} + +static inline int +list_empty(struct list_entry *ent) +{ + return (ent->next == ent); +} + +static inline struct list_entry * +list_prev(struct list_entry *ent) +{ + return ent->prev; +} + +static inline struct list_entry * +list_next(struct list_entry *ent) +{ + return ent->next; +} + +/* + * Insert Operations + */ +static inline void +list_insert(struct list_entry *head, struct list_entry *ent) +{ + ent->next = head->next; + ent->prev = head; + + head->next->prev = ent; + head->next = ent; +} + +static inline void +list_insert_before(struct list_entry *head, struct list_entry *ent) +{ + list_insert(head->prev, ent); +} + +/* + * Remove Operations + */ +static inline struct list_entry * +list_remove(struct list_entry *ent) +{ + ent->next->prev = ent->prev; + ent->prev->next = ent->next; + + ent->next = POISON_LIST; + ent->prev = POISON_LIST; + + return ent; +} + +static inline struct list_entry * +list_remove_before(struct list_entry *list) +{ + return list_remove(list->prev); +} + +static inline struct list_entry * +list_remove_after(struct list_entry *list) +{ + return list_remove(list->next); +} + +#define LIST_FOREACH(list, it) \ + for (it = list_next(list); it != list; it = list_next(it)) + +#define LIST_FOREACH_REVERSE(list, it) \ + for (it = list_prev(list); it != list; it = list_prev(it)) diff --git a/inc/kern/poison.h b/inc/kern/poison.h new file mode 100644 index 0000000..dc6c713 --- /dev/null +++ b/inc/kern/poison.h @@ -0,0 +1,9 @@ +#pragma once + +#define POISON_BASE (0xDEAD000000000000) +#define POISON_STEP (0x1000) + +#define MAKE_POISON(idx) (POISON_BASE + POISON_STEP * (idx)) + +#define POISON_LIST ((void*)MAKE_POISON(0)) +#define POISON_AVL ((void*)MAKE_POISON(1)) diff --git a/inc/kern/print.h b/inc/kern/print.h new file mode 100644 index 0000000..fa65c02 --- /dev/null +++ b/inc/kern/print.h @@ -0,0 +1,10 @@ +#pragma once + +#include <kern/cdef.h> +#include <kern/print.h> + +ATTR_FMT_PRINTF int +kprintf(const char *str, ...); + +int +kvprintf(const char *str, va_list args); diff --git a/inc/kern/spin_lock.h b/inc/kern/spin_lock.h new file mode 100644 index 0000000..8706937 --- /dev/null +++ b/inc/kern/spin_lock.h @@ -0,0 +1,27 @@ +#pragma once + +#include <kern/cdef.h> + +// implements a simple ticket lock +struct spin_lock { + // LOW 16 bits: cur ticket + // HIGH 16 bits: cur owner + DECL_ATOMIC(uint32) val; +}; + +#define SPIN_LOCK_INITIALIZER {.val = ATOMIC_VAR_INIT(0)} + +STATIC_ASSERT(sizeof(struct spin_lock) == sizeof(uint32), "spin_lock size isn't 32 bits"); + +void +spin_lock_init(struct spin_lock *lock); + +void +spin_lock_acq(struct spin_lock *lock); + +void +spin_lock_rel(struct spin_lock *lock); + +// returns non-zero on success otherwise zero +int +spin_lock_try_acq(struct spin_lock *lock); diff --git a/inc/kern/status.h b/inc/kern/status.h new file mode 100644 index 0000000..2d29681 --- /dev/null +++ b/inc/kern/status.h @@ -0,0 +1,14 @@ +#pragma once + +#include <kern/cdef.h> + +/** + * Specific error codes + */ +enum { + S_OK = 0x0, + S_NOMEM = 0x1, + S_INVARG = 0x2, + S_INIT = 0x3, + S_DUP = 0x4 +}; diff --git a/inc/kernel.h b/inc/kernel.h deleted file mode 100644 index d7c70da..0000000 --- a/inc/kernel.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "cdef.h" - - /** - * boot_info structure - */ -struct boot_info -{ - struct - { - char cpu_vendor[13]; - } cpu_info; - - struct - { - uintptr krnl_start_vaddr; - uintptr krnl_end_vaddr; - } mem_info; - - struct intr_info - { - uint32 timer_intr_vec; - uint32 dpc_intr_vec; - uint32 page_fault_vec; - - uint32 irql_low; - uint32 irql_dpc; - uint32 irql_high; - } intr_info; -}; - -void KABI -kmain(struct boot_info *boot_info); diff --git a/inc/mlayout.h b/inc/mlayout.h deleted file mode 100644 index 1560af3..0000000 --- a/inc/mlayout.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -/** - * Kernel Memory Layout - * ----------------------- 0x0000,0000,0000,0000 - User Space - * Application SIZE: 0x0000,8000,0000,0000 (256x PML4) - * ----------------------- 0x0000,8000,0000,0000 - * Non-canonical - * ----------------------- 0xFFFF,8000,0000,0000 - Kernel Space - * Reserved SIZE: 0x0000,7F00,0000,0000 (254x PML4) - * ----------------------- 0xFFFF,FF00,0000,0000 - * Page Table SIZE: 0x0000,0080,0000,0000 (1x PML4) - * ----------------------- 0xFFFF,FF80,0000,0000 - * Kernel Dynamic SIZE: 0x0000,007F,8000,0000 (Kernel Dynamic + Kernel Image = 1x PML4) - * ----------------------- 0xFFFF,FFFF,8000,0000 - * Kernel Image SIZE: 0x0000,0000,8000,0000 - * ----------------------- 0xFFFF,FFFF,FFFF,FFFF -**/ - -/** - * kernel loaded at physical address 16MB - * 0x1000000 = 16777216 = 16 * 1024 * 1024 - */ -#define KERNEL_IMAGE_PADDR (0x1000000) -#define KERNEL_PAGE_SIZE (0x1000) - - -#define KERNEL_SPACE_VADDR (0xFFFF800000000000) -#define KERNEL_RESERVED_VADDR KERNEL_SPACE_VADDR -#define KERNEL_PAGE_TABLE_VADDR (0xFFFFFF0000000000) -#define KERNEL_DYNAMIC_VADDR (0xFFFFFF8000000000) - -/** - * Minus 2GB - */ -#define KERNEL_IMAGE_VADDR (0xFFFFFFFF80000000) -#define KERNEL_IMAGE_OFFSET (KERNEL_IMAGE_PADDR) - diff --git a/inc/test/ktest.h b/inc/test/ktest.h new file mode 100644 index 0000000..c75ecdb --- /dev/null +++ b/inc/test/ktest.h @@ -0,0 +1,36 @@ +#pragma once + +#include <kern/cdef.h> +#include <kern/lds.h> + +LDS_DECL(ktest); + +typedef void (ktestf)(void*); + +struct ktest { + void* args; + ktestf* func; + int subsys; + const char* name; +}; + +#define KTEST_START (struct ktest **)LDS_START(ktest) +#define KTEST_STOP (struct ktest **)LDS_STOP(ktest) + +#define KTEST_DECL(_name, _subsys, _func, _args) \ + static const struct ktest _ktest_##_name = { \ + .args = _args, \ + .func = _func, \ + .subsys = _subsys, \ + .name = #_name \ + }; \ + LDS_ATTR(ktest) ATTR_USED static const struct ktest * _ktest_lds_##_name = &_ktest_##_name + +enum { + KTEST_SUBSYS_LIST = 0, + KTEST_SUBSYS_AVL = 1, + KTEST_SUBSYS_QSORT = 2, +}; + +void +ktest_begin(const char* name); diff --git a/kern/CMakeLists.txt b/kern/CMakeLists.txt new file mode 100644 index 0000000..e893f66 --- /dev/null +++ b/kern/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SUBMODULE kern) +set(CC_SRC + avl_tree.c + libkern.c + kmain.c + print.c + spin_lock.c + ) + +include(${MK}/kern.cmake) + diff --git a/kern/avl_tree.c b/kern/avl_tree.c new file mode 100644 index 0000000..32a1412 --- /dev/null +++ b/kern/avl_tree.c @@ -0,0 +1,462 @@ +#include <kern/avl_tree.h> +#include <kern/libkern.h> +#include <kern/poison.h> +#include <kern/cdef.h> + +static inline struct avl_node * +_avl_node_max(struct avl_node *node) +{ + while (node != NULL) { + node = node->right; + } + return node; +} + +/* the minimum in the subtree with parent */ +static inline struct avl_node * +_avl_node_minp(struct avl_node *node, struct avl_node **parent) +{ + struct avl_node *p = NULL; + + while (node != NULL) { + p = node; + node = node->left; + } + + if (parent != NULL) { + *parent = p; + } + return node; +} + +static inline struct avl_node * +_avl_node_min(struct avl_node *node) +{ + return _avl_node_minp(node, NULL); +} + +static inline void +_avl_node_poison(struct avl_node *node) +{ + node->left = POISON_AVL; + node->right = POISON_AVL; +} + +static inline int +_avl_node_height(struct avl_node *node) +{ + return node == NULL ? -1 : node->height; +} + + +static inline int +_avl_node_bf(struct avl_node *node) +{ + if (node == NULL) { + return 0; + } + return _avl_node_height(node->left) - _avl_node_height(node->right); +} + + +static inline struct avl_node * +_avl_node_rr(struct avl_node *node) +{ + struct avl_node *lchild = node->left; + node->left = lchild->right; + lchild->right = node; + + node->height = MAX(_avl_node_height(node->left), _avl_node_height(node->right)) + 1; + lchild->height = MAX(_avl_node_height(lchild->left), _avl_node_height(lchild->right)) + 1; + return lchild; +} + + +static inline struct avl_node * +_avl_node_lr(struct avl_node *node) +{ + struct avl_node *rchild = node->right; + node->right = rchild->left; + rchild->left = node; + + node->height = MAX(_avl_node_height(node->left), _avl_node_height(node->right)) + 1; + rchild->height = MAX(_avl_node_height(rchild->left), _avl_node_height(rchild->right)) + 1; + return rchild; +} + +/* balances the subtree, returns the new root of the subtree */ +static struct avl_node * +_avl_node_balance(struct avl_node *node) +{ + int bf; + int cbf; + + bf = _avl_node_bf(node); + + if (bf > 1) { + /* + * Left double heavy + */ + cbf = _avl_node_bf(node->left); + if (cbf >= 0) { + /* + * + * Left child is left heavy + * x (k) y (k-1) + * / \ RR(x) / \ + * (k-1) y A (k-3) -----------> (k-2)B x (k-2) + * / \ / \ + * (k-2) B C (k-3) (k-3) C A (k-3) + */ + return _avl_node_rr(node); + } else { + /* + * + * Left child is right heavy + * x (k) x (k) + * / \ / \ + * (k-1) y A (k-3) LR(y) (k-1) z A (k-3) + * / \ ------------> / \ + * (k-3) B z (k-2) (k-2) y D (k-4) + * / \ / \ + * (k-3) C D (k-4) (k-3) B C (k-3) + * + * + * x (k) __z__ (k-1) + * / \ / \ + * (k-1) z A (k-3) (k-2) y x (k-2) + * / \ RR(x) / \ / \ + * (k-2) y D (k-4) ------------> B C D A + * / \ + * (k-3)B C (k-3) + */ + node->left = _avl_node_lr(node->left); + return _avl_node_rr(node); + } + } else if (bf < -1) { + { + cbf = _avl_node_bf(node->right); + if (cbf <= 0) { + // right right, see above + return _avl_node_lr(node); + } else { + // right left, see above + node->right = _avl_node_rr(node->right); + return _avl_node_lr(node); + } + } + } else { + return node; + } +} + +/* does not allow duplicates, returns the new root of the subtree after insertion */ +static struct avl_node * +_avl_node_insert(struct avl_node *node, struct avl_node *entry, avl_cmpf cmpf, struct avl_node **out) +{ + if (node == NULL) { + /* leaf */ + entry->height = 0; + entry->left = NULL; + entry->right = NULL; + *out = entry; + return entry; + } + + int comp = cmpf(node, entry); + if (comp < 0) { + node->right = _avl_node_insert(node->right, entry, cmpf, out); + } else if (comp == 0) { + /* duplicate */ + *out = NULL; + return node; + } else { + node->left = _avl_node_insert(node->left, entry, cmpf, out); + } + + node->height = MAX(_avl_node_height(node->left), _avl_node_height(node->right)) + 1; + + return _avl_node_balance(node); +} + +/* find the node and its parent in the subtree */ +static struct avl_node * +_avl_node_search(struct avl_node *node, struct avl_node *entry, avl_cmpf cmpf) +{ + int comp; + + while (node != NULL) { + comp = cmpf(node, entry); + if (comp < 0) { + node = node->right; + } else if (comp > 0) { + node = node->left; + } else { + break; + } + } + + return node; +} + + +static struct avl_node * +_avl_node_delete(struct avl_node *node, struct avl_node *entry, avl_cmpf cmpf, struct avl_node **deleted) +{ + int comp; + struct avl_node *succ_parent; + + if (node == NULL) { + return NULL; + } + + comp = cmpf(node, entry); + if (comp < 0) { + node->right = _avl_node_delete(node->right, entry, cmpf, deleted); + } else if (comp > 0) { + node->left = _avl_node_delete(node->left, entry, cmpf, deleted); + } else { + /* + * Write the deleted node first + */ + *deleted = node; + + if ((node->left == NULL) || (node->right == NULL)) { + /* + * 0 or 1 child + */ + struct avl_node *child = node->left != NULL ? node->left : node->right; + + if (child == NULL) { + node = NULL; + } else { + node = child; + } + } else { + /* + * 2 children + * meaning that the successor must be in the right subtree + */ + struct avl_node *succ = _avl_node_minp(node->right, &succ_parent); + + /* + * Swap the nodes + * note that after swapping, the BST property of the right subtree is preserved + */ + if (succ_parent == node) { + /* + * check special case where the successor is the right child + */ + node->right = succ->right; + succ->right = node; + } else { + if (succ_parent->left == succ) { + succ_parent->left = node; + } else { + succ_parent->right = node; + } + SWAP(&node->right, &succ->right); + } + SWAP(&node->left, &succ->left); + SWAP(&node->height, &succ->height); + + /* + * Delete the node from the right subtree + */ + succ->right = _avl_node_delete(succ->right, node, cmpf, deleted); + + node = succ; + } + + /* poison the node */ + _avl_node_poison(*deleted); + } + + /* + * balance the new head + */ + if (node != NULL) { + node->height = MAX(_avl_node_height(node->left), _avl_node_height(node->right)) + 1; + node = _avl_node_balance(node); + } + + return node; +} + + +struct avl_node * +avl_first(struct avl_root *root) +{ + return _avl_node_min(root->root); +} + + +struct avl_node * +avl_last(struct avl_root *root) +{ + return _avl_node_max(root->root); +} + + +struct avl_node * +avl_next(struct avl_root *root, struct avl_node *entry) +{ + struct avl_node *succ; + struct avl_node *node; + int comp; + + if (entry->right != NULL) { + succ = _avl_node_min(entry->right); + } else { + succ = NULL; + node = root->root; + + while (node != NULL) { + comp = root->cmpf(node, entry); + + if (comp < 0) { + node = node->right; + } else if (comp > 0) { + succ = node; + node = node->left; + } else { + break; + } + } + } + + return succ; +} + + +struct avl_node * +avl_prev(struct avl_root *root, struct avl_node *entry) +{ + struct avl_node *prev; + struct avl_node *node; + int comp; + + if (entry->left != NULL) { + prev = _avl_node_max(entry->left); + } else { + prev = NULL; + node = root->root; + + while (node != NULL) { + comp = root->cmpf(node, entry); + + if (comp < 0) { + prev = node; + node = node->right; + } else if (comp > 0) { + node = node->left; + } else { + break; + } + } + } + + return prev; +} + + +struct avl_node * +avl_search(struct avl_root *root, struct avl_node *entry) +{ + return _avl_node_search(root->root, entry, root->cmpf); +} + + +struct avl_node * +avl_insert(struct avl_root *root, struct avl_node *entry) +{ + struct avl_node *old; + + root->root = _avl_node_insert(root->root, entry, root->cmpf, &old); + + return old; +} + + +struct avl_node * +avl_remove(struct avl_root *root, struct avl_node *entry) +{ + struct avl_node *node; + + node = NULL; + root->root = _avl_node_delete(root->root, entry, root->cmpf, &node); + return node; +} + + +usize +avl_size(struct avl_root *root) +{ + usize size; + struct avl_node *node; + + if (avl_empty(root)) + return 0; + + size = 0; + node = _avl_node_min(root->root); + while (node != NULL) { + size++; + node = avl_next(root, node); + } + + return size; +} + +/* + * For tests + */ + +static int +_avl_node_calc_height(struct avl_node *tree) +{ + if (tree == NULL) { + return -1; + } + + return MAX(_avl_node_calc_height(tree->left), _avl_node_calc_height(tree->right)) + 1; +} + + +static int +_avl_node_test(struct avl_node *tree, avl_cmpf compare) +{ + if (tree == NULL) { + return 1; + } + + if (_avl_node_bf(tree) < -1 || _avl_node_bf(tree) > 1 || + _avl_node_calc_height(tree) != tree->height) { + return 0; + } + + if (tree->height == 0 && ((tree->left != NULL) || (tree->right != NULL))) { + return 0; + } + + if (tree->right == tree || tree->left == tree || (tree->right == tree->left && tree->right != NULL)) { + return 0; + } + + if ((tree->right != NULL && compare(tree, tree->right) > 0) || + (tree->left != NULL && compare(tree, tree->left) < 0)) { + return 0; + } + + return _avl_node_test(tree->left, compare) && _avl_node_test(tree->right, compare); +} + +int +avl_validate(struct avl_root *root) +{ + if (avl_empty(root)) { + return 1; + } + + return _avl_node_test(root->root, root->cmpf); +} diff --git a/kern/kmain.c b/kern/kmain.c new file mode 100644 index 0000000..d429df1 --- /dev/null +++ b/kern/kmain.c @@ -0,0 +1,35 @@ +#include <kern/cdef.h> +#include <kern/brute.h> +#include <kern/kinit.h> +#include <kern/libkern.h> + +static int +kinit_cmpf(const void *ki1, const void *ki2) +{ + const struct kinit *const *kinit1 = ki1; + const struct kinit *const *kinit2 = ki2; + + return (*kinit1)->pri - (*kinit2)->pri; +} + +static void +init_kinit() +{ + qsort(KINIT_START, ((uintptr) KINIT_STOP - (uintptr) KINIT_START) / sizeof(struct kinit *), sizeof(struct kinit *), + kinit_cmpf); + for (struct kinit **it = KINIT_START; it < KINIT_STOP; it++) { + (*it)->func((*it)->args); + } +} + +/** + * Kernel entry point + * @param boot_info passed by the bootloader + */ +ATTR_UNUSED void KABI +kmain(ATTR_UNUSED void *boot_info) +{ + KASSERT(boot_info != NULL, "bootinfo is NULL"); + init_kinit(); + BRUTE("Control reached end of kmain"); +} diff --git a/kern/libkern.c b/kern/libkern.c new file mode 100644 index 0000000..398087e --- /dev/null +++ b/kern/libkern.c @@ -0,0 +1,147 @@ +#include <kern/cdef.h> +#include <kern/libkern.h> + +void +memswp(void *dst, void *src, usize size) +{ + char tmp; + char *buf1 = dst; + char *buf2 = src; + + while (size--) { + tmp = *buf1; + *buf1 = *buf2; + *buf2 = tmp; + + buf1++; + buf2++; + } +} + +void * +memcpy(void *dst, const void *src, usize size) +{ + const char *csrc = (const char *) src; + char *cdst = (char *) dst; + while (size--) { + *(cdst++) = *(csrc++); + } + + return dst; +} + +void * +memset(void *dst, int val, usize size) +{ + while (size--) { + *(uint8 *) dst = (uchar) val; + dst = (void *) ((uintptr) dst + 1); + } + + return dst; +} + +void * +memmove(void *dst, const void *src, usize size) +{ + if (src >= dst) { + memcpy(dst, src, size); + } else { + src = (void *) ((uintptr) src + size - 1); + dst = (void *) ((uintptr) dst + size - 1); + while (size--) { + *(char *) dst = *(char *) src; + dst = (void *) ((uintptr) dst - 1); + src = (void *) ((uintptr) src - 1); + } + } + return dst; +} + +/* + * randoms taken from FreeBSD + */ + +#define NSHUFF (50) + +static ulong seed = 937186357; + +ulong +krand() +{ + long x, hi, lo, t; + + /* + * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1). + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + /* Can't be initialized with 0, so use another value. */ + if ((x = seed) == 0) + x = 123459876; + hi = x / 127773; + lo = x % 127773; + t = 16807 * lo - 2836 * hi; + if (t < 0) + t += 0x7fffffff; + seed = t; + return (t); +} + +void +ksrand(ulong sd) +{ + seed = sd; + for (int i = 0; i < NSHUFF; i++) { + krand(); + } +} + +/* + * quicksort + */ +static int +_qsort_partition(void *base, size_t num, size_t sz, int (*cmpf)(const void *, const void *)) +{ + void *smaller = base; + void *pivot = (char *)base + (num - 1) * sz; + /* number of items smaller than pivot */ + int smaller_idx = 0; + + /* pivot = last element */ + while (base < pivot) { + if (cmpf(base, pivot) < 0) { + /* base < pivot */ + + /*swap smaller and base*/ + if (smaller != base) { + memswp(smaller, base, sz); + } + + smaller_idx++; + smaller = (char*)smaller + sz; + } + base = (char*)base + sz; + + } + + /* swap the pivot to its correct position */ + if (smaller != pivot) { + memswp(smaller, pivot, sz); + } + + return smaller_idx; +} + +void +qsort(void *base, size_t num, size_t sz, int (*cmpf)(const void *, const void *)) +{ + int pivot; + if (num > 0) { + pivot = _qsort_partition(base, num, sz, cmpf); + + qsort(base, pivot, sz, cmpf); + qsort((char*)base + (pivot + 1) * sz, (num - pivot - 1), sz, cmpf); + } +} diff --git a/kern/print.c b/kern/print.c new file mode 100644 index 0000000..82cd563 --- /dev/null +++ b/kern/print.c @@ -0,0 +1,159 @@ +#include <kern/print.h> +#include <arch/print.h> +#include <kern/libkern.h> +#include <kern/spin_lock.h> + +/* max space needed for each byte is when printing it in binary = 8 bits */ +#define NBUF_SZ (sizeof(uintmax) * 8) + +static char nbuf[NBUF_SZ]; +static struct spin_lock print_lock = SPIN_LOCK_INITIALIZER; + +static int +_printu(char *buf, uintmax num, uint base, int cap) +{ + int len; + char c; + + len = 0; + while (num > 0) { + c = dtoa(num % base); + if (cap) { + c = (char) toupper(c); + } + buf[len] = c; + + len++; + num = num / base; + } + + return len; +} + +static int +_vprintf(const char *fmt, va_list args) +{ + uintmax num; + char c; + const char * s; + int base, usignf, capf, sz_ptr, sz_long, len, ret; + + ret = 0; + + for (; *fmt != '\0'; fmt++) { + if (*fmt != '%') { + arch_putc(*fmt); + continue; + } + + base = 10; + usignf = 0; + sz_ptr = 0; + sz_long = 0; + capf = 0; + + retry: + fmt++; + switch (*fmt) { + case 'p': + sz_ptr = 1; + goto pnum; + case 'd': + goto pnum; + case 'u': + usignf = 1; + goto pnum; + case 's': + s = (char*)va_arg(args, char *); + while (*s != '\0') { + arch_putc(*s); + s++; + ret++; + } + break; + case 'c': + c = (char) va_arg(args, int); + arch_putc(c); + ret++; + break; + case 'x': + base = 16; + usignf = 1; + goto pnum; + case 'X': + base = 16; + usignf = 1; + capf = 1; + goto pnum; + case 'l': + sz_long = 1; + goto retry; + case '%': + arch_putc('%'); + ret++; + break; + default: + /* ignore */ + break; + pnum: + if (usignf) { + if (sz_ptr) { + num = (uintptr) va_arg(args, uintptr); + } else if (sz_long) { + num = (ulong) va_arg(args, ulong); + } else { + num = (uint) va_arg(args, uint); + } + } else { + if (sz_ptr) { + num = (uintptr) va_arg(args, uintptr); + } else if (sz_long) { + num = (long) va_arg(args, long); + } else { + num = (int) va_arg(args, int); + } + } + /* print num */ + if (!usignf && (intmax) num < 0) { + num = -(intmax)num; + arch_putc('-'); + } + + len = _printu(nbuf, num, base, capf); + while (len) { + arch_putc(nbuf[len]); + len--; + } + ret += len; + } + } + + return ret; +} + +ATTR_FMT_PRINTF int +kprintf(const char *fmt, ...) +{ + int ret; + va_list args; + va_start(args, fmt); + + spin_lock_acq(&print_lock); + ret = _vprintf(fmt, args); + spin_lock_rel(&print_lock); + + va_end(args); + return ret; +} + +int +kvprintf(const char *fmt, va_list args) +{ + int ret; + + spin_lock_acq(&print_lock); + ret = _vprintf(fmt, args); + spin_lock_rel(&print_lock); + + return ret; +} diff --git a/kern/spin_lock.c b/kern/spin_lock.c new file mode 100644 index 0000000..ad724c1 --- /dev/null +++ b/kern/spin_lock.c @@ -0,0 +1,60 @@ +#include <kern/cdef.h> +#include <kern/spin_lock.h> + +static inline uint32 +_spin_lock_get_ticket(uint32 val) +{ + return val & 0xFFFFu; +} + +static inline uint32 +_spin_lock_get_owner(uint32 val) +{ + return val >> 16u; +} + +void +spin_lock_init(struct spin_lock *lock) +{ + atomic_store(&lock->val, 0); +} + +void +spin_lock_acq(struct spin_lock *lock) +{ + uint32 val; + + do { + val = atomic_load(&lock->val); + } while (!atomic_compare_exchange_weak(&lock->val, &val, val + (1u << 16u))); + + // val now contains cur ticket and target ticket + while (_spin_lock_get_ticket(val) != _spin_lock_get_owner(val)) { + val = atomic_load(&lock->val); + } + + // owner = ticket, we've acquired the lock +} + +void +spin_lock_rel(struct spin_lock *lock) +{ + // increment ticket + atomic_fetch_add(&lock->val, 1); +} + +int +spin_lock_try_acq(struct spin_lock *lock) +{ + uint32 val; + + val = atomic_load(&lock->val); + + if ((_spin_lock_get_owner(val) == _spin_lock_get_ticket(val)) && + atomic_compare_exchange_weak(&lock->val, &val, val + (1u << 16u))) { + return 1; + } + + return 0; +} + diff --git a/kernel/Rules.mk b/kernel/Rules.mk deleted file mode 100644 index ccb5180..0000000 --- a/kernel/Rules.mk +++ /dev/null @@ -1,16 +0,0 @@ -include $(MK)/prologue.mk - -MOD:=KERNEL -C_FLAGS_$(MOD):=$(addprefix -I, $(d)/inc) -AS_FLAGS_$(MOD):=$(addprefix -I, $(d)/inc) - -dir := $(d)/ke -include $(dir)/Rules.mk -dir := $(d)/mm -include $(dir)/Rules.mk -dir := $(d)/rf -include $(dir)/Rules.mk -dir := $(d)/lb -include $(dir)/Rules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/kernel/inc/ke/alloc.h b/kernel/inc/ke/alloc.h deleted file mode 100644 index 520d355..0000000 --- a/kernel/inc/ke/alloc.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "cdef.h" - -void -ke_alloc_init(void); - -void * -ke_alloc(uint32 size); - -void -ke_free(void *ptr); diff --git a/kernel/inc/ke/assert.h b/kernel/inc/ke/assert.h deleted file mode 100644 index 7a32136..0000000 --- a/kernel/inc/ke/assert.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "cdef.h" - -#define KE_ASSERT(expr) ke_assert_ex(#expr, __FILE__, __LINE__, expr) - -void -ke_assert_ex(const char *expr_str, const char *file, int32 line, int32 expr); diff --git a/kernel/inc/ke/atomic.h b/kernel/inc/ke/atomic.h deleted file mode 100644 index bd844f5..0000000 --- a/kernel/inc/ke/atomic.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "cdef.h" - -int32 -ke_atomic_xchg_32(int32 *target, int32 val); - -int32 -ke_atomic_inc_32(int32 *target, int32 increment); - -int32 -ke_atmoic_cmpxchg_32(int32 *target, int32 compare, int32 val); diff --git a/kernel/inc/ke/intr.h b/kernel/inc/ke/intr.h deleted file mode 100644 index 712cc2e..0000000 --- a/kernel/inc/ke/intr.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "cdef.h" - -#define IRQL_LOW (0) -#define IRQL_DPC (1) -#define IRQL_HIGH (2) -#define IRQL_NUM (3) - -uint32 -ke_raise_irql(uint32 irql); - -uint32 -ke_lower_irql(uint32 irql); - -uint32 -ke_get_irql(void); - -void -ke_issue_intr(uint32 core, uint32 vector); - -typedef void (KABI *k_intr_handler)(void* k_context); - -void -ke_reg_intr(uint32 vec, k_intr_handler); - -void -ke_dereg_intr(uint32 vec); - -#define EXC_UNRCVY (0) -#define EXC_DIV (1) -#define EXC_PROT (2) -#define EXC_OP (3) -#define EXC_PF (4) -#define EXC_UNSUP (5) -#define EXC_DEBUG (6) - -typedef void (KABI *k_exc_handler)(uintptr exc_addr, uint64 err_code); - -void -ke_reg_exc(uint32 vec, k_exc_handler handler); - -void -ke_dereg_exc(uint32 vec); - -uint32 -ke_get_core_id(void); - diff --git a/kernel/inc/ke/panic.h b/kernel/inc/ke/panic.h deleted file mode 100644 index 8808167..0000000 --- a/kernel/inc/ke/panic.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "cdef.h" - -void -ke_panic(uint32 reason); diff --git a/kernel/inc/ke/print.h b/kernel/inc/ke/print.h deleted file mode 100644 index bfa4a2a..0000000 --- a/kernel/inc/ke/print.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "cdef.h" - -void -ke_printf(const char *str, ...); - -void -ke_vprintf(const char *str, va_list args); diff --git a/kernel/inc/ke/rww_lock.h b/kernel/inc/ke/rww_lock.h deleted file mode 100644 index accfcd8..0000000 --- a/kernel/inc/ke/rww_lock.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "cdef.h" -#include "ke/spin_lock.h" - -struct rww_lock -{ - struct spin_lock w_mutex; - struct spin_lock r_mutex; - struct spin_lock res_lock; - struct spin_lock r_try; - uint32 reader_ct; - uint32 writer_ct; -}; - -void -ke_rww_init(struct rww_lock *lock); - -void -ke_rww_r_lock(struct rww_lock *lock); - -void -ke_rww_r_unlock(struct rww_lock *lock); - -void -ke_rww_w_lock(struct rww_lock *lock); - -void -ke_rww_w_unlock(struct rww_lock *lock); diff --git a/kernel/inc/ke/spin_lock.h b/kernel/inc/ke/spin_lock.h deleted file mode 100644 index 3e6125a..0000000 --- a/kernel/inc/ke/spin_lock.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "cdef.h" - -struct spin_lock -{ - int32 val; -}; - -void -ke_spin_init(struct spin_lock *lock); - -void -ke_spin_lock(struct spin_lock *lock); - -void -ke_spin_unlock(struct spin_lock *lock); diff --git a/kernel/inc/lb/atree.h b/kernel/inc/lb/atree.h deleted file mode 100644 index 5bb0239..0000000 --- a/kernel/inc/lb/atree.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include "cdef.h" - - -struct atree_node -{ - struct atree_node *left; - struct atree_node *right; - int32 height; -}; - -/** -* A comparison function between self (yours) and treenode (tree's) -* Returns: -* < 0 if treenode < self -* = 0 if treenode = self -* > 0 if treenode > self -*/ -typedef int32 (*atree_cmp_fp)(struct atree_node *tree_node, struct atree_node *self); - -struct atree -{ - atree_cmp_fp cmpf; - struct atree_node *root; -}; - - -struct atree_node * -lb_atree_search(struct atree *tree, struct atree_node *entry); - - -struct atree_node * -lb_atree_insert(struct atree *tree, struct atree_node *entry); - - -struct atree_node * -lb_atree_delete(struct atree *tree, struct atree_node *entry); - - -void -lb_atree_init(struct atree *tree, atree_cmp_fp compare); - - -struct atree_node * -lb_atree_max(struct atree *tree); - - -struct atree_node * -lb_atree_min(struct atree *tree); - - -struct atree_node * -lb_atree_next(struct atree *tree, struct atree_node *entry); - - -struct atree_node * -lb_atree_prev(struct atree *tree, struct atree_node *entry); - -bool -lb_atree_validate(struct atree *tree); - -uint32 -lb_atree_size(struct atree *tree); - diff --git a/kernel/inc/lb/llist.h b/kernel/inc/lb/llist.h deleted file mode 100644 index 28cde95..0000000 --- a/kernel/inc/lb/llist.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include "cdef.h" - -struct llist_node -{ - struct llist_node *prev; - struct llist_node *next; -}; - -struct llist -{ - struct llist_node *head; - struct llist_node *tail; - uint32 size; -}; - -void -lb_llist_init(struct llist *list); - -uint32 -lb_llist_size(struct llist *list); - -void -lb_llist_push_front(struct llist *list, struct llist_node *node); - -void -lb_llist_push_back(struct llist *list, struct llist_node *node); - -struct llist_node * -lb_llist_pop_front(struct llist *list); - - -struct llist_node * -lb_llist_pop_back(struct llist *list); - -void -lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node); - -struct llist_node * -lb_llist_remove_by_idx(struct llist *list, uint32 index); - - -struct llist_node * -lb_llist_get(struct llist *list, uint32 index); - - -void -lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node); - - -struct llist_node * -lb_llist_remove_by_ref(struct llist *list, struct llist_node *node); - - -struct llist_node * -lb_llist_next(struct llist_node *node); - - -struct llist_node * -lb_llist_prev(struct llist_node *node); - - -struct llist_node * -lb_llist_first(struct llist *list); - - -struct llist_node * -lb_llist_last(struct llist *list); diff --git a/kernel/inc/lb/salloc.h b/kernel/inc/lb/salloc.h deleted file mode 100644 index 8434f09..0000000 --- a/kernel/inc/lb/salloc.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "cdef.h" - -void -lb_salloc_init(void *base, uint32 size); - -void * -lb_salloc(void *base, uint32 size); - -void -lb_sfree(void *base, void *ptr); - -bool -lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size); - diff --git a/kernel/inc/mm/pmm.h b/kernel/inc/mm/pmm.h deleted file mode 100644 index 3ff7127..0000000 --- a/kernel/inc/mm/pmm.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "cdef.h" -#include "status.h" -#include "kernel.h" -#include "mlayout.h" - -/** - * physical page allocation - */ -k_status -mm_alloc_page(uintptr *out); - -k_status -mm_free_page(uintptr base); - -k_status -mm_query_page_attr(uintptr base, int32 *out); - -k_status -mm_pmm_init(struct boot_info *info); diff --git a/kernel/inc/rf/ref.h b/kernel/inc/rf/ref.h deleted file mode 100644 index e266413..0000000 --- a/kernel/inc/rf/ref.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "cdef.h" -#include "status.h" -#include "lb/atree.h" - -typedef uint32 k_ident; - -typedef void (*ref_free_fp)(void *); - -struct ref_node -{ - int32 ref_count; - ref_free_fp f_free; -}; - -struct ident_node -{ - struct atree_node tree_node; - k_ident ident; - struct ref_node *obj; - ref_free_fp free_routine; -}; - -// -// All functions are sx since users or kernel devs should not be -// specifying where the allocations take place -// - -k_status -rf_ref_init(void); - -k_status -rf_ref_node_init(struct ref_node *rf_node, ref_free_fp free_func); - -k_status -rf_ref_obj(struct ref_node *rf_node); - -k_status -rf_deref_obj(struct ref_node *rf_node); - -k_status -rf_open_obj_by_ident(k_ident id, struct ref_node **out); - -k_status -rf_ident_create(struct ref_node *rf_node, struct ident_node *id_node, k_ident *out); - -k_status -rf_ident_close(k_ident id); - diff --git a/kernel/inc/status.h b/kernel/inc/status.h deleted file mode 100644 index 90fb14f..0000000 --- a/kernel/inc/status.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "cdef.h" - -typedef uint32 k_status; - -/** - * Specific error codes - */ - -#define STATUS_SUCCESS (0x0) - -#define STATUS_INVALID_ARGS (0x1) -#define STATUS_NO_MEM (0x2) -#define STATUS_UNINITIALIZED (0x3) -#define STATUS_DUPLICATE (0x4) - -#define SX_SUCCESS(val) ((val) == (STATUS_SUCCESS)) diff --git a/kernel/ke/Rules.mk b/kernel/ke/Rules.mk deleted file mode 100644 index f61901f..0000000 --- a/kernel/ke/Rules.mk +++ /dev/null @@ -1,15 +0,0 @@ -include $(MK)/prologue.mk - -SRC_$(d) := $(d)/alloc.c \ - $(d)/assert.c \ - $(d)/atomic.c \ - $(d)/panic.c \ - $(d)/intr.c \ - $(d)/print.c \ - $(d)/rww_lock.c \ - $(d)/spin_lock.c \ - $(d)/main.c - -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/kernel/ke/alloc.c b/kernel/ke/alloc.c deleted file mode 100644 index 4d76e31..0000000 --- a/kernel/ke/alloc.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "ke/alloc.h" -#include "lb/salloc.h" - -#define K_KERNEL_HEAP_SIZE 8192 - -static bool alloc_initialized; -static uint8 alloc_heap[K_KERNEL_HEAP_SIZE]; - -void -ke_alloc_init(void) -{ - if (!alloc_initialized) - { - lb_salloc_init(alloc_heap, K_KERNEL_HEAP_SIZE); - alloc_initialized = TRUE; - } -} - -void * -ke_alloc(uint32 size) -{ - return alloc_initialized ? lb_salloc(alloc_heap, size) : NULL; -} - -void -ke_free(void *ptr) -{ - if (alloc_initialized) - { - lb_sfree(alloc_heap, ptr); - } -} diff --git a/kernel/ke/assert.c b/kernel/ke/assert.c deleted file mode 100644 index d7cbabb..0000000 --- a/kernel/ke/assert.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "ke/assert.h" -#include "ke/print.h" - -void ke_assert_ex(const char *expr_str, const char *file, int32 line, int32 expr) -{ - if (!expr) - { - ke_printf("Assertion \"%s\" failed at %s:%d.\n", expr_str, file, line); - } -} diff --git a/kernel/ke/atomic.c b/kernel/ke/atomic.c deleted file mode 100644 index faaeea6..0000000 --- a/kernel/ke/atomic.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "ke/atomic.h" -#include "hal.h" - -int32 ke_atomic_xchg_32(int32 *target, int32 val) -{ - return hal_atomic_xchg_32(target, val); -} - -int32 ke_atomic_inc_32(int32 *target, int32 increment) -{ - return hal_atomic_inc_32(target, increment); -} - -int32 ke_atmoic_cmpxchg_32(int32 *target, int32 compare, int32 val) -{ - return hal_atomic_cmpxchg_32(target, compare, val); -} - diff --git a/kernel/ke/intr.c b/kernel/ke/intr.c deleted file mode 100644 index 5f19ef5..0000000 --- a/kernel/ke/intr.c +++ /dev/null @@ -1,86 +0,0 @@ -#include "cdef.h" -#include "status.h" -#include "intrp.h" -#include "ke/assert.h" - -uint32 -ke_raise_irql(uint32 irql) -{ - KE_ASSERT(ke_get_irql() <= irql); - return hal_set_irql(irql); -} - - -uint32 -ke_lower_irql(uint32 irql) -{ - uint32 old_irql = ke_get_irql(); - KE_ASSERT(old_irql >= irql); - return hal_set_irql(irql); -} - - -uint32 -ke_get_irql(void) -{ - return hal_get_irql(); -} - - -void -ke_issue_intr(uint32 core, uint32 vector) -{ - hal_issue_intr(core, vector); -} - - -void -ke_reg_intr(uint32 vec, k_intr_handler handler) -{ - // TODO: implement kernel dispatch table - UNREFERENCED(vec); - UNREFERENCED(handler); -} - - -void -ke_dereg_intr(uint32 vec) -{ - // TODO: implement kernel dispatch table - UNREFERENCED(vec); -} - - -void -ke_reg_exc(uint32 vec, k_exc_handler handler) -{ - // TODO: implement kernel dispatch table - UNREFERENCED(vec); - UNREFERENCED(handler); -} - - -void -ke_dereg_exc(uint32 vec) -{ - // TODO: implement kernel dispatch table - UNREFERENCED(vec); -} - - -uint32 -ke_get_core_id(void) -{ - return hal_get_core_id(); -} - - -k_status -kp_intr_init(struct boot_info *info) -{ - // TODO: initialize kernel dispatch table - UNREFERENCED(info); - return STATUS_INVALID_ARGS; -} - - diff --git a/kernel/ke/intrp.h b/kernel/ke/intrp.h deleted file mode 100644 index a118d51..0000000 --- a/kernel/ke/intrp.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "hal.h" -#include "ke/intr.h" -#include "status.h" -#include "kernel.h" - -k_status -kp_intr_init(struct boot_info *info); diff --git a/kernel/ke/main.c b/kernel/ke/main.c deleted file mode 100644 index 315de7f..0000000 --- a/kernel/ke/main.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "kernel.h" -#include "cdef.h" -#include "intrp.h" -#include "mm/pmm.h" -#include "ke/panic.h" - -/** - * Kernel entry point - * @param boot_info passed by the bootloader - */ -void KABI -kmain(struct boot_info *boot_info) -{ - k_status status; - - // initialize interrupts - status = kp_intr_init(boot_info); - if (!SX_SUCCESS(status)) - { - goto end; - } - - // initialize memory manager - status = mm_pmm_init(boot_info); - if (!SX_SUCCESS(status)) - { - goto end; - } - -end: - if (!SX_SUCCESS(status)) - { - ke_panic(status); - } - - ke_panic(0x0); -} - diff --git a/kernel/ke/panic.c b/kernel/ke/panic.c deleted file mode 100644 index 323595e..0000000 --- a/kernel/ke/panic.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "ke/panic.h" -#include "ke/print.h" -#include "hal.h" - -void ke_panic(uint32 reason) -{ - ke_printf("BugCheck: Reason - %ul\n", reason); - hal_halt(); -} diff --git a/kernel/ke/print.c b/kernel/ke/print.c deleted file mode 100644 index acf9f61..0000000 --- a/kernel/ke/print.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "ke/print.h" -#include "ke/assert.h" - -void -ke_printf(const char *str, ...) -{ - va_list args; - va_start(args, str); - ke_vprintf(str, args); - va_end(args); -} - -void -ke_vprintf(const char *str, va_list args) -{ - //TODO: implement - KE_ASSERT(0); - UNREFERENCED(str); - UNREFERENCED(args); -} diff --git a/kernel/ke/rww_lock.c b/kernel/ke/rww_lock.c deleted file mode 100644 index 2cd7b23..0000000 --- a/kernel/ke/rww_lock.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "ke/rww_lock.h" - -void -ke_rww_init(struct rww_lock *lock) -{ - if (lock != NULL) - { - ke_spin_init(&lock->w_mutex); - ke_spin_init(&lock->r_mutex); - ke_spin_init(&lock->res_lock); - ke_spin_init(&lock->r_try); - lock->reader_ct = 0; - lock->writer_ct = 0; - } -} - -void -ke_rww_r_lock(struct rww_lock *lock) -{ - if (lock != NULL) - { - ke_spin_lock(&lock->r_try); - ke_spin_lock(&lock->r_mutex); - lock->reader_ct++; - if (lock->reader_ct == 1) - { - ke_spin_lock(&lock->res_lock); - } - ke_spin_unlock(&lock->r_mutex); - ke_spin_unlock(&lock->r_try); - } -} - -void -ke_rww_r_unlock(struct rww_lock *lock) -{ - if (lock != NULL) - { - ke_spin_lock(&lock->r_mutex); - lock->reader_ct--; - if (lock->reader_ct == 0) - { - ke_spin_unlock(&lock->res_lock); - } - ke_spin_unlock(&lock->r_mutex); - } -} - -void -ke_rww_w_lock(struct rww_lock *lock) -{ - ke_spin_lock(&lock->w_mutex); - lock->writer_ct++; - if (lock->writer_ct == 1) - { - ke_spin_lock(&lock->r_try); - } - ke_spin_unlock(&lock->w_mutex); - ke_spin_lock(&lock->res_lock); -} - -void -ke_rww_w_unlock(struct rww_lock *lock) -{ - ke_spin_unlock(&lock->res_lock); - ke_spin_lock(&lock->w_mutex); - lock->writer_ct--; - if (lock->writer_ct == 0) - { - ke_spin_unlock(&lock->r_try); - } - ke_spin_unlock(&lock->w_mutex); -} diff --git a/kernel/ke/spin_lock.c b/kernel/ke/spin_lock.c deleted file mode 100644 index 0194d23..0000000 --- a/kernel/ke/spin_lock.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "ke/spin_lock.h" -#include "ke/atomic.h" - -void -ke_spin_init(struct spin_lock *lock) -{ - if (lock != NULL) - { - lock->val = 0; - } -} - - -void -ke_spin_lock(struct spin_lock *lock) -{ - if (lock != NULL) - { - while (ke_atmoic_cmpxchg_32(&lock->val, 0, 1) != 0) - {} - } -} - - -void -ke_spin_unlock(struct spin_lock *lock) -{ - if (lock != NULL) - { - lock->val = 0; - } -} - diff --git a/kernel/lb/Rules.mk b/kernel/lb/Rules.mk deleted file mode 100644 index 05ee10e..0000000 --- a/kernel/lb/Rules.mk +++ /dev/null @@ -1,8 +0,0 @@ -include $(MK)/prologue.mk - -SRC_$(d) := $(d)/atree.c \ - $(d)/llist.c \ - $(d)/salloc.c -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/kernel/lb/atree.c b/kernel/lb/atree.c deleted file mode 100644 index 315e410..0000000 --- a/kernel/lb/atree.c +++ /dev/null @@ -1,548 +0,0 @@ -#include "lb/atree.h" -#include "clib.h" - -static struct atree_node * -atree_node_max(struct atree_node *node) -{ - while ((node != NULL) && (node->right != NULL)) - { - node = node->right; - } - return node; -} - - -static struct atree_node * -atree_node_min(struct atree_node *node) -{ - while ((node != NULL) && (node->left != NULL)) - { - node = node->left; - } - return node; -} - - -static void -atree_node_init(struct atree_node *it) -{ - if (it != NULL) - { - it->height = 0; - it->left = NULL; - it->right = NULL; - } -} - - -static int32 -atree_node_get_height(struct atree_node *node) -{ - return node == NULL ? -1 : node->height; -} - - -static int32 -atree_node_get_balance_factor(struct atree_node *node) -{ - if (node == NULL) - { - return 0; - } - return atree_node_get_height(node->left) - atree_node_get_height(node->right); -} - - -static struct atree_node * -atree_node_right_rotate(struct atree_node *node) -{ - struct atree_node *lchild = node->left; - node->left = lchild->right; - lchild->right = node; - - node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1; - lchild->height = MAX(atree_node_get_height(lchild->left), atree_node_get_height(lchild->right)) + 1; - return lchild; -} - - -static struct atree_node * -atree_node_left_rotate(struct atree_node *node) -{ - struct atree_node *rchild = node->right; - node->right = rchild->left; - rchild->left = node; - - node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1; - rchild->height = MAX(atree_node_get_height(rchild->left), atree_node_get_height(rchild->right)) + 1; - return rchild; -} - - -static struct atree_node * -atree_node_balance(struct atree_node *node) -{ - int32 bf; - int32 cbf; - - bf = atree_node_get_balance_factor(node); - - if (bf > 1) - { - /** - * Left double heavy - */ - cbf = atree_node_get_balance_factor(node->left); - if (cbf >= 0) - { - /** - * - * Left child is left heavy - * x (k) y (k-1) - * / \ RR(x) / \ - * (k-1) y A (k-3) -----------> (k-2)B x (k-2) - * / \ / \ - * (k-2) B C (k-3) (k-3) C A (k-3) - */ - return atree_node_right_rotate(node); - } - else - { - /** - * - * Left child is right heavy - * x (k) x (k) - * / \ / \ - * (k-1) y A (k-3) LR(y) (k-1) z A (k-3) - * / \ ------------> / \ - * (k-3) B z (k-2) (k-2) y D (k-4) - * / \ / \ - * (k-3) C D (k-4) (k-3) B C (k-3) - * - * - * x (k) __z__ (k-1) - * / \ / \ - * (k-1) z A (k-3) (k-2) y x (k-2) - * / \ RR(x) / \ / \ - * (k-2) y D (k-4) ------------> B C D A - * / \ - * (k-3)B C (k-3) - */ - node->left = atree_node_left_rotate(node->left); - return atree_node_right_rotate(node); - } - } - else if (bf < -1) - { - { - cbf = atree_node_get_balance_factor(node->right); - if (cbf <= 0) - { - // right right, see above - return atree_node_left_rotate(node); - } - else - { - // right left, see above - node->right = atree_node_right_rotate(node->right); - return atree_node_left_rotate(node); - } - } - } - else - { - return node; - } -} - - -static struct atree_node * -atree_node_insert(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **overwritten) -{ - if (node == NULL) - { - atree_node_init(entry); - return entry; - } - - int32 comp = compare(node, entry); - if (comp < 0) - { - node->right = atree_node_insert(node->right, entry, compare, overwritten); - } - else - { - if (comp == 0) - { - /** - * overwrite existing value - */ - atree_node_init(entry); - entry->right = node->right; - entry->left = node->left; - entry->height = node->height; - *overwritten = node; - return entry; - } - else - { - node->left = atree_node_insert(node->left, entry, compare, overwritten); - } - } - - node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1; - - return atree_node_balance(node); -} - - -static struct atree_node * -atree_node_search(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **parent) -{ - int32 comp; - struct atree_node *prev; - struct atree_node *temp; - - prev = NULL; - - while (node != NULL) - { - comp = compare(node, entry); - temp = node; - if (comp < 0) - { - node = node->right; - } - else if (comp > 0) - { - node = node->left; - } - else - { - break; - } - - prev = temp; - } - - if (parent != NULL) - { - *parent = prev; - } - - return node; -} - - -static struct atree_node * -atree_node_delete(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **deleted) -{ - int32 comp; - struct atree_node *succ_parent; - - if (node == NULL) - { - return NULL; - } - - comp = compare(node, entry); - if (comp < 0) - { - node->right = atree_node_delete(node->right, entry, compare, deleted); - } - else if (comp > 0) - { - node->left = atree_node_delete(node->left, entry, compare, deleted); - } - else - { - /** - * Write the deleted node first - */ - *deleted = node; - - if ((node->left == NULL) || (node->right == NULL)) - { - /** - * 0 or 1 child - */ - struct atree_node *child = node->left != NULL ? node->left : node->right; - - if (child == NULL) - { - node = NULL; - } - else - { - node = child; - } - } - else - { - /** - * 2 children - * meaning that the successor must be in the right subtree - */ - struct atree_node *succ = atree_node_min(node->right); - atree_node_search(node, succ, compare, &succ_parent); - - /** - * Swap the nodes - * note that after swapping, the BST property of the right subtree is preserved - */ - if (succ_parent == node) - { - /** - * check special case where the successor is the right child - */ - node->right = succ->right; - succ->right = node; - } - else - { - if (succ_parent->left == succ) - { - succ_parent->left = node; - } - else - { - succ_parent->right = node; - } - SWAP(&node->right, &succ->right, struct atree_node*); - } - SWAP(&node->left, &succ->left, struct atree_node*); - SWAP(&node->height, &succ->height, int32); - - /** - * Delete the node from the right subtree - */ - succ->right = atree_node_delete(succ->right, node, compare, deleted); - - node = succ; - } - } - - /** - * balance the new head - */ - if (node != NULL) - { - node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1; - node = atree_node_balance(node); - } - - return node; -} - - -struct atree_node * -lb_atree_min(struct atree *tree) -{ - return atree_node_min(tree->root); -} - - -struct atree_node * -lb_atree_max(struct atree *tree) -{ - return atree_node_max(tree->root); -} - - -struct atree_node * -lb_atree_next(struct atree *tree, struct atree_node *entry) -{ - struct atree_node *succ; - struct atree_node *node; - int32 comp; - - if (entry->right != NULL) - { - succ = atree_node_min(entry->right); - } - else - { - succ = NULL; - node = tree->root; - - while (node != NULL) - { - comp = tree->cmpf(node, entry); - - if (comp < 0) - { - node = node->right; - } - else if (comp > 0) - { - succ = node; - node = node->left; - } - else - { - break; - } - } - } - - return succ; -} - - -struct atree_node * -lb_atree_prev(struct atree *tree, struct atree_node *entry) -{ - struct atree_node *prev; - struct atree_node *node; - int32 comp; - - if (entry->left != NULL) - { - prev = atree_node_max(entry->left); - } - else - { - prev = NULL; - node = tree->root; - - while (node != NULL) - { - comp = tree->cmpf(node, entry); - - if (comp < 0) - { - prev = node; - node = node->right; - } - else if (comp > 0) - { - node = node->left; - } - else - { - break; - } - } - } - - return prev; -} - - -struct atree_node * -lb_atree_search(struct atree *tree, struct atree_node *entry) -{ - return atree_node_search(tree->root, entry, tree->cmpf, NULL); -} - - -struct atree_node * -lb_atree_insert(struct atree *tree, struct atree_node *entry) -{ - struct atree_node *old; - - old = NULL; - tree->root = atree_node_insert(tree->root, entry, tree->cmpf, &old); - return old; -} - - -struct atree_node * -lb_atree_delete(struct atree *tree, struct atree_node *entry) -{ - struct atree_node *node; - - node = NULL; - tree->root = atree_node_delete(tree->root, entry, tree->cmpf, &node); - return node; -} - - -uint32 -lb_atree_size(struct atree *tree) -{ - uint32 size; - struct atree_node *node; - - size = 0; - if (tree->root != NULL) - { - node = lb_atree_min(tree); - while (node != NULL) - { - size++; - node = lb_atree_next(tree, node); - } - } - return size; -} - - -void -lb_atree_init(struct atree *tree, atree_cmp_fp compare) -{ - tree->cmpf = compare; - tree->root = NULL; -} - - -/** - * Used by tests - */ - -static -int32 -atree_node_calc_height(struct atree_node *tree) -{ - if (tree == NULL) - { - return -1; - } - return MAX(atree_node_calc_height(tree->left), atree_node_calc_height(tree->right)) + 1; -} - - -static -bool -atree_node_test(struct atree_node *tree, atree_cmp_fp compare) -{ - if (tree == NULL) - { - return TRUE; - } - - if (atree_node_get_balance_factor(tree) < -1 || atree_node_get_balance_factor(tree) > 1 || - atree_node_calc_height(tree) != tree->height) - { - return FALSE; - } - - if(tree->height == 0 && ((tree->left != NULL) || (tree->right != NULL))) - { - return FALSE; - } - - if(tree->right == tree || tree->left == tree || (tree->right == tree->left && tree->right != NULL)) - { - return FALSE; - } - - if ((tree->right != NULL && compare(tree, tree->right) > 0) || - (tree->left != NULL && compare(tree, tree->left) < 0)) - { - return FALSE; - } - - return atree_node_test(tree->left, compare) && atree_node_test(tree->right, compare); -} - - -bool -lb_atree_validate(struct atree *tree) -{ - if (tree == NULL) - { - return TRUE; - } - return atree_node_test(tree->root, tree->cmpf); -} diff --git a/kernel/lb/llist.c b/kernel/lb/llist.c deleted file mode 100644 index 5ca7e37..0000000 --- a/kernel/lb/llist.c +++ /dev/null @@ -1,250 +0,0 @@ -#include "lb/llist.h" - -static void -llist_node_init(struct llist_node *node) -{ - node->next = NULL; - node->prev = NULL; -} - - -void -lb_llist_init(struct llist *list) -{ - list->head = NULL; - list->tail = NULL; - list->size = 0; -} - - -uint32 -lb_llist_size(struct llist *list) -{ - return list->size; -} - - -void -lb_llist_push_front(struct llist *list, struct llist_node *node) -{ - llist_node_init(node); - lb_llist_insert_by_ref(list, NULL, node); -} - - -void -lb_llist_push_back(struct llist *list, struct llist_node *node) -{ - llist_node_init(node); - lb_llist_insert_by_ref(list, list->tail, node); -} - - -struct llist_node * -lb_llist_pop_front(struct llist *list) -{ - struct llist_node *ret; - - ret = list->head; - lb_llist_remove_by_ref(list, list->head); - - return ret; -} - - -struct llist_node * -lb_llist_pop_back(struct llist *list) -{ - struct llist_node *ret; - - ret = list->tail; - lb_llist_remove_by_ref(list, list->tail); - - return ret; -} - - -void -lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node) -{ - struct llist_node *left_node; - struct llist_node *right_node; - - if (list == NULL || new_node == NULL) - { - return; - } - - llist_node_init(new_node); - - /* - * adjust the current node - */ - if (cur_node == NULL) - { - new_node->next = list->head; - new_node->prev = NULL; - } - else - { - new_node->prev = cur_node; - new_node->next = cur_node->next; - } - - /* - * assign left and treenode node - */ - if (cur_node == NULL) - { - left_node = NULL; - right_node = list->head == NULL ? NULL : list->head; - } - else - { - left_node = cur_node; - right_node = cur_node->next; - } - - /* - * adjust left and treenode node accordingly - */ - if (left_node != NULL) - { - left_node->next = new_node; - } - else - { - list->head = new_node; - } - - if (right_node != NULL) - { - right_node->prev = new_node; - } - else - { - list->tail = new_node; - } - - list->size++; -} - - -void -lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node) -{ - struct llist_node *prev_node; - - prev_node = lb_llist_get(list, index - 1); - llist_node_init(node); - - if (prev_node == NULL) - { - if (index == 0) - { - lb_llist_insert_by_ref(list, NULL, node); - } - } - else - { - lb_llist_insert_by_ref(list, prev_node, node); - } -} - - -struct llist_node * -lb_llist_remove_by_idx(struct llist *list, uint32 index) -{ - struct llist_node *cur_node; - - cur_node = lb_llist_get(list, index); - - if (cur_node == NULL) - { - return NULL; - } - - return lb_llist_remove_by_ref(list, cur_node); -} - - -/** - * returns the next node - */ -struct llist_node * -lb_llist_remove_by_ref(struct llist *list, struct llist_node *node) -{ - struct llist_node *ret; - - /* - * Adjust the left and treenode node - */ - if (node->prev != NULL) - { - node->prev->next = node->next; - } - else - { - list->head = node->next; - } - - if (node->next != NULL) - { - node->next->prev = node->prev; - } - else - { - list->tail = node->prev; - } - - ret = node->next; - - llist_node_init(node); - - list->size--; - - return ret; -} - - -struct llist_node * -lb_llist_get(struct llist *list, uint32 index) -{ - if (list->head == NULL) - { - return NULL; - } - struct llist_node *cur_node = list->head; - while (index-- && (cur_node = cur_node->next) != NULL) - {} - return cur_node; -} - - -struct llist_node * -lb_llist_next(struct llist_node *node) -{ - return node->next; -} - - -struct llist_node * -lb_llist_prev(struct llist_node *node) -{ - return node->prev; -} - - -struct llist_node * -lb_llist_first(struct llist *list) -{ - return list->head; -} - - -struct llist_node * -lb_llist_last(struct llist *list) -{ - return list->tail; -} - diff --git a/kernel/lb/salloc.c b/kernel/lb/salloc.c deleted file mode 100644 index d347c37..0000000 --- a/kernel/lb/salloc.c +++ /dev/null @@ -1,235 +0,0 @@ -#include "lb/salloc.h" -#include "clib.h" - -struct salloc_header -{ - union - { - uint32 size; - uint32 flags; - }; -}; - -#define ALLOC_FLAG_NUM 2 -#define ALLOC_HEADER_FLAG_FREE 0 -#define ALLOC_HEADER_FLAG_LAST 1 - -static void -set_salloc_header_size(struct salloc_header *header, uint32 size) -{ - // align the integer, ignoring overflowed bits - size <<= ALLOC_FLAG_NUM; - - // clear ALLOC_FLAG_NUM-th to 31-th bits - header->size &= ~(uint32) bit_field_mask(ALLOC_FLAG_NUM, 31); - // set bits - header->size |= size; -} - - -static uint32 -read_salloc_header_size(struct salloc_header *header) -{ - return header->size >> ALLOC_FLAG_NUM; -} - - -static uint32 -read_salloc_header_flag(struct salloc_header *header, uint32 bit) -{ - return (header->flags & (uint32) bit_mask(bit)) == 0 ? 0 : 1; -} - - -static void -set_salloc_header_flag(struct salloc_header *header, uint32 bit, uint32 value) -{ - value &= (uint32) bit_mask(0); - if (value == 1) - { - header->flags |= (uint32) bit_mask(bit); - } - else - { - header->flags &= ~(uint32) bit_mask(bit); - } -} - - -static -void salloc_join(void *base) -{ - if (base != NULL) - { - char *c_ptr = (char *) base; - while (1) - { - uint32 c_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); - uint32 c_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); - uint32 c_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr); - char *n_ptr = c_blk_last == 1 ? NULL : c_ptr + c_blk_size; - if (n_ptr != NULL && c_blk_free == 1) - { - // if this is not the last block and the prev block is free - uint32 n_blk_free = read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_FREE); - uint32 n_blk_last = read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_LAST); - uint32 n_blk_size = read_salloc_header_size((struct salloc_header *) n_ptr); - - if (n_blk_free == 1) - { - // logically gone - set_salloc_header_size((struct salloc_header *) c_ptr, n_blk_size + c_blk_size); - set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, n_blk_last); - continue; - } - } - // update the c_ptr - if (c_blk_last == 0) - { - c_ptr += c_blk_size; - } - else - { - break; - } - } - } -} - - -bool -lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size) -{ - if (base == NULL || blk_free == NULL || blk_size == NULL) - { - return NULL; - } - uint32 i = 0; - char *c_ptr = (char *) base; - while (1) - { - uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); - uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); - uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr); - if (cur_blk_free != blk_free[i] || cur_blk_size != blk_size[i]) - { - return FALSE; - } - else - { - c_ptr += cur_blk_size; - i++; - } - if (cur_blk_last == 1) - { - return i == size; - } - } -} - - -void -lb_salloc_init(void *base, uint32 size) -{ - if (base != NULL && size >= sizeof(struct salloc_header)) - { - struct salloc_header *ptr = (struct salloc_header *) base; - set_salloc_header_size(ptr, size); - set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_FREE, 1); - set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_LAST, 1); - } -} - - -void * -lb_salloc(void *base, uint32 size) -{ - void *result = NULL; - if (base != NULL && size != 0) - { - uint32 total_size = size + sizeof(struct salloc_header); - char *c_ptr = (char *) base; - while (1) - { - uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); - uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr); - uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); - if (cur_blk_free == 0 || cur_blk_size < total_size) - { - //if cur block not a free block - //or the current block size is less than the size we want - if (cur_blk_last == 1) - { - //if last one, break and fail. - break; - } - else - { - c_ptr += cur_blk_size; - } - } - else - { - // we have a free block with enough size - if (total_size == cur_blk_size || - cur_blk_size - total_size < sizeof(struct salloc_header)) - { - // since the space left is not enough for salloc_header - // we alloc the whole block - set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0); - } - else - { - // we split the block here - // set properties for the first block - set_salloc_header_size((struct salloc_header *) c_ptr, total_size); - set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, 0); - set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0); - - // set properties for the second block - set_salloc_header_size((struct salloc_header *) (c_ptr + total_size), cur_blk_size - total_size); - set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_LAST, - cur_blk_last); - set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_FREE, 1); - } - // return the pointer, skip the alloc header - result = c_ptr + sizeof(struct salloc_header); - break; - } - } - } - return result; -} - - -void -lb_sfree(void *base, void *ptr) -{ - if (base != NULL && ptr != NULL) - { - char *c_ptr = (char *) base; - while (1) - { - uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); - uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); - uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr); - if (cur_blk_free == 0 && ptr == c_ptr + sizeof(struct salloc_header)) - { - // we found the block, mark it as free - set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 1); - // merge blocks - salloc_join(base); - break; - } - - if (cur_blk_last == 1) - { - break; - } - else - { - c_ptr += cur_blk_size; - } - } - } -} diff --git a/kernel/mm/Rules.mk b/kernel/mm/Rules.mk deleted file mode 100644 index e9cedb3..0000000 --- a/kernel/mm/Rules.mk +++ /dev/null @@ -1,7 +0,0 @@ -include $(MK)/prologue.mk - -SRC_$(d) := $(d)/pmm.c - -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/kernel/mm/pmm.c b/kernel/mm/pmm.c deleted file mode 100644 index 386e7f3..0000000 --- a/kernel/mm/pmm.c +++ /dev/null @@ -1,200 +0,0 @@ -#include "mm/pmm.h" - -#include "lb/atree.h" -#include "lb/llist.h" -#include "ke/rww_lock.h" -#include "clib.h" -#include "ke/intr.h" - -struct phys_page_desc -{ - struct llist_node free_list_node; - struct atree_node tree_node; - uintptr base; - int32 attr; -}; - -static struct atree active_tree; -static struct llist free_list; -static struct rww_lock lock; - -/* - * A comparison function between tree_node and your_node - * Returns: - * < 0 if tree_node < your_node - * = 0 if tree_node == your_node - * > 0 if tree_node > your_node - */ -//static int32 mmp_base_paddr_compare(struct atree_node *tree_node, struct atree_node *my_node) -//{ -// uintptr tree_base = OBTAIN_STRUCT_ADDR(tree_node, -// struct phys_page_desc, -// tree_node)->base; -// uintptr my_base = OBTAIN_STRUCT_ADDR(my_node, -// struct phys_page_desc, -// tree_node)->base; -// if (tree_base > my_base) -// { -// return 1; -// } -// else -// { -// if (tree_base < my_base) -// { -// return -1; -// } -// else -// { -// return 0; -// } -// } -//} - -k_status mm_pmm_init(struct boot_info *info) -{ - UNREFERENCED(info); -// if (info == NULL) -// { -// return MM_INVALID_ARGUMENTS; -// } -// -// if (initialized) -// { -// return STATUS_SUCCESS; -// } -// -// ke_rwwlock_init(&lock); -// lb_linked_list_init(&free_list); -// lb_avl_tree_init(&active_tree, mmp_base_paddr_compare); -// -// for (uint32 i = 0; i < info->num_of_nodes; i++) -// { -// pmm_node_t *each_node = &info->nodes[i]; -// -// KE_ASSERT (each_node->base % KERNEL_PAGE_SIZE != 0); -// -// for (uint64 j = 0; j <= each_node->size; j++) -// { -// // note that k_alloc function here might trigger page fault -// // however it's fine as long as we don't touch linked list just yet -// // it will use the pages that are already on file to enlarge the kernel heap -// // don't worry, be happy :) -// struct phys_page_desc *page_info = ke_alloc(sizeof(struct phys_page_desc)); -// -// if (page_info == NULL) -// { -// return MM_ALLOCATION_FAILED; -// } -// -// page_info->base = each_node->base; -// lb_linked_list_push_back(&free_list, &page_info->free_list_node); -// } -// } -// initialized = TRUE; - return STATUS_INVALID_ARGS; -} - -// free lists can only be updated at IRQL == DISABLED -// we need to guarantee that on the same CPU, these APIs are not preempted by -// potential callers of these, since timer/interrupts queue DPC, which might trigger -// page fault (kernel heap), therefore, it must set IRQL to DISABLED - -k_status mm_alloc_page(uintptr *out) -{ - uint32 irql; - k_status status; - - status = STATUS_SUCCESS; - - irql = ke_raise_irql(IRQL_HIGH); - ke_rww_w_lock(&lock); - - struct llist_node *node = NULL; - struct phys_page_desc *page_info = NULL; - node = lb_llist_pop_front(&free_list); - if (node != NULL) - { - page_info = OBTAIN_STRUCT_ADDR(node, - struct phys_page_desc, - free_list_node); - lb_atree_insert(&active_tree, &page_info->tree_node); - *out = page_info->base; - } - else - { - status = STATUS_NO_MEM; - } - - ke_rww_w_unlock(&lock); - ke_lower_irql(irql); - return status; -} - -k_status mm_query_page_attr(uintptr base, - int32 *out) -{ - uint32 irql; - k_status result; - struct atree_node *node; - struct phys_page_desc dummy; - struct phys_page_desc *page_info; - - result = STATUS_SUCCESS; - node = NULL; - page_info = NULL; - - dummy.base = base; - - irql = ke_raise_irql(IRQL_HIGH); - ke_rww_r_lock(&lock); - - node = lb_atree_search(&active_tree, &dummy.tree_node); - - ke_rww_r_unlock(&lock); - ke_lower_irql(irql); - - if (node != NULL) - { - page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node); - *out = page_info->attr; - } - else - { - result = STATUS_INVALID_ARGS; - } - - - return result; -} - -k_status mm_free_page(uintptr base) -{ - // just lock since not sharing with anyone - uint32 irql; - k_status result; - struct atree_node *node; - struct phys_page_desc dummy, *page_info; - - result = STATUS_SUCCESS; - dummy.base = base; - - irql = ke_raise_irql(IRQL_HIGH); - ke_rww_w_lock(&lock); - - node = lb_atree_delete(&active_tree, &dummy.tree_node); - - if (node != NULL) - { - page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node); - lb_llist_push_back(&free_list, &page_info->free_list_node); - } - else - { - result = STATUS_INVALID_ARGS; - } - - ke_rww_w_unlock(&lock); - ke_lower_irql(irql); - - return result; -} diff --git a/kernel/rf/Rules.mk b/kernel/rf/Rules.mk deleted file mode 100644 index 8462177..0000000 --- a/kernel/rf/Rules.mk +++ /dev/null @@ -1,7 +0,0 @@ -include $(MK)/prologue.mk - -SRC_$(d) := $(d)/ref.c - -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/kernel/rf/ref.c b/kernel/rf/ref.c deleted file mode 100644 index 38adc5d..0000000 --- a/kernel/rf/ref.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "rf/ref.h" -#include "ke/assert.h" -#include "ke/spin_lock.h" -#include "ke/atomic.h" -#include "ke/intr.h" -#include "clib.h" - -#define K_IDENT_BASE (0x80000000ul) - -static struct atree ident_tree; -static struct spin_lock ident_tree_lock; -static uint32 ident_base; - - -static int32 -handle_compare(struct atree_node *tree_node, struct atree_node *my_node) -{ - struct ident_node *tcb = OBTAIN_STRUCT_ADDR(tree_node, struct ident_node, tree_node); - struct ident_node *my_tcb = OBTAIN_STRUCT_ADDR(my_node, struct ident_node, tree_node); - - if ((uintptr) tcb->ident > (uintptr) my_tcb->ident) - { - return -1; - } - else - { - if ((uintptr) tcb->ident == (uintptr) my_tcb->ident) - { - return 0; - } - else - { - return 1; - } - } -} - - -static struct ident_node * -search_handle_node(k_ident ident) -{ - struct atree_node *result; - struct ident_node temp; - temp.ident = ident; - result = lb_atree_search(&ident_tree, &temp.tree_node); - return result == NULL ? NULL : OBTAIN_STRUCT_ADDR(result, struct ident_node, tree_node); -} - - -k_status -rf_ref_init(void) -{ - lb_atree_init(&ident_tree, handle_compare); - ke_spin_init(&ident_tree_lock); - ident_base = K_IDENT_BASE; - - return STATUS_SUCCESS; -} - - -k_status -rf_ref_node_init(struct ref_node *rf_node, ref_free_fp free_func) -{ - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - rf_node->f_free = free_func; - rf_node->ref_count = 1; - - return STATUS_SUCCESS; -} - - -k_status -rf_ref_obj(struct ref_node *ref_node) -{ - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - if (ref_node == NULL) - { - return STATUS_INVALID_ARGS; - } - - int32 old_ref_count = ke_atomic_inc_32(&ref_node->ref_count, 1); - - KE_ASSERT(old_ref_count >= 1); - - return STATUS_SUCCESS; -} - - -k_status -rf_deref_obj(struct ref_node *rf_node) -{ - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - if (rf_node == NULL) - { - return STATUS_INVALID_ARGS; - } - - k_status result = STATUS_SUCCESS; - - int32 old_ref_count = ke_atomic_inc_32(&rf_node->ref_count, -1); - - KE_ASSERT(old_ref_count >= 1); - - if (old_ref_count == 1) - { - rf_node->f_free(rf_node); - } - - return result; -} - - -k_status -rf_open_obj_by_ident(k_ident id, struct ref_node **out) -{ - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - uint32 irql; - k_status status = STATUS_SUCCESS; - struct ref_node *ref = NULL; - - irql = ke_raise_irql(IRQL_DPC); - ke_spin_lock(&ident_tree_lock); - struct ident_node *ident_node = search_handle_node(id); - if (ident_node == NULL) - { - status = STATUS_INVALID_ARGS; - } - else - { - ref = ident_node->obj; - } - - // PREREQUISITE: Having a handle -> having a reference - // MUST GUARANTEE that handle exists while we reference - if (SX_SUCCESS(status)) - { - // reference the object then return the reference - rf_ref_obj(ref); - *out = ref; - } - - ke_spin_unlock(&ident_tree_lock); - ke_lower_irql(irql); - - return status; -} - - -k_status -rf_ident_create(struct ref_node *rf_node, struct ident_node *id_node, k_ident *out) -{ - k_status result; - uint32 irql; - - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - result = STATUS_SUCCESS; - - // TODO: CHECK OVERFLOW - id_node->ident = (k_ident) ke_atomic_inc_32((int32 *) &ident_base, 1); - id_node->obj = rf_node; - - irql = ke_raise_irql(IRQL_DPC); - ke_spin_lock(&ident_tree_lock); - - struct ident_node *existing_node = search_handle_node(id_node->ident); - if (existing_node == NULL) - { - lb_atree_insert(&ident_tree, &id_node->tree_node); - } - else - { - /** - * Shouldn't get to here - */ - result = STATUS_DUPLICATE; - } - - ke_spin_unlock(&ident_tree_lock); - ke_lower_irql(irql); - - - if (SX_SUCCESS(result)) - { - rf_ref_obj(rf_node); - *out = id_node->ident; - } - - return result; -} - - -k_status -rf_ident_close(k_ident id) -{ - uint32 irql; - k_status status; - struct ref_node *ref; - - KE_ASSERT(ke_get_irql() <= IRQL_DPC); - - status = STATUS_SUCCESS; - ref = NULL; - - irql = ke_raise_irql(IRQL_DPC); - ke_spin_lock(&ident_tree_lock); - - struct ident_node *id_node = search_handle_node(id); - if (id_node == NULL) - { - status = STATUS_INVALID_ARGS; - } - else - { - ref = id_node->obj; - lb_atree_delete(&ident_tree, &id_node->tree_node); - } - - ke_spin_unlock(&ident_tree_lock); - ke_lower_irql(irql); - - if (SX_SUCCESS(status)) - { - /** - * Success means already freed - */ - id_node->free_routine(id_node); - /** - * Dereference the object - */ - rf_deref_obj(ref); - } - - return status; -} diff --git a/makfile b/makfile deleted file mode 100644 index 22579be..0000000 --- a/makfile +++ /dev/null @@ -1,87 +0,0 @@ - -AS := nasm -CC := clang -LD := lld -DAS := objdump - -ifneq '$(AS_ENV)' '' -AS := $(AS_ENV) -endif -$(info Using AS=$(AS)) - -ifneq '$(CC_ENV)' '' -CC := $(CC_ENV) -endif -$(info Using CC=$(CC)) - -ifneq '$(LD_ENV)' '' -LD := $(LD_ENV) -endif -$(info Using LD=$(LD)) - -ifneq '$(DAS_ENV)' '' -DAS := $(DAS_ENV) -endif -$(info Using DAS=$(DAS)) - -INC_COMMON := inc -MK := mk -OUT := out - -C_FLAGS_ARCH_X86_64 := -mcmodel=kernel \ - -target x86_64-pc-none-elf \ - -mno-red-zone \ - -mno-mmx \ - -mno-sse \ - -mno-sse2 \ - -mno-sse3 \ - -mno-3dnow - -# generic freestanding cflags used for target -# each submodule can append to this flag -C_FLAGS = -x c \ - -g \ - -c \ - -O2 \ - -std=c17 \ - -Wall \ - -Wextra \ - -Wpedantic \ - -Werror \ - -ffreestanding \ - -fno-pic \ - -fno-stack-protector \ - $(C_FLAGS_ARCH_X86_64) \ - -I$(INC_COMMON) \ - $(C_FLAGS_$(MOD)) - -# generic asm flags used for target -# each submodule can append to this flag -AS_FLAGS = -w+all \ - -w+error \ - -f elf64 \ - -F dwarf \ - -g \ - -I$(INC_COMMON) \ - $(AS_FLAGS_$(MOD)) - -# generic pre-processing flags used for target -PREP_FLAGS = -E \ - -xc\ - -P \ - -I$(INC_COMMON) \ - $(C_FLAGS_$(MOD)) - -# generic generate dependency flags used for target -# each submodule can append to this flag -GDEP_FLAGS = $(PREP_FLAGS) \ - -MMD \ - -MT $@ - -MKDIR = mkdir -p $(dir $@) -COMP = $(CC) $(C_FLAGS) -o $@ $< -COMPAS = $(AS) $(AS_FLAGS) -o $@ $< -PREP = $(CC) $(PREP_FLAGS) $< > $@ -GDEP = $(CC) $(GDEP_FLAGS) -MF $(addsuffix .d, $@) $< > /dev/null - -include Rules.top diff --git a/mk/Rules.mk b/mk/Rules.mk deleted file mode 100644 index d274a91..0000000 --- a/mk/Rules.mk +++ /dev/null @@ -1,9 +0,0 @@ -include $(MK)/prologue.mk - -MOD:=MK - -SRCIN_$(d) := $(d)/linker.ld.in - -include $(MK)/stdrules.mk - -include $(MK)/epilogue.mk \ No newline at end of file diff --git a/mk/amd64.cmake b/mk/amd64.cmake new file mode 100644 index 0000000..df17874 --- /dev/null +++ b/mk/amd64.cmake @@ -0,0 +1,29 @@ +# toolchain file for amd64 target +find_program(AS nasm) +find_program(CC clang) +find_program(LD ld.lld) +find_program(DMP objdump) +find_program(GRUB grub2-mkrescue) + + +set(CC_FLAGS_${ARCH} + --target=x86_64-unknown-none-elf + -mcmodel=kernel + -mno-red-zone + -mno-mmx + -mno-sse + -mno-sse2 + -mno-sse3 + -mno-3dnow) + +set(AS_FLAGS_${ARCH} + -w+all + -w+error + -Fdwarf + -g + -felf64) + +set(DMP_FLAGS_${ARCH} + -M intel + -d + -t) diff --git a/mk/common.cmake b/mk/common.cmake new file mode 100644 index 0000000..5cfe4d9 --- /dev/null +++ b/mk/common.cmake @@ -0,0 +1,41 @@ + +# preprocess files, add all target object files to ${target} variable +function(PP_GEN file target) + # Note that file should be full path + get_filename_component(base ${file} NAME) + set(output ${CMAKE_CURRENT_BINARY_DIR}/${base}) + add_custom_command( + OUTPUT ${output} + DEPENDS ${file} + COMMAND ${CC} ${PP_FLAGS} -o ${output} ${file} + IMPLICIT_DEPENDS C ${file} + ) + set(${target} ${${target}} ${output} PARENT_SCOPE) +endfunction() + +# cc file compile, add all target object files to ${target} variable +function(CC_GEN file target) + # Note that file should be full path + get_filename_component(base ${file} NAME) + set(output ${CMAKE_CURRENT_BINARY_DIR}/${base}.o) + add_custom_command( + OUTPUT ${output} + DEPENDS ${file} + COMMAND ${CC} ${CC_FLAGS} -o ${output} ${file} + IMPLICIT_DEPENDS C ${file} + ) + set(${target} ${${target}} ${output} PARENT_SCOPE) +endfunction() + +# asm file compile, add all target object files to ${target} variable +function(AS_GEN file target) + # Note that file should be full path + get_filename_component(base ${file} NAME) + set(output ${CMAKE_CURRENT_BINARY_DIR}/${base}.o) + add_custom_command( + OUTPUT ${output} + DEPENDS ${file} + COMMAND ${AS} ${AS_FLAGS} -o ${output} ${file} + ) + set(${target} ${${target}} ${output} PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/mk/epilogue.mk b/mk/epilogue.mk deleted file mode 100644 index 75fe942..0000000 --- a/mk/epilogue.mk +++ /dev/null @@ -1,2 +0,0 @@ -d := $(dirstack_$(sp)) -sp := $(basename $(sp)) \ No newline at end of file diff --git a/mk/grub.cfg b/mk/grub.cfg deleted file mode 100644 index b27672b..0000000 --- a/mk/grub.cfg +++ /dev/null @@ -1,6 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "secX" { - multiboot2 /secX/secxkrnl.elf -} \ No newline at end of file diff --git a/mk/kern.cmake b/mk/kern.cmake new file mode 100644 index 0000000..0943e96 --- /dev/null +++ b/mk/kern.cmake @@ -0,0 +1,41 @@ +include(${MK}/common.cmake) + +# +# Standard rules for kernel +# +# Process AS_SRC and CC_SRC and add them to "OBJS" +# + +FOREACH(f IN LISTS AS_SRC) + PP_GEN(${CMAKE_CURRENT_SOURCE_DIR}/${f} AS_TMPSRC) +endforeach(f) + +FOREACH(f IN LISTS AS_TMPSRC) + AS_GEN(${f} M_OBJS) +endforeach(f) + +FOREACH(f IN LISTS CC_SRC) + CC_GEN(${CMAKE_CURRENT_SOURCE_DIR}/${f} M_OBJS) +endforeach(f) + +set(SUBTARGET ${CMAKE_CURRENT_BINARY_DIR}/${SUBMODULE}.o) +# Rules for generating the target +add_custom_command( + OUTPUT ${SUBTARGET} + DEPENDS ${M_OBJS} + COMMAND ${CC} ${LD_FLAGS} -r -o ${SUBTARGET} ${M_OBJS}) + +add_custom_target(${SUBMODULE} + DEPENDS ${SUBTARGET}) + +set(OBJS_${SUBMODULE} ${SUBTARGET} PARENT_SCOPE) +set(TARGET_${SUBMODULE} ${SUBMODULE} PARENT_SCOPE) + +# hack for clion not parsing custom targets +set(CUR_CC_SRC "") + +FOREACH(f IN LISTS CC_SRC) + set(CUR_CC_SRC ${CUR_CC_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/${f}) +endforeach(f) + +set(G_CC_SRC ${G_CC_SRC} ${CUR_CC_SRC} PARENT_SCOPE) \ No newline at end of file diff --git a/mk/linker.ld.in b/mk/linker.ld.in deleted file mode 100644 index dc2a92a..0000000 --- a/mk/linker.ld.in +++ /dev/null @@ -1,31 +0,0 @@ -#define ASM_FILE -#include "mlayout.h" - -ENTRY(sys_entry) - -SECTIONS -{ - . = KERNEL_IMAGE_VADDR + KERNEL_IMAGE_OFFSET; - - .multiboot_header ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.multiboot_header) - KERNEL_IMAGE_VADDR) - { - *(.multiboot_header) - } - - .text ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.text) - KERNEL_IMAGE_VADDR) - { - *(.text) - } - - .data ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.data) - KERNEL_IMAGE_VADDR) - { - *(.data) - *(.rodata*) - } - - .bss ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.bss) - KERNEL_IMAGE_VADDR) - { - *(.bss) - *(COMMON) - } -} diff --git a/mk/prologue.mk b/mk/prologue.mk deleted file mode 100644 index 00aff87..0000000 --- a/mk/prologue.mk +++ /dev/null @@ -1,4 +0,0 @@ -# Standard things -sp := $(sp).x -dirstack_$(sp) := $(d) -d := $(dir) diff --git a/mk/stdrules.mk b/mk/stdrules.mk deleted file mode 100644 index f9968a1..0000000 --- a/mk/stdrules.mk +++ /dev/null @@ -1,35 +0,0 @@ -# The source rules.mk defines: -# SRC_$(d) for all c source files -# SRCAS_$(d) for all asm source files -# SRCIN_$(d) for all in(preprocessor) source files -# Compiles all c and in source files and generate dependencies -# Adds c and asm object files to $OBJ variable -# Adds all generated files to $CLEAN variable - -OBJ_$(d) := $(OBJ_$(d)) $(addprefix $(OUT)/, $(SRC_$(d):.c=.o)) -OBJAS_$(d) := $(OBJAS_$(d)) $(addprefix $(OUT)/, $(SRCAS_$(d):.asm=.a)) -OBJIN_$(d) := $(OBJIN_$(d)) $(addprefix $(OUT)/, $(SRCIN_$(d):.in=)) -DEP_$(d) := $(DEP_$(d)) $(addsuffix .d, $(OBJ_$(d)) $(OBJIN_$(d))) - -$(OUT)/$(d)/%.o: MOD:=$(MOD) - -$(OBJ_$(d)): $(OUT)/$(d)/%.o: $(d)/%.c - $(MKDIR) - $(COMP) - $(GDEP) - -$(OUT)/$(d)/%.a: MOD:=$(MOD) - -$(OBJAS_$(d)): $(OUT)/$(d)/%.a: $(d)/%.asm - $(MKDIR) - $(COMPAS) - -$(OBJIN_$(d)): $(OUT)/$(d)/%: $(d)/%.in - $(MKDIR) - $(PREP) - $(GDEP) - -# append all OBJECTS to OBJ -OBJ := $(OBJ) $(OBJ_$(d)) $(OBJAS_$(d)) - --include $(DEP_$(d)) diff --git a/qemu_bios.bin b/qemu_bios.bin deleted file mode 100644 index 455e121..0000000 Binary files a/qemu_bios.bin and /dev/null differ diff --git a/runq.sh b/runq.sh deleted file mode 100644 index 003a80a..0000000 --- a/runq.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -qemu-system-x86_64 -bios qemu_bios.bin -vnc :10 -monitor stdio -cdrom out/secxkrnl.iso -s -S -no-reboot - - diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt new file mode 100644 index 0000000..10b8820 --- /dev/null +++ b/scripts/CMakeLists.txt @@ -0,0 +1,20 @@ +set(SUBMODULE scripts) + +set(GRUB_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/grub.cfg) + +set(LD_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/linker.lds) + +include (${MK}/common.cmake) + +PP_GEN(${GRUB_SRC} GRUB_CFG) +PP_GEN(${LD_SRC} LD_LDS) + +add_custom_target(${SUBMODULE} + DEPENDS ${GRUB_CFG} + DEPENDS ${LD_LDS}) + +set(TARGET_${SUBMODULE} ${SUBMODULE} PARENT_SCOPE) +set(SCRIPT_LD ${LD_LDS} PARENT_SCOPE) +set(SCRIPT_GRUB ${GRUB_CFG} PARENT_SCOPE) \ No newline at end of file diff --git a/scripts/grub.cfg b/scripts/grub.cfg new file mode 100644 index 0000000..a2f771c --- /dev/null +++ b/scripts/grub.cfg @@ -0,0 +1,6 @@ +set timeout=0 +set default=0 + +menuentry "bond" { + multiboot2 bond.elf +} \ No newline at end of file diff --git a/scripts/linker.lds b/scripts/linker.lds new file mode 100644 index 0000000..dddce90 --- /dev/null +++ b/scripts/linker.lds @@ -0,0 +1,14 @@ +#define ASM_FILE +#include <arch/mlayout.h> + +ENTRY(arch_init_32) + +SECTIONS +{ + . = KERNEL_IMG_VADDR + KERNEL_IMG_PADDR; + + .multiboot_header ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.multiboot_header) - KERNEL_IMG_VADDR) + { + *(.multiboot_header) + } +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..0d7651f --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,10 @@ +set(SUBMODULE test) +set(CC_SRC + avl_test.c + list_test.c + ktest.c + qsort_test.c + ) + +include(${MK}/kern.cmake) + diff --git a/test/atree_test.c b/test/atree_test.c deleted file mode 100644 index 48d61df..0000000 --- a/test/atree_test.c +++ /dev/null @@ -1,1002 +0,0 @@ -#include "test_main.h" -#include "test_case.h" -#include "lb/atree.h" -#include "clib.h" -#include <stdio.h> - -struct test_node -{ - struct atree_node tree_entry; - int32 val; -} test_node; - -static struct test_node * -create_test_node(int val) -{ - struct test_node *rs = talloc(sizeof(struct test_node)); - rs->val = val; - return rs; -} - -static int32 -test_node_compare(struct atree_node *root, struct atree_node *node) -{ - struct test_node *tree_node = OBTAIN_STRUCT_ADDR(root, struct test_node, tree_entry); - struct test_node *self = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); - return tree_node->val - self->val; -} - -static void -_pre_order_print(struct atree_node *node) -{ - if (node == NULL) - { - return; - } - struct test_node *t_node = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); - printf("%d-", t_node->val); - _pre_order_print(node->left); - _pre_order_print(node->right); -} - -static void -pre_order(struct atree_node *node) -{ -#ifdef TDBG - _pre_order_print(node); -#endif -} - -static bool -_pre_order_assert(struct atree_node *node, int order[], int size, int *counter) -{ - if (node == NULL) - { - return TRUE; - } - if (*counter >= size) - { - return FALSE; - } - - bool result = TRUE; - struct test_node *t_node = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); - if (order[*counter] != t_node->val) - { - result = FALSE; - } - (*counter)++; - result = result && _pre_order_assert(node->left, order, size, counter); - result = result && _pre_order_assert(node->right, order, size, counter); - return result; -} - -static bool -pre_order_assert(struct atree *tree, int order[], int size) -{ - bool ret; - int counter = 0; - - ret = _pre_order_assert(tree->root, order, size, &counter); -#ifdef TDBG - if (!ret) - { - printf("[AVL ASSERT] Expected: "); - for (int i = 0; i < size; i++) - { - printf("%d-", order[i]); - } - printf("\n Got:"); - pre_order(tree->root); - printf("\n"); - fflush(stdout); - } -#endif - return ret; -} - -/** - * Tests - */ - -static bool -insert_simple_l(void) -{ - //1 2 - // \ / \ - // 2 == 1L ==> 1 3 - // \ - // 3 - - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(1)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - int val1[] = {1, 2}; - result = result && pre_order_assert(&tree, val1, 2); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - int val2[] = {2, 1, 3}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -insert_simple_r(void) -{ - // 3 2 - // / / \ - // 2 == 1R ==> 1 3 - // / - //1 - - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - int val1[] = {3, 2}; - result = result && pre_order_assert(&tree, val1, 2); - - lb_atree_insert(&tree, &create_test_node(1)->tree_entry); - - int val2[] = {2, 1, 3}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -insert_simple_ll(void) -{ - //2 3 - // \ / \ - // 4 == 2L ==> 2 4 - // / - //3 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - int val1[] = {2, 4}; - result = result && pre_order_assert(&tree, val1, 2); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - - int val2[] = {3, 2, 4}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -insert_simple_rr(void) -{ - // 4 3 - // / / \ - //2 == 2R ==> 2 4 - // \ - // 3 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - int val1[] = {4, 2}; - result = result && pre_order_assert(&tree, val1, 2); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - - int val2[] = {3, 2, 4}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -insert_complex_1(void) -{ - // 20+ 20++ 20++ 9 - // / \ / \ / \ / \ - // 4 26 => 4- 26 => 9+ 26 => 4+ 20 - // / \ / \ / \ / / \ - //3 9 3 9- 4+ 15 3 15 26 - // \ / - // 15 3 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(26)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(9)->tree_entry); - int val1[] = {20, 4, 3, 9, 26}; - result = result && pre_order_assert(&tree, val1, 5); - - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - - int val2[] = {9, 4, 3, 20, 15, 26}; - result = result && pre_order_assert(&tree, val2, 6); - return result && lb_atree_validate(&tree); -} - -static bool -insert_complex_2(void) -{ - // 20+ 20++ 20++ 9 - // / \ / \ / \ / \ - // 4 26 => 4- 26 => 9++ 26 => 4 20- - // / \ / \ / / \ \ - //3 9 3 9+ 4 3 8 26 - // / / \ - // 8 3 8 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(26)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(9)->tree_entry); - int val1[] = {20, 4, 3, 9, 26}; - result = result && pre_order_assert(&tree, val1, 5); - - lb_atree_insert(&tree, &create_test_node(8)->tree_entry); - - int val2[] = {9, 4, 3, 8, 20, 26}; - result = result && pre_order_assert(&tree, val2, 6); - return result && lb_atree_validate(&tree); -} - -static bool -insert_complex_3(void) -{ - // __20+__ _20++_ __20++_ ___9___ - // / \ / \ / \ / \ - // 4 26 => 4- 26 => 9+ 26 => 4+ __20__ - // / \ / \ / \ / \ / \ / \ / \ / \ - // 3+ 9 21 30 3+ 9- 21 30 4+ 11- 21 30 3+ 7 11- 26 - // / / \ / / \ / \ \ / \ / \ - //2 7 11 2 7 11- 3+ 7 15 2 15 21 30 - // \ / - // 15 2 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(26)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(9)->tree_entry); - lb_atree_insert(&tree, &create_test_node(21)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &create_test_node(7)->tree_entry); - lb_atree_insert(&tree, &create_test_node(11)->tree_entry); - int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; - result = result && pre_order_assert(&tree, val1, 10); - - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - - int val2[] = {9, 4, 3, 2, 7, 20, 11, 15, 26, 21, 30}; - result = result && pre_order_assert(&tree, val2, 11); - return result && lb_atree_validate(&tree); -} - -static bool -insert_complex_4(void) -{ - // __20+__ _20++_ __20++_ ___9___ - // / \ / \ / \ / \ - // 4 26 4- 26 9+ 26 4 _20- - // / \ / \ / \ / \ / \ / \ / \ / \ - // 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26 - // / / \ / / \ / \ / \ / \ - //2 7 11 2 7- 11 3+ 7- 2 8 21 30 - // \ / \ - // 8 2 8 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(26)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(9)->tree_entry); - lb_atree_insert(&tree, &create_test_node(21)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &create_test_node(7)->tree_entry); - lb_atree_insert(&tree, &create_test_node(11)->tree_entry); - int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; - result = result && pre_order_assert(&tree, val1, 10); - - lb_atree_insert(&tree, &create_test_node(8)->tree_entry); - - int val2[] = {9, 4, 3, 2, 7, 8, 20, 11, 26, 21, 30}; - result = result && pre_order_assert(&tree, val2, 11); - return result && lb_atree_validate(&tree); -} - -static bool -insert_duplicate(void) -{ - // __20+__ _20++_ __20++_ ___9___ - // / \ / \ / \ / \ - // 4 26 4- 26 9+ 26 4 _20- - // / \ / \ / \ / \ / \ / \ / \ / \ - // 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26 - // / / \ / / \ / \ / \ / \ - //2 7 11 2 7- 11 3+ 7- 2 8 21 30 - // \ / \ - // 8 2 8 - bool result = TRUE; - struct atree tree; - struct test_node *temp, *temp20, *temp30, *temp7, *temp2; - lb_atree_init(&tree, test_node_compare); - - temp20 = create_test_node(20); - temp30 = create_test_node(30); - temp7 = create_test_node(7); - temp2 = create_test_node(2); - - lb_atree_insert(&tree, &temp20->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &create_test_node(26)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(9)->tree_entry); - lb_atree_insert(&tree, &create_test_node(21)->tree_entry); - lb_atree_insert(&tree, &temp30->tree_entry); - lb_atree_insert(&tree, &temp2->tree_entry); - lb_atree_insert(&tree, &temp7->tree_entry); - lb_atree_insert(&tree, &create_test_node(11)->tree_entry); - int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; - result = result && pre_order_assert(&tree, val1, 10); - - // should return the value being overwritten - temp = OBTAIN_STRUCT_ADDR(lb_atree_insert(&tree, &create_test_node(20)->tree_entry), struct test_node, tree_entry); - result = result && (temp == temp20); - temp = OBTAIN_STRUCT_ADDR(lb_atree_insert(&tree, &create_test_node(30)->tree_entry), struct test_node, tree_entry); - result = result && (temp == temp30); - temp = OBTAIN_STRUCT_ADDR(lb_atree_insert(&tree, &create_test_node(7)->tree_entry), struct test_node, tree_entry); - result = result && (temp == temp7); - temp = OBTAIN_STRUCT_ADDR(lb_atree_insert(&tree, &create_test_node(2)->tree_entry), struct test_node, tree_entry); - result = result && (temp == temp2); - - result = result && pre_order_assert(&tree, val1, 10); - return result && lb_atree_validate(&tree); -} - - -static bool -delete_simple_l(void) -{ - // 2 3 - // x \ / \ - //1 3 == 1L ==> 2 4 - // \ - // 4 - - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(1); - - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - int val1[] = {2, 1, 3, 4}; - result = result && pre_order_assert(&tree, val1, 4); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {3, 2, 4}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -delete_simple_r(void) -{ - // 3 2 - // / x / \ - // 2 4 == 1R ==> 1 3 - // / - //1 - - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(4); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(1)->tree_entry); - int val1[] = {3, 2, 1, 4}; - result = result && pre_order_assert(&tree, val1, 4); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {2, 1, 3}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -delete_simple_ll(void) -{ - // 2 3 - // x \ / \ - //1 4 == 2L ==> 2 4 - // / - // 3 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(1); - - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &create_test_node(4)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - int val1[] = {2, 1, 4, 3}; - result = result && pre_order_assert(&tree, val1, 4); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {3, 2, 4}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -delete_simple_rr(void) -{ - // 3 2 - // / x / \ - //2 4 == 2R ==> 1 3 - // \ - // 1 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(4); - - lb_atree_insert(&tree, &create_test_node(3)->tree_entry); - lb_atree_insert(&tree, &create_test_node(2)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(1)->tree_entry); - int val1[] = {3, 2, 1, 4}; - result = result && pre_order_assert(&tree, val1, 4); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {2, 1, 3}; - result = result && pre_order_assert(&tree, val2, 3); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_1(void) -{ - // Test Case #1 - // - A single node tree has its only node removed. - // Create: - // 10 - // - // Call: remove(10) - // - // Result: - // empty tree - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(10); - - lb_atree_insert(&tree, &deleted->tree_entry); - int val1[] = {10}; - result = result && pre_order_assert(&tree, val1, 1); - - lb_atree_delete(&tree, &deleted->tree_entry); - - result = result && pre_order_assert(&tree, val1, 0); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_2(void) -{ - // Test Case #2 - // - A small tree has its root removed. - // Create: - // 20 - // / \ - // 10 30 - // / \ - // 25 35 - // - // Call: remove(20) - // - // Results: (simplest result with no rotations) - // (replace root with smallest value on the treenode or 25) - // - // 25 - // / \ - // 10 30 - // \ - // 35 - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(20); - - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(10)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - lb_atree_insert(&tree, &create_test_node(35)->tree_entry); - int val1[] = {20, 10, 30, 25, 35}; - result = result && pre_order_assert(&tree, val1, 5); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {25, 10, 30, 35}; - result = result && pre_order_assert(&tree, val2, 4); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_3(void) -{ - // Test Case #3 - // - A small tree has a node with 2 children removed - // 20 - // / \ - // 10 30 - // / \ / - // 5 15 25 - // - // Call: remove(10) - // - // Results: - // 20 - // / \ - // 15 30 - // / / - // 5 25 - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(10); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(5)->tree_entry); - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - int val1[] = {20, 10, 5, 15, 30, 25}; - result = result && pre_order_assert(&tree, val1, 6); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {20, 15, 5, 30, 25}; - result = result && pre_order_assert(&tree, val2, 5); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_4(void) -{ - // Test Case #4 - // - A small tree has all nodes but the root removed from the bottom up. - // Create: - // 20 - // / \ - // 10 30 - // / \ / - // 5 15 25 - // - // Call: remove(5), remove(15), remove(25), remove(10), remove(30) - // - // - // Results: - // 20 - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *delete5 = create_test_node(5); - struct test_node *delete10 = create_test_node(10); - struct test_node *delete15 = create_test_node(15); - struct test_node *delete25 = create_test_node(25); - struct test_node *delete30 = create_test_node(30); - - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &delete10->tree_entry); - lb_atree_insert(&tree, &delete30->tree_entry); - lb_atree_insert(&tree, &delete5->tree_entry); - lb_atree_insert(&tree, &delete15->tree_entry); - lb_atree_insert(&tree, &delete25->tree_entry); - - int val1[] = {20, 10, 5, 15, 30, 25}; - result = result && pre_order_assert(&tree, val1, 6); - - lb_atree_delete(&tree, &delete5->tree_entry); - lb_atree_delete(&tree, &delete15->tree_entry); - lb_atree_delete(&tree, &delete25->tree_entry); - lb_atree_delete(&tree, &delete10->tree_entry); - lb_atree_delete(&tree, &delete30->tree_entry); - - int val2[] = {20}; - result = result && pre_order_assert(&tree, val2, 1); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_single_rotation(void) -{ - // Test case single rotation - // - // Create: - // - // 20 - // / \ - // 10 30 - // / \ / \ - // 5 15 25 40 - // / / / \ - // 12 22 35 50 - // / - // 31 - // - // Call: remove(50) - // - // 20 - // / \ - // 10 30 - // / \ / \ - // 5 15 25 35 - // / / / \ - // 12 22 31 40 - // - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(50); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(10)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(5)->tree_entry); - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - lb_atree_insert(&tree, &create_test_node(40)->tree_entry); - lb_atree_insert(&tree, &create_test_node(12)->tree_entry); - lb_atree_insert(&tree, &create_test_node(22)->tree_entry); - lb_atree_insert(&tree, &create_test_node(35)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(31)->tree_entry); - int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; - result = result && pre_order_assert(&tree, val1, 12); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {20, 10, 5, 15, 12, 30, 25, 22, 35, 31, 40}; - result = result && pre_order_assert(&tree, val2, 11); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_double_rotation(void) -{ -// Test case double rotation - // - // Create: - // - // 20 - // / \ - // 10 30 - // / \ / \ - // 5 15 25 40 - // / / / \ - // 12 22 35 50 - // / - // 31 - // - // Call: remove(22) - // - // 20 - // / \ - // 10 35 - // / \ / \ - // 5 15 30 40 - // / / \ \ - // 12 25 31 50 - // - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(22); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(10)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(5)->tree_entry); - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - lb_atree_insert(&tree, &create_test_node(40)->tree_entry); - lb_atree_insert(&tree, &create_test_node(12)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(35)->tree_entry); - lb_atree_insert(&tree, &create_test_node(50)->tree_entry); - lb_atree_insert(&tree, &create_test_node(31)->tree_entry); - int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; - result = result && pre_order_assert(&tree, val1, 12); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {20, 10, 5, 15, 12, 35, 30, 25, 31, 40, 50}; - result = result && pre_order_assert(&tree, val2, 11); - return result && lb_atree_validate(&tree); -} - -static bool -delete_complex_multiple_rotation(void) -{ - // Test case multiple rotation - // - // Create: - // 20 - // / \ - // 10 30 - // / \ / \ - // 5 15 25 40 - // / / / \ - // 12 22 35 50 - // / - // 31 - // - // Call: remove(5) - // - // Results: - // 30 - // / \ - // 20 40 - // / \ / \ - // 12 25 35 50 - // / \ / / - // 10 15 22 31 - // - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *deleted = create_test_node(5); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(10)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &deleted->tree_entry); - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - lb_atree_insert(&tree, &create_test_node(40)->tree_entry); - lb_atree_insert(&tree, &create_test_node(12)->tree_entry); - lb_atree_insert(&tree, &create_test_node(22)->tree_entry); - lb_atree_insert(&tree, &create_test_node(35)->tree_entry); - lb_atree_insert(&tree, &create_test_node(50)->tree_entry); - lb_atree_insert(&tree, &create_test_node(31)->tree_entry); - int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; - result = result && pre_order_assert(&tree, val1, 12); - - lb_atree_delete(&tree, &deleted->tree_entry); - - int val2[] = {30, 20, 12, 10, 15, 25, 22, 40, 35, 31, 50}; - result = result && pre_order_assert(&tree, val2, 11); - return result && lb_atree_validate(&tree); -} - -static bool -delete_DNE(void) -{ - // Test case DNE - // Delete a node that does not exist - // 20 - // / \ - // 10 30 - // / \ / - // 5 15 25 - // - // Call: remove(100), remove(24) - // - // - // Results: - // 20 - // / \ - // 10 30 - // / \ / - // 5 15 25 - // - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - struct test_node *delete100 = create_test_node(100); - struct test_node *delete24 = create_test_node(24); - - lb_atree_insert(&tree, &create_test_node(20)->tree_entry); - lb_atree_insert(&tree, &create_test_node(10)->tree_entry); - lb_atree_insert(&tree, &create_test_node(30)->tree_entry); - lb_atree_insert(&tree, &create_test_node(5)->tree_entry); - lb_atree_insert(&tree, &create_test_node(15)->tree_entry); - lb_atree_insert(&tree, &create_test_node(25)->tree_entry); - - int val1[] = {20, 10, 5, 15, 30, 25}; - result = result && pre_order_assert(&tree, val1, 6); - - lb_atree_delete(&tree, &delete24->tree_entry); - lb_atree_delete(&tree, &delete100->tree_entry); - result = result && pre_order_assert(&tree, val1, 6); - return result && lb_atree_validate(&tree); -} - -#define AVL_APOCALYPSE_NUM 1000 -#define AVL_APOCALYPSE_IT 5 -static struct test_node apocalypse[AVL_APOCALYPSE_NUM]; - -static bool -test_apocalypse(void) -{ - bool result = TRUE; - struct atree tree; - lb_atree_init(&tree, test_node_compare); - - // insert test - for (int i = 0; i < AVL_APOCALYPSE_NUM; i++) - { - apocalypse[i].val = (int32) lb_rand(); - while (lb_atree_search(&tree, &apocalypse[i].tree_entry) != NULL) - { - apocalypse[i].val += (int32) lb_rand() % 32765; - } - lb_atree_insert(&tree, &apocalypse[i].tree_entry); - } - - // integrity test - result = result && lb_atree_validate(&tree); - result = result && lb_atree_size(&tree) == AVL_APOCALYPSE_NUM; - - // smaller and bigger test - struct atree_node *entry = lb_atree_min(&tree); - uint32 size = 0; - int32 prev = -1; - int32 cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; - while (entry != NULL) - { - if (cur < prev) - { - result = FALSE; - break; - } - size++; - entry = lb_atree_next(&tree, entry); - prev = cur; - if (entry != NULL) - { - cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; - } - } - - result = result && size == AVL_APOCALYPSE_NUM; - - // larger test - entry = lb_atree_max(&tree); - size = 0; - cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; - prev = cur; - while (entry != NULL) - { - if (cur > prev) - { - result = FALSE; - break; - } - size++; - entry = lb_atree_prev(&tree, entry); - prev = cur; - if (entry != NULL) - { - cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; - } - } - - result = result && size == AVL_APOCALYPSE_NUM; - - - // delete and search test - for (int i = 0; i < AVL_APOCALYPSE_NUM; i++) - { - result = result && (lb_atree_search(&tree, &apocalypse[i].tree_entry) != NULL); - lb_atree_delete(&tree, &apocalypse[i].tree_entry); - result = result && (lb_atree_search(&tree, &apocalypse[i].tree_entry) == NULL); - result = result && lb_atree_validate(&tree); - } - - result = result && (lb_atree_size(&tree) == 0); - return result; -} - - -void -avl_tree_test(void) -{ - test_begin("AVL tree test"); - - // simple tests - run_case("insert_simple_l", insert_simple_l()); - run_case("insert_simple_r", insert_simple_r()); - run_case("insert_simple_ll", insert_simple_ll()); - run_case("insert_simple_rr", insert_simple_rr()); - - // complex ones - run_case("insert_complex_1", insert_complex_1()); - run_case("insert_complex_2", insert_complex_2()); - run_case("insert_complex_3", insert_complex_3()); - run_case("insert_complex_4", insert_complex_4()); - - // insert duplicate - run_case("insert_duplicate", insert_duplicate()); - - // simple tests - run_case("delete_simple_l", delete_simple_l()); - run_case("delete_simple_r", delete_simple_r()); - run_case("delete_simple_ll", delete_simple_ll()); - run_case("delete_simple_rr", delete_simple_rr()); - - // complex tests - run_case("delete_complex_1", delete_complex_1()); - run_case("delete_complex_2", delete_complex_2()); - run_case("delete_complex_3", delete_complex_3()); - run_case("delete_complex_4", delete_complex_4()); - run_case("delete_complex_single_rotation", delete_complex_single_rotation()); - run_case("delete_complex_double_rotation", delete_complex_double_rotation()); - run_case("delete_complex_multiple_rotation", delete_complex_multiple_rotation()); - - // delete non-existing - run_case("delete_DNE", delete_DNE()); - - lb_srand(2986); - // ultimate apocalypse - for (int i = 0; i < AVL_APOCALYPSE_IT; i++) - { - run_case("test_apocalypse", test_apocalypse()); - } - - test_end(); -} - diff --git a/test/avl_test.c b/test/avl_test.c new file mode 100644 index 0000000..3d3f660 --- /dev/null +++ b/test/avl_test.c @@ -0,0 +1,979 @@ +#include <kern/cdef.h> +#include <kern/libkern.h> +#include <kern/avl_tree.h> +#include <test/ktest.h> +#include <kern/brute.h> + +struct test_node { + struct avl_node tree_entry; + int32 val; +} test_node; + +#define AVL_BRUTE_TEST_NODE 1024 +#define AVL_MAX_TEST_NODE (AVL_BRUTE_TEST_NODE + 512) + +static struct test_node avl_alloc_nodes[AVL_MAX_TEST_NODE]; +static int avl_alloc_idx = 0; + +static struct test_node * +create_test_node(int val) +{ + KASSERT(avl_alloc_idx < AVL_MAX_TEST_NODE, "node allocation overflow"); + + struct test_node *rs = &avl_alloc_nodes[avl_alloc_idx++]; + rs->val = val; + return rs; +} + +static int +test_node_compare(struct avl_node *root, struct avl_node *node) +{ + struct test_node *tree_node = OBTAIN_STRUCT_ADDR(root, struct test_node, tree_entry); + struct test_node *self = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); + return tree_node->val - self->val; +} + +static void +pre_order_print(struct avl_node *node) +{ + if (node == NULL) { + return; + } + struct test_node *t_node = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); + kprintf("%d-", t_node->val); + pre_order_print(node->left); + pre_order_print(node->right); +} + +static void ATTR_UNUSED +pre_order(struct avl_node *node) +{ + pre_order_print(node); +} + +static int +_pre_order_assert(struct avl_node *node, const int *order, int size, int *counter) +{ + if (node == NULL) { + return 1; + } + if (*counter >= size) { + return 0; + } + + int result = 1; + struct test_node *t_node = OBTAIN_STRUCT_ADDR(node, struct test_node, tree_entry); + if (order[*counter] != t_node->val) { + result = 0; + } + (*counter)++; + result = result && _pre_order_assert(node->left, order, size, counter); + result = result && _pre_order_assert(node->right, order, size, counter); + return result; +} + +static int +pre_order_assert(struct avl_root *tree, int order[], int size) +{ + int ret; + int counter = 0; + + ret = _pre_order_assert(tree->root, order, size, &counter); +#ifdef TDBG + if (!ret) + { + printf("[AVL ASSERT] Expected: "); + for (int i = 0; i < size; i++) + { + printf("%d-", order[i]); + } + printf("\n Got:"); + pre_order(tree->root); + printf("\n"); + fflush(stdout); + } +#endif + return ret; +} + +/** + * Tests + */ + +static void +insert_simple_l(void) +{ + //1 2 + // \ / \ + // 2 == 1L ==> 1 3 + // \ + // 3 + ktest_begin("insert_simple_l"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(1)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + int val1[] = {1, 2}; + KASSERT(pre_order_assert(&tree, val1, 2), "insert_simple_l_1"); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + int val2[] = {2, 1, 3}; + KASSERT(pre_order_assert(&tree, val2, 3), "insert_simple_l_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_simple_r(void) +{ + // 3 2 + // / / \ + // 2 == 1R ==> 1 3 + // / + //1 + ktest_begin("insert_simple_r"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + int val1[] = {3, 2}; + KASSERT(pre_order_assert(&tree, val1, 2), "insert_simple_r_1"); + + avl_insert(&tree, &create_test_node(1)->tree_entry); + + int val2[] = {2, 1, 3}; + KASSERT(pre_order_assert(&tree, val2, 3), "insert_simple_r_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_simple_ll(void) +{ + //2 3 + // \ / \ + // 4 == 2L ==> 2 4 + // / + //3 + ktest_begin("insert_simple_ll"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + int val1[] = {2, 4}; + KASSERT(pre_order_assert(&tree, val1, 2), "insert_simple_ll_1"); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + + int val2[] = {3, 2, 4}; + KASSERT(pre_order_assert(&tree, val2, 3), "insert_simple_ll_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_simple_rr(void) +{ + // 4 3 + // / / \ + //2 == 2R ==> 2 4 + // \ + // 3 + ktest_begin("insert_simple_rr"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + int val1[] = {4, 2}; + KASSERT(pre_order_assert(&tree, val1, 2), "insert_simple_rr_1"); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + + int val2[] = {3, 2, 4}; + KASSERT(pre_order_assert(&tree, val2, 3), "insert_simple_rr_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_complex_1(void) +{ + // 20+ 20++ 20++ 9 + // / \ / \ / \ / \ + // 4 26 => 4- 26 => 9+ 26 => 4+ 20 + // / \ / \ / \ / / \ + //3 9 3 9- 4+ 15 3 15 26 + // \ / + // 15 3 + ktest_begin("insert_complex_1"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(26)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(9)->tree_entry); + int val1[] = {20, 4, 3, 9, 26}; + KASSERT(pre_order_assert(&tree, val1, 5), "insert_complex_1_1"); + + avl_insert(&tree, &create_test_node(15)->tree_entry); + + int val2[] = {9, 4, 3, 20, 15, 26}; + KASSERT(pre_order_assert(&tree, val2, 6), "insert_complex_1_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_complex_2(void) +{ + // 20+ 20++ 20++ 9 + // / \ / \ / \ / \ + // 4 26 => 4- 26 => 9++ 26 => 4 20- + // / \ / \ / / \ \ + //3 9 3 9+ 4 3 8 26 + // / / \ + // 8 3 8 + ktest_begin("insert_complex_2"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(26)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(9)->tree_entry); + int val1[] = {20, 4, 3, 9, 26}; + KASSERT(pre_order_assert(&tree, val1, 5), "insert_complex_2_1"); + + avl_insert(&tree, &create_test_node(8)->tree_entry); + + int val2[] = {9, 4, 3, 8, 20, 26}; + KASSERT(pre_order_assert(&tree, val2, 6), "insert_complex_2_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_complex_3(void) +{ + // __20+__ _20++_ __20++_ ___9___ + // / \ / \ / \ / \ + // 4 26 => 4- 26 => 9+ 26 => 4+ __20__ + // / \ / \ / \ / \ / \ / \ / \ / \ + // 3+ 9 21 30 3+ 9- 21 30 4+ 11- 21 30 3+ 7 11- 26 + // / / \ / / \ / \ \ / \ / \ + //2 7 11 2 7 11- 3+ 7 15 2 15 21 30 + // \ / + // 15 2 + ktest_begin("insert_complex_3"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(26)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(9)->tree_entry); + avl_insert(&tree, &create_test_node(21)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &create_test_node(7)->tree_entry); + avl_insert(&tree, &create_test_node(11)->tree_entry); + int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; + KASSERT(pre_order_assert(&tree, val1, 10), "insert_complex_3_1"); + + avl_insert(&tree, &create_test_node(15)->tree_entry); + + int val2[] = {9, 4, 3, 2, 7, 20, 11, 15, 26, 21, 30}; + KASSERT(pre_order_assert(&tree, val2, 11), "insert_complex_3_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_complex_4(void) +{ + // __20+__ _20++_ __20++_ ___9___ + // / \ / \ / \ / \ + // 4 26 4- 26 9+ 26 4 _20- + // / \ / \ / \ / \ / \ / \ / \ / \ + // 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26 + // / / \ / / \ / \ / \ / \ + //2 7 11 2 7- 11 3+ 7- 2 8 21 30 + // \ / \ + // 8 2 8 + ktest_begin("insert_complex_4"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(26)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(9)->tree_entry); + avl_insert(&tree, &create_test_node(21)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &create_test_node(7)->tree_entry); + avl_insert(&tree, &create_test_node(11)->tree_entry); + int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; + KASSERT(pre_order_assert(&tree, val1, 10), "insert_complex_4_1"); + + avl_insert(&tree, &create_test_node(8)->tree_entry); + + int val2[] = {9, 4, 3, 2, 7, 8, 20, 11, 26, 21, 30}; + KASSERT(pre_order_assert(&tree, val2, 11), "insert_complex_4_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +insert_duplicate(void) +{ + // __20+__ _20++_ __20++_ ___9___ + // / \ / \ / \ / \ + // 4 26 4- 26 9+ 26 4 _20- + // / \ / \ / \ / \ / \ / \ / \ / \ + // 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26 + // / / \ / / \ / \ / \ / \ + //2 7 11 2 7- 11 3+ 7- 2 8 21 30 + // \ / \ + // 8 2 8 + ktest_begin("insert_duplicate"); + struct avl_root tree; + struct test_node *temp, *temp20, *temp30, *temp7, *temp2; + avl_init(&tree, test_node_compare); + + temp20 = create_test_node(20); + temp30 = create_test_node(30); + temp7 = create_test_node(7); + temp2 = create_test_node(2); + + avl_insert(&tree, &temp20->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &create_test_node(26)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(9)->tree_entry); + avl_insert(&tree, &create_test_node(21)->tree_entry); + avl_insert(&tree, &temp30->tree_entry); + avl_insert(&tree, &temp2->tree_entry); + avl_insert(&tree, &temp7->tree_entry); + avl_insert(&tree, &create_test_node(11)->tree_entry); + int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30}; + KASSERT(pre_order_assert(&tree, val1, 10), "insert_duplicate_1"); + + // should return the value being overwritten + temp = OBTAIN_STRUCT_ADDR(avl_insert(&tree, &create_test_node(20)->tree_entry), struct test_node, tree_entry); + KASSERT((temp == temp20), "insert_duplicate_2"); + temp = OBTAIN_STRUCT_ADDR(avl_insert(&tree, &create_test_node(30)->tree_entry), struct test_node, tree_entry); + KASSERT((temp == temp30), "insert_duplicate_3"); + temp = OBTAIN_STRUCT_ADDR(avl_insert(&tree, &create_test_node(7)->tree_entry), struct test_node, tree_entry); + KASSERT((temp == temp7), "insert_duplicate_4"); + temp = OBTAIN_STRUCT_ADDR(avl_insert(&tree, &create_test_node(2)->tree_entry), struct test_node, tree_entry); + KASSERT((temp == temp2), "insert_duplicate_5"); + + KASSERT(pre_order_assert(&tree, val1, 10), "insert_duplicate_6"); + KASSERT(avl_validate(&tree), "validate"); +} + + +static void +delete_simple_l(void) +{ + // 2 3 + // x \ / \ + //1 3 == 1L ==> 2 4 + // \ + // 4 + ktest_begin("delete_simple_l"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(1); + + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + int val1[] = {2, 1, 3, 4}; + KASSERT(pre_order_assert(&tree, val1, 4), "delete_simple_l_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {3, 2, 4}; + KASSERT(pre_order_assert(&tree, val2, 3), "delete_simple_l_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_simple_r(void) +{ + // 3 2 + // / x / \ + // 2 4 == 1R ==> 1 3 + // / + //1 + ktest_begin("delete_simple_r"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(4); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(1)->tree_entry); + int val1[] = {3, 2, 1, 4}; + KASSERT(pre_order_assert(&tree, val1, 4), "delete_simple_r_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {2, 1, 3}; + KASSERT(pre_order_assert(&tree, val2, 3), "delete_simple_r_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_simple_ll(void) +{ + // 2 3 + // x \ / \ + //1 4 == 2L ==> 2 4 + // / + // 3 + ktest_begin("delete_simple_ll"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(1); + + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &create_test_node(4)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(3)->tree_entry); + int val1[] = {2, 1, 4, 3}; + KASSERT(pre_order_assert(&tree, val1, 4), "delete_simple_ll_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {3, 2, 4}; + KASSERT(pre_order_assert(&tree, val2, 3), "delete_simple_ll_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_simple_rr(void) +{ + // 3 2 + // / x / \ + //2 4 == 2R ==> 1 3 + // \ + // 1 + ktest_begin("delete_simple_rr"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(4); + + avl_insert(&tree, &create_test_node(3)->tree_entry); + avl_insert(&tree, &create_test_node(2)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(1)->tree_entry); + int val1[] = {3, 2, 1, 4}; + KASSERT(pre_order_assert(&tree, val1, 4), "delete_simple_rr_1" ); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {2, 1, 3}; + KASSERT(pre_order_assert(&tree, val2, 3), "delete_simple_rr_2" ); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_1(void) +{ + // Test Case #1 + // - A single node tree has its only node removed. + // Create: + // 10 + // + // Call: remove(10) + // + // Result: + // empty tree + ktest_begin("delete_complex_1"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(10); + + avl_insert(&tree, &deleted->tree_entry); + int val1[] = {10}; + KASSERT(pre_order_assert(&tree, val1, 1), "delete_complex_1_1"); + + avl_remove(&tree, &deleted->tree_entry); + + KASSERT(pre_order_assert(&tree, val1, 0), "delete_complex_1_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_2(void) +{ + // Test Case #2 + // - A small tree has its root removed. + // Create: + // 20 + // / \ + // 10 30 + // / \ + // 25 35 + // + // Call: remove(20) + // + // Results: (simplest result with no rotations) + // (replace root with smallest value on the treenode or 25) + // + // 25 + // / \ + // 10 30 + // \ + // 35 + // + ktest_begin("delete_complex_2"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(20); + + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(10)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + avl_insert(&tree, &create_test_node(35)->tree_entry); + int val1[] = {20, 10, 30, 25, 35}; + KASSERT(pre_order_assert(&tree, val1, 5), "delete_complex_2_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {25, 10, 30, 35}; + KASSERT(pre_order_assert(&tree, val2, 4), "delete_complex_2_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_3(void) +{ + // Test Case #3 + // - A small tree has a node with 2 children removed + // 20 + // / \ + // 10 30 + // / \ / + // 5 15 25 + // + // Call: remove(10) + // + // Results: + // 20 + // / \ + // 15 30 + // / / + // 5 25 + ktest_begin("delete_complex_3"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(10); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(5)->tree_entry); + avl_insert(&tree, &create_test_node(15)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + int val1[] = {20, 10, 5, 15, 30, 25}; + KASSERT(pre_order_assert(&tree, val1, 6), "delete_complex_3_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {20, 15, 5, 30, 25}; + KASSERT(pre_order_assert(&tree, val2, 5), "delete_complex_3_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_4(void) +{ + // Test Case #4 + // - A small tree has all nodes but the root removed from the bottom up. + // Create: + // 20 + // / \ + // 10 30 + // / \ / + // 5 15 25 + // + // Call: remove(5), remove(15), remove(25), remove(10), remove(30) + // + // + // Results: + // 20 + // + ktest_begin("delete_complex_4"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *delete5 = create_test_node(5); + struct test_node *delete10 = create_test_node(10); + struct test_node *delete15 = create_test_node(15); + struct test_node *delete25 = create_test_node(25); + struct test_node *delete30 = create_test_node(30); + + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &delete10->tree_entry); + avl_insert(&tree, &delete30->tree_entry); + avl_insert(&tree, &delete5->tree_entry); + avl_insert(&tree, &delete15->tree_entry); + avl_insert(&tree, &delete25->tree_entry); + + int val1[] = {20, 10, 5, 15, 30, 25}; + KASSERT(pre_order_assert(&tree, val1, 6), "delete_complex_4_1"); + + avl_remove(&tree, &delete5->tree_entry); + avl_remove(&tree, &delete15->tree_entry); + avl_remove(&tree, &delete25->tree_entry); + avl_remove(&tree, &delete10->tree_entry); + avl_remove(&tree, &delete30->tree_entry); + + int val2[] = {20}; + KASSERT(pre_order_assert(&tree, val2, 1), "delete_complex_4_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_single_rotation(void) +{ + // Test case single rotation + // + // Create: + // + // 20 + // / \ + // 10 30 + // / \ / \ + // 5 15 25 40 + // / / / \ + // 12 22 35 50 + // / + // 31 + // + // Call: remove(50) + // + // 20 + // / \ + // 10 30 + // / \ / \ + // 5 15 25 35 + // / / / \ + // 12 22 31 40 + // + // + ktest_begin("delete_complex_single_rotation"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(50); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(10)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(5)->tree_entry); + avl_insert(&tree, &create_test_node(15)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + avl_insert(&tree, &create_test_node(40)->tree_entry); + avl_insert(&tree, &create_test_node(12)->tree_entry); + avl_insert(&tree, &create_test_node(22)->tree_entry); + avl_insert(&tree, &create_test_node(35)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(31)->tree_entry); + int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; + KASSERT(pre_order_assert(&tree, val1, 12), "delete_complex_single_rotation_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {20, 10, 5, 15, 12, 30, 25, 22, 35, 31, 40}; + KASSERT(pre_order_assert(&tree, val2, 11), "delete_complex_single_rotation_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_double_rotation(void) +{ +// Test case double rotation + // + // Create: + // + // 20 + // / \ + // 10 30 + // / \ / \ + // 5 15 25 40 + // / / / \ + // 12 22 35 50 + // / + // 31 + // + // Call: remove(22) + // + // 20 + // / \ + // 10 35 + // / \ / \ + // 5 15 30 40 + // / / \ \ + // 12 25 31 50 + // + // + ktest_begin("delete_complex_double_rotation"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(22); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(10)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(5)->tree_entry); + avl_insert(&tree, &create_test_node(15)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + avl_insert(&tree, &create_test_node(40)->tree_entry); + avl_insert(&tree, &create_test_node(12)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(35)->tree_entry); + avl_insert(&tree, &create_test_node(50)->tree_entry); + avl_insert(&tree, &create_test_node(31)->tree_entry); + int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; + KASSERT(pre_order_assert(&tree, val1, 12), "delete_complex_double_rotation_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {20, 10, 5, 15, 12, 35, 30, 25, 31, 40, 50}; + KASSERT(pre_order_assert(&tree, val2, 11), "delete_complex_double_rotation_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_complex_multiple_rotation(void) +{ + // Test case multiple rotation + // + // Create: + // 20 + // / \ + // 10 30 + // / \ / \ + // 5 15 25 40 + // / / / \ + // 12 22 35 50 + // / + // 31 + // + // Call: remove(5) + // + // Results: + // 30 + // / \ + // 20 40 + // / \ / \ + // 12 25 35 50 + // / \ / / + // 10 15 22 31 + // + // + ktest_begin("delete_complex_multiple_rotation"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *deleted = create_test_node(5); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(10)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &deleted->tree_entry); + avl_insert(&tree, &create_test_node(15)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + avl_insert(&tree, &create_test_node(40)->tree_entry); + avl_insert(&tree, &create_test_node(12)->tree_entry); + avl_insert(&tree, &create_test_node(22)->tree_entry); + avl_insert(&tree, &create_test_node(35)->tree_entry); + avl_insert(&tree, &create_test_node(50)->tree_entry); + avl_insert(&tree, &create_test_node(31)->tree_entry); + int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50}; + KASSERT(pre_order_assert(&tree, val1, 12), "delete_complex_multiple_rotation_1"); + + avl_remove(&tree, &deleted->tree_entry); + + int val2[] = {30, 20, 12, 10, 15, 25, 22, 40, 35, 31, 50}; + KASSERT(pre_order_assert(&tree, val2, 11), "delete_complex_multiple_rotation_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +delete_DNE(void) +{ + // Test case DNE + // Delete a node that does not exist + // 20 + // / \ + // 10 30 + // / \ / + // 5 15 25 + // + // Call: remove(100), remove(24) + // + // + // Results: + // 20 + // / \ + // 10 30 + // / \ / + // 5 15 25 + // + ktest_begin("delete_DNE"); + struct avl_root tree; + avl_init(&tree, test_node_compare); + + struct test_node *delete100 = create_test_node(100); + struct test_node *delete24 = create_test_node(24); + + avl_insert(&tree, &create_test_node(20)->tree_entry); + avl_insert(&tree, &create_test_node(10)->tree_entry); + avl_insert(&tree, &create_test_node(30)->tree_entry); + avl_insert(&tree, &create_test_node(5)->tree_entry); + avl_insert(&tree, &create_test_node(15)->tree_entry); + avl_insert(&tree, &create_test_node(25)->tree_entry); + + int val1[] = {20, 10, 5, 15, 30, 25}; + KASSERT(pre_order_assert(&tree, val1, 6), "delete_DNE_1"); + + avl_remove(&tree, &delete24->tree_entry); + avl_remove(&tree, &delete100->tree_entry); + KASSERT(pre_order_assert(&tree, val1, 6), "delete_DNE_2"); + KASSERT(avl_validate(&tree), "validate"); +} + +static void +test_apocalypse(void) +{ + struct avl_root tree; + + ktest_begin("test_apocalypse"); + + ksrand(1337523847); + + avl_init(&tree, test_node_compare); + + // insert test + for (int i = 0; i < AVL_BRUTE_TEST_NODE; i++) { + avl_alloc_nodes[i].val = krand(); + while (avl_search(&tree, &avl_alloc_nodes[i].tree_entry) != NULL) { + avl_alloc_nodes[i].val += krand() % 32765; + } + avl_insert(&tree, &avl_alloc_nodes[i].tree_entry); + } + + // integrity test + KASSERT(avl_validate(&tree), "validate"); + KASSERT(avl_size(&tree) == AVL_BRUTE_TEST_NODE, "test_apo_sz_1"); + + // smaller and bigger test + struct avl_node *entry = avl_first(&tree); + uint32 size = 0; + int32 prev = -1; + int32 cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; + while (entry != NULL) { + if (cur < prev) { + KASSERT(0, "test_apo_order_1"); + break; + } + size++; + entry = avl_next(&tree, entry); + prev = cur; + if (entry != NULL) { + cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; + } + } + + KASSERT(size == AVL_BRUTE_TEST_NODE, "test_apo_1"); + + // larger test + entry = avl_last(&tree); + size = 0; + cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; + prev = cur; + while (entry != NULL) { + if (cur > prev) { + KASSERT(0, "test_apo_order_1"); + break; + } + size++; + entry = avl_prev(&tree, entry); + prev = cur; + if (entry != NULL) { + cur = OBTAIN_STRUCT_ADDR(entry, struct test_node, tree_entry)->val; + } + } + + KASSERT(size == AVL_BRUTE_TEST_NODE, "test_apo_2"); + + + // delete and search test + for (int i = 0; i < AVL_BRUTE_TEST_NODE; i++) { + KASSERT((avl_search(&tree, &avl_alloc_nodes[i].tree_entry) != NULL), "test_apo_search_1"); + avl_remove(&tree, &avl_alloc_nodes[i].tree_entry); + KASSERT((avl_search(&tree, &avl_alloc_nodes[i].tree_entry) == NULL), "test_apo_search_2"); + KASSERT(avl_validate(&tree), "test_apo_validate_2"); + } + + KASSERT((avl_size(&tree) == 0), "test_apo_sz_2"); +} + +static void +avl_tree_test(ATTR_UNUSED void *unused) +{ + insert_simple_l(); + insert_simple_r(); + insert_simple_ll(); + insert_simple_rr(); + + // complex ones + insert_complex_1(); + insert_complex_2(); + insert_complex_3(); + insert_complex_4(); + + // insert duplicate + insert_duplicate(); + + // simple tests + delete_simple_l(); + delete_simple_r(); + delete_simple_ll(); + delete_simple_rr(); + + // complex tests + delete_complex_1(); + delete_complex_2(); + delete_complex_3(); + delete_complex_4(); + delete_complex_single_rotation(); + delete_complex_double_rotation(); + delete_complex_multiple_rotation(); + delete_DNE(); + + /* clear all memory */ + test_apocalypse(); +} + +KTEST_DECL(avl_tree, KTEST_SUBSYS_AVL, avl_tree_test, NULL); + diff --git a/test/inc/test_case.h b/test/inc/test_case.h deleted file mode 100644 index 2e6cbd0..0000000 --- a/test/inc/test_case.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEST_TEST_H -#define TEST_TEST_H - -#include "cdef.h" - -void -linked_list_test(void); - -void -avl_tree_test(void); - -void -salloc_test(void); - -#endif diff --git a/test/inc/test_main.h b/test/inc/test_main.h deleted file mode 100644 index 3f4fd13..0000000 --- a/test/inc/test_main.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TEST_DRIVER_H -#define TEST_DRIVER_H - -#include "cdef.h" - -void -test_begin(char *name); - -void -test_end(void); - -void * -talloc(uint32 size); - -void -run_case(char *name, bool result); - -#endif diff --git a/test/kern_stub.c b/test/kern_stub.c deleted file mode 100644 index 7175e88..0000000 --- a/test/kern_stub.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "cdef.h" -#include "hal.h" - -/** - * Bogus implementation of HAL - */ -int32 KABI -hal_atomic_xchg_32(int32 *target, int32 val) -{ - return 0; -} - - -int32 KABI -hal_atomic_inc_32(int32 *target, int32 increment) -{ - return 0; -} - -int32 KABI -hal_atomic_cmpxchg_32(int32 *target, int32 compare, int32 val) -{ - return 0; -} - -uint32 KABI -hal_set_irql(uint32 irql) -{ - return 0; -} - -uint32 KABI -hal_get_irql(void) -{ - return 0; -} - -void KABI -hal_issue_intr(uint32 core, uint32 vector) -{ -} - -void KABI -hal_reg_intr(uint32 index, k_intr_dispatcher handler) -{ -} - -void KABI -hal_dereg_intr(uint32 index) -{ -} - -void KABI -hal_reg_exc(uint32 exc, k_exc_dispatcher handler) -{ -} - -void KABI -hal_dereg_exc(uint32 exc) -{ -} - -uint32 KABI -hal_get_core_id(void) -{ - return 0; -} - -void KABI -hal_halt(void) -{ - -} \ No newline at end of file diff --git a/test/ktest.c b/test/ktest.c new file mode 100644 index 0000000..cb22460 --- /dev/null +++ b/test/ktest.c @@ -0,0 +1,35 @@ +#include <test/ktest.h> +#include <kern/cdef.h> +#include <kern/print.h> +#include <kern/kinit.h> + +static uint ktest_cases = 0; + +static void +ktest_reset() +{ + ktest_cases = 0; +} + +void +ktest_begin(const char* name) +{ + kprintf(" Running test %d: %s...", ktest_cases, name); + ktest_cases++; +} + +static void +ktest_main(ATTR_UNUSED void* args) +{ + kprintf("Running ktest test suite...\n\n"); + // run all ktests XXX: we don't care about priority for now as qsort is part of the test + for(struct ktest **it = KTEST_START; it < KTEST_STOP; it++) { + ktest_reset(); + kprintf("Testing subsystem %s...\n", (*it)->name); + (*it)->func((*it)->args); + kprintf("%d test cases passed.\n\n", ktest_cases); + } + kprintf("All tests completed.\n"); +} + +KINIT_DECL(ktest, KINIT_SUBSYS_KTEST, 0, ktest_main, NULL); diff --git a/test/list_test.c b/test/list_test.c new file mode 100644 index 0000000..2781bd5 --- /dev/null +++ b/test/list_test.c @@ -0,0 +1,274 @@ +#include <test/ktest.h> +#include <kern/cdef.h> +#include <kern/list.h> +#include <kern/libkern.h> + +#define ARR_SZ(arr) (sizeof(arr) / sizeof((arr)[0])) + +struct test_list_node { + struct list_entry lnode; + int val; +}; + +static void +validate_list(struct list_entry *list) +{ + if (list_empty(list)) { + return; + } + + KASSERT(!(list->prev == NULL || list->next == NULL), "list head ptr corrupted"); + + struct list_entry *it; + LIST_FOREACH(list, it) { + KASSERT(it->next->prev == it && it->prev->next == it, "forward list entry ptr corrupted"); + } + + LIST_FOREACH_REVERSE(list, it) { + KASSERT(it->next->prev == it && it->prev->next == it, "backward list entry ptr corrupted"); + } +} + +//static void +//print_list(struct list_entry *list) +//{ +// struct list_entry *e; +// +// LIST_FOREACH(list, e) { +// struct test_list_node *enode = OBTAIN_STRUCT_ADDR(e, struct test_list_node, lnode); +// kprintf("%d->", enode->val); +// } +// kprintf("[END]\n"); +//} + +static void +check_list_elements(struct list_entry *list, const int *val, int size) +{ + struct list_entry *node; + int i = 0; + + LIST_FOREACH(list, node) { + struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode); + KASSERT(enode->val == val[i], "check list element failed at idx %d: %d != %d", i, enode->val, val[i]); + i++; + } + + KASSERT(i == size, "list size != expected size"); +} + +static void +assert_list(struct list_entry *list, const int *val, int size) +{ + validate_list(list); + check_list_elements(list, val, size); +} + +static void +insert_test_front(void) +{ + ktest_begin("insert_test_front"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + int val[] = {3, 2, 1, 0}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +insert_test_before(void) +{ + ktest_begin("insert_test_before"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert_before(&list, &n0.lnode); + list_insert_before(&list, &n1.lnode); + list_insert_before(&list, &n2.lnode); + list_insert_before(&list, &n3.lnode); + + int val[] = {0, 1, 2, 3}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +insert_test_middle(void) +{ + ktest_begin("insert_test_middle"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n4 = {.val = 4}; + struct test_list_node n5 = {.val = 5}; + struct test_list_node n6 = {.val = 6}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + + list_insert(&n1.lnode, &n4.lnode); + list_insert(&n1.lnode, &n5.lnode); + list_insert_before(&n4.lnode, &n6.lnode); + + int val[] = {2, 1, 5, 6, 4, 0}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +insert_test_back(void) +{ + ktest_begin("insert_test_back"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&n0.lnode, &n1.lnode); + list_insert(&n1.lnode, &n2.lnode); + list_insert(&n2.lnode, &n3.lnode); + + int val[] = {0, 1, 2, 3}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +remove_test_front(void) +{ + ktest_begin("remove_test_front"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + list_remove_after(&list); + list_remove_after(&list); + + int val[] = {1, 0}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +remove_test_middle(void) +{ + ktest_begin("remove_test_middle"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + list_remove(&n1.lnode); + list_remove(&n2.lnode); + + int val[] = {3, 0}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +remove_test_end(void) +{ + ktest_begin("remove_test_middle"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + list_remove_before(&list); + list_remove_before(&list); + + int val[] = {3, 2}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +remove_test_all(void) +{ + ktest_begin("remove_test_all"); + + struct list_entry list; + struct test_list_node n0 = {.val = 0}; + struct test_list_node n1 = {.val = 1}; + struct test_list_node n2 = {.val = 2}; + struct test_list_node n3 = {.val = 3}; + + list_init(&list); + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + list_remove_after(&list); + list_remove_after(&list); + list_remove_after(&list); + list_remove_after(&list); + + assert_list(&list, NULL, 0); + + list_insert(&list, &n0.lnode); + list_insert(&list, &n1.lnode); + list_insert(&list, &n2.lnode); + list_insert(&list, &n3.lnode); + + int val[] = {0, 1, 2, 3}; + assert_list(&list, val, ARR_SZ(val)); +} + +static void +list_test(ATTR_UNUSED void *unused) +{ + insert_test_front(); + insert_test_before(); + insert_test_middle(); + insert_test_back(); + + remove_test_front(); + remove_test_middle(); + remove_test_end(); + remove_test_all(); +} + +KTEST_DECL(list, KTEST_SUBSYS_LIST, list_test, NULL); diff --git a/test/llist_test.c b/test/llist_test.c deleted file mode 100644 index 6fe7c23..0000000 --- a/test/llist_test.c +++ /dev/null @@ -1,497 +0,0 @@ -#include "test_main.h" -#include "test_case.h" -#include "lb/llist.h" -#include "clib.h" -#include <stdio.h> - -struct test_list_node -{ - struct llist_node lnode; - int32 val; -}; - -static bool -validate_list(struct llist *list) -{ - bool result = TRUE; - // list_head_test - if (list->head != NULL) - { - result = result && (list->head->prev == NULL); - } - else - { - result = result && (list->tail == NULL); - } - - if (list->tail != NULL) - { - result = result && (list->tail->next == NULL); - } - else - { - result = result && (list->head == NULL); - } - - return result; -} - -static void -print_list(struct llist *list) -{ -#ifdef TDBG - struct llist_node *node = lb_llist_first(list); - - while (node != NULL) - { - struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode); - printf("%d->", enode->val); - node = lb_llist_next(node); - } - printf("[END]\n"); -#endif -} - -static bool -check_list_elements(struct llist *list, int val[], int size) -{ - struct llist_node *node = list->head; - bool ret = TRUE; - int i = 0; - while (node != NULL && i < size) - { - struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode); - if (enode->val != val[i]) - { - ret = FALSE; - break; - } - i++; - node = lb_llist_next(node); - } - - if(ret) - { - if (i != size) - { - ret = FALSE; - } - } - - if(ret) - { - node = lb_llist_last(list); - while (node != NULL && i >= 0) - { - struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode); - if (enode->val != val[i - 1]) - { - ret = FALSE; - break; - } - i--; - node = lb_llist_prev(node); - } - } - - if(ret) - { - ret = ret && (i == 0); - } - -#ifdef TDBG - if (!ret) - { - printf("[LLIST ASSERT] Expected: "); - for (i = 0; i < size; i++) - { - printf("%d-", val[i]); - } - printf("\n Got:"); - print_list(list); - printf("\n"); - fflush(stdout); - } -#endif - return ret; -} - - -static bool -assert_list(struct llist *list, int val[], int size) -{ - struct llist_node *node = lb_llist_first(list); - int i = 0; - - if (!validate_list(list)) - { - return FALSE; - } - - return check_list_elements(list, val, size); -} - -static void -insert_val(struct llist *list, int index, int val) -{ - struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node)); - a->val = val; - lb_llist_insert_by_idx(list, index, &a->lnode); -} - -static void -push_back_val(struct llist *list, int val) -{ - struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node)); - a->val = val; - lb_llist_push_back(list, &a->lnode); -} - -static void -push_front_val(struct llist *list, int val) -{ - struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node)); - a->val = val; - lb_llist_push_front(list, &a->lnode); -} - - -static bool -insert_test_beginning(void) -{ - struct llist list; - lb_llist_init(&list); - insert_val(&list, 0, 0); - insert_val(&list, 0, 1); - insert_val(&list, 0, 2); - insert_val(&list, 0, 3); - - // 3210==0123 - int val[4] = {3, 2, 1, 0}; - return assert_list(&list, val, 4); -} - -static bool -insert_test_middle(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 0); - insert_val(&list, 0, 1); - insert_val(&list, 0, 2); - - insert_val(&list, 1, 4); - insert_val(&list, 1, 5); - insert_val(&list, 2, 6); - - int val[] = {2, 5, 6, 4, 1, 0}; - return assert_list(&list, val, 6); -} - -static bool -insert_test_end(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - int val[] = {0, 1, 2, 3}; - return assert_list(&list, val, 4); -} - -static bool -insert_test_invalid(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 3); - insert_val(&list, 0, 2); - insert_val(&list, 0, 1); - insert_val(&list, 0, 0); - - // large index - insert_val(&list, 5, 9); - insert_val(&list, 6, 9); - insert_val(&list, 999, 9); - - // small index - insert_val(&list, -1, 8); - insert_val(&list, -2, 8); - insert_val(&list, -999, 8); - - /** - * Since it's kernel library - * Don't test NULL - */ - /* - insert_val(NULL, 1, 4); - lb_llist_insert_by_ref(NULL, list.head, list.tail); - lb_llist_insert_by_ref(&list, list.head, NULL); - */ - - int val[] = {0, 1, 2, 3}; - return assert_list(&list, val, 4); -} - - -static bool -remove_test_beginning(void) -{ - struct llist list; - lb_llist_init(&list); - insert_val(&list, 0, 0); - insert_val(&list, 0, 1); - insert_val(&list, 0, 2); - insert_val(&list, 0, 3); - - lb_llist_remove_by_idx(&list, 0); - lb_llist_remove_by_idx(&list, 0); - - // 10==01 - int val[] = {1, 0}; - return assert_list(&list, val, 2); -} - -static bool -remove_test_middle(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 0); - insert_val(&list, 0, 1); - insert_val(&list, 0, 2); - - insert_val(&list, 0, 3); - insert_val(&list, 0, 4); - insert_val(&list, 0, 5); - - lb_llist_remove_by_idx(&list, 1); - lb_llist_remove_by_idx(&list, 2); - - // 5310=====0135 - int val[] = {5, 3, 1, 0}; - return assert_list(&list, val, 4); -} - -static bool -remove_test_end(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - lb_llist_remove_by_idx(&list, 3); - lb_llist_remove_by_idx(&list, 2); - - int val[] = {0, 1}; - return assert_list(&list, val, 2); -} - -static bool -remove_test_all(void) -{ - bool result = TRUE; - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - lb_llist_remove_by_idx(&list, 0); - lb_llist_remove_by_idx(&list, 0); - lb_llist_remove_by_idx(&list, 0); - lb_llist_remove_by_idx(&list, 0); - - result = result && assert_list(&list, NULL, 0); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - lb_llist_remove_by_idx(&list, 3); - lb_llist_remove_by_idx(&list, 2); - lb_llist_remove_by_idx(&list, 1); - lb_llist_remove_by_idx(&list, 0); - - result = result && assert_list(&list, NULL, 0); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - lb_llist_remove_by_idx(&list, 1); - lb_llist_remove_by_idx(&list, 1); - lb_llist_remove_by_idx(&list, 1); - lb_llist_remove_by_idx(&list, 0); - - result = result && assert_list(&list, NULL, 0); - - return result; -} - -static bool -remove_test_invalid(void) -{ - struct llist list; - lb_llist_init(&list); - - insert_val(&list, 0, 3); - insert_val(&list, 0, 2); - insert_val(&list, 0, 1); - insert_val(&list, 0, 0); - - // large index - lb_llist_remove_by_idx(&list, 5); - lb_llist_remove_by_idx(&list, 6); - lb_llist_remove_by_idx(&list, 999); - - // small index - lb_llist_remove_by_idx(&list, -1); - lb_llist_remove_by_idx(&list, -2); - lb_llist_remove_by_idx(&list, -999); - - /** - * Since it's kernel library - * Don't test NULL - */ - /* - lb_llist_remove_by_idx(NULL, 1); - lb_llist_remove_by_ref(NULL, list.head); - lb_llist_remove_by_ref(&list, NULL); */ - - // 0123=====3210 - int val[] = {0, 1, 2, 3}; - return assert_list(&list, val, 4); -} - -static bool -size_test(void) -{ - bool result = TRUE; - struct llist list; - lb_llist_init(&list); - struct llist list2; - lb_llist_init(&list2); - - insert_val(&list, 0, 0); - insert_val(&list, 1, 1); - insert_val(&list, 2, 2); - insert_val(&list, 3, 3); - - /** - * Since it's kernel library - * Don't test NULL - */ - /* - * lb_llist_size(NULL) == -1 - */ - result = result && (lb_llist_size(&list) == 4 && lb_llist_size(&list2) == 0); - - lb_llist_remove_by_idx(&list, 0); - result = result && (lb_llist_size(&list) == 3); - insert_val(&list, 0, 0); - - int val[] = {0, 1, 2, 3}; - result = result && assert_list(&list, val, 4); - return result; -} - -static bool -push_pop_front_test(void) -{ - struct llist_node *node; - bool result = TRUE; - struct llist list; - lb_llist_init(&list); - - push_front_val(&list, 1); - push_front_val(&list, 2); - push_front_val(&list, 3); - push_front_val(&list, 4); - - //4321==1234 - int val1[] = {4, 3, 2, 1}; - result = result && assert_list(&list, val1, 4); - - node = lb_llist_pop_front(&list); - //321==123 - int val2[] = {3, 2, 1}; - result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 4; - - lb_llist_pop_front(&list); - lb_llist_pop_front(&list); - node = lb_llist_pop_front(&list); - - result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 1; - return result; -} - -static bool -push_pop_back_test(void) -{ - bool result = TRUE; - struct llist list; - lb_llist_init(&list); - struct llist_node *node; - - push_back_val(&list, 1); - push_back_val(&list, 2); - push_back_val(&list, 3); - push_back_val(&list, 4); - - //1234==4321 - int val1[] = {1, 2, 3, 4}; - result = result && assert_list(&list, val1, 4); - - node = lb_llist_pop_back(&list); - //123==321 - int val2[] = {1, 2, 3}; - result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 4; - - lb_llist_pop_back(&list); - node = lb_llist_pop_back(&list); - lb_llist_pop_back(&list); - - result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 2; - return result; -} - -void -linked_list_test(void) -{ - test_begin("Linked list test"); - run_case("insert_test_beginning", insert_test_beginning()); - run_case("insert_test_middle", insert_test_middle()); - run_case("insert_test_end", insert_test_end()); - run_case("insert_test_invalid", insert_test_invalid()); - - run_case("remove_test_beginning", remove_test_beginning()); - run_case("remove_test_middle", remove_test_middle()); - run_case("remove_test_end", remove_test_end()); - run_case("remove_test_invalid", remove_test_invalid()); - - run_case("size_test", size_test()); - - run_case("remove_test_all", remove_test_all()); - - run_case("push_pop_front_test", push_pop_front_test()); - run_case("push_pop_back_test", push_pop_back_test()); - - test_end(); -} - diff --git a/test/qsort_test.c b/test/qsort_test.c new file mode 100644 index 0000000..54bc745 --- /dev/null +++ b/test/qsort_test.c @@ -0,0 +1,56 @@ +#include <kern/cdef.h> +#include <kern/libkern.h> +#include <kern/brute.h> +#include <test/ktest.h> + +#define MAX_ELE (10) + +static int +int_cmp(const void* a, const void* b) +{ + return *(const int*)a - *(const int*)b; +} + +static void +arr_assert(const int* a, const int *b, usize sz) +{ + for(usize i = 0; i < sz; i++) { + KASSERT(a[i] == b[i], "element at %d not equal: %d != %d",(int)i, a[i], b[i]); + } +} + +static void +test_permutation(int *arr, int *exp, int *buf, usize start, usize sz) +{ + if (start == sz) { + memcpy(buf, arr, sz * sizeof(int)); + qsort(buf, sz, sizeof(int), int_cmp); + arr_assert(exp, buf, sz); + } else { + for (usize i = start; i < sz; i++) { + memswp(&arr[start], &arr[i], sizeof(int)); + test_permutation(arr, exp, buf, start + 1, sz); + memswp(&arr[start], &arr[i], sizeof(int)); + } + } +} + +static void +qsort_test(ATTR_UNUSED void *unused) +{ + int arr[MAX_ELE]; + int exp[MAX_ELE]; + int buf[MAX_ELE]; + + for(int i = 0; i < MAX_ELE; i++) { + arr[i] = i; + exp[i] = i; + } + + for(int i = 0; i <= MAX_ELE; i++) { + test_permutation(arr, exp, buf, 0, i); + memcpy(arr, exp, sizeof(int) * MAX_ELE); + } +} + +KTEST_DECL(qsort, KTEST_SUBSYS_QSORT, qsort_test, NULL); diff --git a/test/salloc_test.c b/test/salloc_test.c deleted file mode 100644 index d180526..0000000 --- a/test/salloc_test.c +++ /dev/null @@ -1,282 +0,0 @@ -#include "test_main.h" -#include "lb/salloc.h" -#include "test_case.h" - -typedef union -{ - uint32 size; - uint32 flags; -} salloc_header; - -static const uint32 salloc_header_size = sizeof(salloc_header); - -static char buffer[1024]; - -static bool salloc_init_test(void) -{ - lb_salloc_init(buffer, 1024); - uint32 blk_size[] = {1024}; - bool blk_free[] = {TRUE}; - return lb_salloc_assert(buffer, blk_size, blk_free, 1); -} - -static bool salloc_basic_alloc(void) -{ - bool result = TRUE; - lb_salloc_init(buffer, 1024); - result = result && (lb_salloc(buffer, 10) != NULL); - uint32 blk_size[] = {10 + salloc_header_size, 1024 - 10 - salloc_header_size}; - bool blk_free[] = {FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 2); - return result; -} - -static bool salloc_full_alloc(void) -{ - bool result = TRUE; - lb_salloc_init(buffer, 1024); - result = result && (lb_salloc(buffer, 1024 - salloc_header_size) != NULL); - uint32 blk_size[] = {1024}; - bool blk_free[] = {FALSE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - -static bool salloc_overflow_alloc(void) -{ - bool result = TRUE; - lb_salloc_init(buffer, 1024); - result = result && (lb_salloc(buffer, 1024 - salloc_header_size + 1) == NULL); - uint32 blk_size[] = {1024}; - bool blk_free[] = {TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - -static bool salloc_multiple_alloc(void) -{ - bool result = TRUE; - lb_salloc_init(buffer, 1024); - result = result && (lb_salloc(buffer, 10) != NULL); - result = result && (lb_salloc(buffer, 10) != NULL); - result = result && (lb_salloc(buffer, 10) != NULL); - uint32 blk_size[] = {10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 1024 - 3 * (10 + salloc_header_size)}; - bool blk_free[] = {FALSE, FALSE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4); - return result; -} - -static bool salloc_alloc_not_enough(void) -{ - void *ptr; - bool result = TRUE; - lb_salloc_init(buffer, salloc_header_size + salloc_header_size + salloc_header_size - 1); - ptr = lb_salloc(buffer, salloc_header_size); - result = result && (ptr != NULL); - uint32 blk_size[] = {salloc_header_size + salloc_header_size + salloc_header_size - 1}; - bool blk_free[] = {FALSE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - - -static bool salloc_basic_free(void) -{ - void *ptr; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr = lb_salloc(buffer, 10); - result = result && (ptr != NULL); - - lb_sfree(buffer, ptr); - uint32 blk_size[] = {1024}; - bool blk_free[] = {TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - -static bool salloc_full_free(void) -{ - void *ptr; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr = lb_salloc(buffer, 1024 - salloc_header_size); - result = result && (ptr != NULL); - - lb_sfree(buffer, ptr); - uint32 blk_size[] = {1024}; - bool blk_free[] = {TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - -static bool salloc_multiple_free(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL); - lb_sfree(buffer, ptr1); - lb_sfree(buffer, ptr3); - - uint32 blk_size[] = {10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 1024 - 4 * (10 + salloc_header_size)}; - bool blk_free[] = {TRUE, FALSE, TRUE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 5); - return result; -} - -static bool salloc_free_join_tail(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL); - lb_sfree(buffer, ptr4); - - uint32 blk_size[] = {10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 1024 - 3 * (10 + salloc_header_size)}; - bool blk_free[] = {FALSE, FALSE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4); - return result; -} - -static bool salloc_free_join_head(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL); - lb_sfree(buffer, ptr1); - lb_sfree(buffer, ptr2); - - uint32 blk_size[] = {2 * (10 + salloc_header_size), - 10 + salloc_header_size, - 10 + salloc_header_size, - 1024 - 4 * (10 + salloc_header_size)}; - bool blk_free[] = {TRUE, FALSE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4); - return result; -} - -static bool salloc_free_join_mid(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL); - lb_sfree(buffer, ptr2); - lb_sfree(buffer, ptr3); - - uint32 blk_size[] = {10 + salloc_header_size, - 2 * (10 + salloc_header_size), - 10 + salloc_header_size, - 1024 - 4 * (10 + salloc_header_size)}; - bool blk_free[] = {FALSE, TRUE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4); - return result; -} - -static bool salloc_free_join_consecutive(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - ptr5 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL) && (ptr5 != NULL); - lb_sfree(buffer, ptr2); - lb_sfree(buffer, ptr4); - - uint32 blk_size[] = {10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 10 + salloc_header_size, - 1024 - 5 * (10 + salloc_header_size)}; - bool blk_free[] = {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 6); - - lb_sfree(buffer, ptr3); - - uint32 blk_size2[] = {10 + salloc_header_size, - 3 * (10 + salloc_header_size), - 10 + salloc_header_size, - 1024 - 5 * (10 + salloc_header_size)}; - bool blk_free2[] = {FALSE, TRUE, FALSE, TRUE}; - result = result && lb_salloc_assert(buffer, blk_size2, blk_free2, 4); - return result; -} - -static bool salloc_free_all(void) -{ - void *ptr1, *ptr2, *ptr3, *ptr4; - bool result = TRUE; - lb_salloc_init(buffer, 1024); - ptr1 = lb_salloc(buffer, 10); - ptr2 = lb_salloc(buffer, 10); - ptr3 = lb_salloc(buffer, 10); - ptr4 = lb_salloc(buffer, 10); - result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL); - lb_sfree(buffer, ptr1); - lb_sfree(buffer, ptr2); - lb_sfree(buffer, ptr3); - lb_sfree(buffer, ptr4); - - uint32 blk_size[] = {1024}; - bool blk_free[] = {TRUE}; - result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1); - return result; -} - - -void salloc_test(void) -{ - test_begin("salloc test"); - - run_case("salloc_init_test", salloc_init_test()); - - run_case("salloc_basic_alloc", salloc_basic_alloc()); - run_case("salloc_full_alloc", salloc_full_alloc()); - run_case("salloc_overflow_alloc", salloc_overflow_alloc()); - run_case("salloc_multiple_alloc", salloc_multiple_alloc()); - run_case("salloc_alloc_not_enough", salloc_alloc_not_enough()); - - run_case("salloc_basic_free", salloc_basic_free()); - run_case("salloc_full_free", salloc_full_free()); - run_case("salloc_multiple_free", salloc_multiple_free()); - run_case("salloc_free_join_tail", salloc_free_join_tail()); - run_case("salloc_free_join_head", salloc_free_join_head()); - run_case("salloc_free_join_mid", salloc_free_join_mid()); - run_case("salloc_free_join_consecutive", salloc_free_join_consecutive()); - run_case("salloc_free_all", salloc_free_all()); - - test_end(); -} diff --git a/test/test_main.c b/test/test_main.c deleted file mode 100644 index e33ce55..0000000 --- a/test/test_main.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "test_main.h" -#include "test_case.h" -#include <stdio.h> -#include <stdlib.h> - -#define GAT_SIZE 256 -#define CASE_NUM 32 - -typedef struct -{ - char *case_name; - bool success; - bool used; -} case_info; - -static case_info ginfo[CASE_NUM]; -static void *gat[GAT_SIZE]; -static char *test_name; - -static void test_info(void) -{ - printf("[TD-INFO][%s] - ", test_name); - fflush(stdout); -} - -static void test_warning(void) -{ - printf("[TD-WARN][%s] - ", test_name); - fflush(stdout); -} - -static void test_error(void) -{ - printf("[TD-ERR][%s] - ", test_name); - fflush(stdout); -} - -static void gat_push(void *ptr) -{ - for (int i = 0; i < GAT_SIZE; i++) - { - if (gat[i] == NULL) - { - gat[i] = ptr; - return; - } - } -} - -static bool gat_full(void) -{ - for (int i = 0; i < GAT_SIZE; i++) - { - if (gat[i] == NULL) - { - return FALSE; - } - } - return TRUE; -} - -static void gat_free(void) -{ - for (int i = 0; i < GAT_SIZE; i++) - { - if (gat[i] != NULL) - { - free(gat[i]); - gat[i] = NULL; - } - } -} - -static void ginfo_push(char *case_name, bool success) -{ - char *r_case_name = (case_name == NULL ? "Anonymous Case" : case_name); - for (int i = 0; i < CASE_NUM; i++) - { - if (!ginfo[i].used) - { - ginfo[i].case_name = r_case_name; - ginfo[i].success = success; - ginfo[i].used = TRUE; - return; - } - } - test_warning(); - printf("GINFO full, [%s] result not recorded.\n", r_case_name); -} - -void test_begin(char *name) -{ - test_name = (name == NULL ? "Anonymous Test" : name); - for (int i = 0; i < GAT_SIZE; i++) - { - gat[i] = NULL; - } - for (int i = 0; i < CASE_NUM; i++) - { - ginfo[i].used = FALSE; - } -} - -void test_end(void) -{ - gat_free(); - int32 total = 0, failed = 0, success = 0; - for (int i = 0; i < CASE_NUM; i++) - { - if (ginfo[i].used) - { - total++; - if (ginfo[i].success) - { - success++; - } - else - { - failed++; - } - } - } - test_info(); - printf("%s\n", failed > 0 ? "FAIL" : "PASS"); - printf(" %d cases executed. S: %d. F: %d.\n", total, success, failed); - if (failed > 0) - { - for (int i = 0; i < CASE_NUM; i++) - { - if (ginfo[i].used && !ginfo[i].success) - { - printf(" %s FAILED\n", ginfo[i].case_name); - } - } - } - for (int i = 0; i < CASE_NUM; i++) - { - ginfo[i].used = FALSE; - } -} - -void *talloc(uint32 size) -{ - if (!gat_full()) - { - void *result = malloc(size); - gat_push(result); - return result; - } - else - { - test_error(); - printf("GAT full, rejecting further allocations.\n"); - } - return NULL; -} - -void run_case(char *name, bool result) -{ - ginfo_push(name, result); -} - -int main(void) -{ - linked_list_test(); - salloc_test(); - avl_tree_test(); - return 0; -} - - -