Merge working to master #1

Merged
d merged 9 commits from working into master 2019-11-28 18:05:00 +00:00
127 changed files with 3815 additions and 7515 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.idea .idea
cmake-build-debug cmake-build-debug
out/ out/
.vscode

View File

@ -1,24 +1,140 @@
cmake_minimum_required(VERSION 2.8.4) cmake_minimum_required(VERSION 3.10)
project(secX)
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) project(bond)
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)
# HAL set(proj bond)
#include_directories(hal/inc) set(INC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
#add_executable(hal ${hal_src}) 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 # Rules for generating the image
include_directories(kernel/inc) set(TARGET ${proj}_elf)
add_executable(kernel ${kernel_src}) 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})

View File

@ -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

View File

@ -1,7 +1,4 @@
# Building # Building
### Environment
All platforms where the required packages are available.
### Required packages ### Required packages
For compiling kernel only (make compile): 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. 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.

View File

@ -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

16
arch/CMakeLists.txt Normal file
View File

@ -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)

View File

@ -1,18 +1,17 @@
#define ASM_FILE #define ASM_FILE
#include "mlayout.h" #include <arch/mlayout.h>
#include "multiboot2.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_PML4(vaddr) (((vaddr) >> 39 ) & 0x1FF)
%define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF) %define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF)
global sys_entry global arch_init_32
global sys_entry_64 extern arch_main
extern hmain
section .text section .text
bits 32 bits 32
sys_entry: arch_init_32:
cli cli
cld cld
cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC
@ -35,10 +34,9 @@ sys_entry:
mov eax, GET_PADDR(init_pml4) mov eax, GET_PADDR(init_pml4)
mov dword [eax], GET_PADDR(init_pdpt_iden) + 11b ; write the lower bits, higher = 0 mov dword [eax], GET_PADDR(init_pdpt_iden) + 11b ; write the lower bits, higher = 0
; point the nth PML4 entry to the kernel pdpt ; 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 mov dword [eax], GET_PADDR(init_pdpt_kern) + 11b
; identity map the first 4GB ; identity map the first 4GB
mov eax, GET_PADDR(init_pdpt_iden) mov eax, GET_PADDR(init_pdpt_iden)
mov ebx, 10000011b ; R/W + SU + 1G page 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 ; map the first 1 GB, which contains the kernel, to KERNEL_BASE_VADDR
mov eax, GET_PADDR(init_pdpt_kern) mov eax, GET_PADDR(init_pdpt_kern)
; extract the PML4 entry ; 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 ebx, 10000011b ; R/W + SU + 1G page
mov dword [eax], ebx mov dword [eax], ebx
@ -82,10 +80,9 @@ sys_entry:
lgdt [GET_PADDR(init_gdt.ptr)] lgdt [GET_PADDR(init_gdt.ptr)]
; switch to long mode ; switch to long mode
jmp init_gdt.code:GET_PADDR(sys_entry_64) jmp init_gdt.code:GET_PADDR(arch_init_64)
.end: .end:
hlt jmp $
check_long_mode: check_long_mode:
push ebp push ebp
@ -126,7 +123,7 @@ multiboot_info_ptr:
section .text section .text
bits 64 bits 64
sys_entry_64: arch_init_64:
; note that we are in long mode but rip is still lower ; note that we are in long mode but rip is still lower
; switch to high address ; switch to high address
mov rax, .high mov rax, .high
@ -140,10 +137,12 @@ sys_entry_64:
mov gs,ax mov gs,ax
mov ss,ax mov ss,ax
; initial kernel stack, 4k
mov rsp, init_stack mov rsp, init_stack
xor rdi, rdi xor rdi, rdi
mov edi, dword [multiboot_info_ptr] mov edi, dword [multiboot_info_ptr]
call hmain ; init arch
call arch_main
.end: .end:
hlt hlt

6
arch/brute.c Normal file
View File

@ -0,0 +1,6 @@
#include <arch/brute.h>
void arch_brute()
{
while(1) {}
}

229
arch/cpu.asm Normal file
View File

@ -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

82
arch/cpu.c Normal file
View File

@ -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));
}

92
arch/cpu.h Normal file
View File

@ -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);

View File

@ -1,30 +1,21 @@
#include "mem.h" #include <kern/cdef.h>
#include "print.h" #include <kern/print.h>
#include "intr.h" #include <arch/print.h>
#include "cpu.h" #include <arch/brute.h>
#include "kernel.h"
#include "hal.h" // private headers
#include "multiboot2.h" #include "multiboot2.h"
//static void void arch_main(ATTR_UNUSED void* mb_info)
//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)
{ {
if (mb_info == NULL) /* init printf related stuff */
arch_print_init();
kprintf("Initializing arch layer...\n");
arch_brute();
/* if (mb_info == NULL)
{ {
goto err; goto err;
} }
@ -76,5 +67,5 @@ hmain(struct multiboot_tag *mb_info)
kmain(boot_info); kmain(boot_info);
err: err:
hal_halt_cpu(); hal_halt_cpu(); */
} }

View File

@ -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 %macro PUSHAQ 0
push rax ;save current rax push rax ;save current rax
push rbx ;save current rbx push rbx ;save current rbx
@ -37,7 +25,7 @@ ret
pop r10 ;restore current r10 pop r10 ;restore current r10
pop r9 ;restore current r9 pop r9 ;restore current r9
pop r8 ;restore current r8 pop r8 ;restore current r8
pop rsi ;restore current rsi pop rsi ;restore current rsix
pop rdi ;restore current rdi pop rdi ;restore current rdi
pop rbp ;restore current rbp pop rbp ;restore current rbp
pop rdx ;restore current rdx pop rdx ;restore current rdx
@ -85,6 +73,7 @@ hal_interrupt_handler_%1:
; +0 RBP ; +0 RBP
push rbp push rbp
mov rbp,rsp mov rbp,rsp
PUSHAQ PUSHAQ
cld cld
mov rdi, %1 ; INT VEC # mov rdi, %1 ; INT VEC #

121
arch/intr.c Normal file
View File

@ -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);
}

View File

@ -1,6 +1,6 @@
#define ASM_FILE #define ASM_FILE
#include "multiboot2.h" #include "multiboot2.h"
#include "mlayout.h" #include <arch/mlayout.h>
extern hmain extern hmain
global hal_main_32 global hal_main_32

View File

@ -1,33 +1,6 @@
#pragma once #include <kern/cdef.h>
#include <arch/mem.h>
#include "cdef.h" #include <arch/mlayout.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)
/** /**
Page Table Definitions Page Table Definitions
@ -73,39 +46,21 @@
#define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF) #define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF)
#define PT_ENTRY_NUM(vaddr) (((vaddr) >> 12) & 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);

60
arch/print.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -1,9 +0,0 @@
include $(MK)/prologue.mk
MOD:=COMMON
SRC_$(d) := $(d)/clib.c
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -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;
}

4
gdbq
View File

@ -1,4 +0,0 @@
file out/secxkrnl.elf
set arch i386:x86-64
target remote localhost:1234
break hmain

3
gdbw
View File

@ -1,3 +0,0 @@
disconnect
set arch i386:x86-64:intel
target remote localhost:1234

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -1,5 +0,0 @@
#pragma once
#include "cdef.h"
#define HABI KABI

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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

208
hal/mem.c
View File

@ -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);
}

View File

@ -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();
}
}

3
inc/arch/brute.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void arch_brute();

60
inc/arch/intr.h Normal file
View File

@ -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();

10
inc/arch/mem.h Normal file
View File

@ -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);
}

34
inc/arch/mlayout.h Normal file
View File

@ -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)

12
inc/arch/print.h Normal file
View File

@ -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);

View File

@ -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))

View File

@ -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;
}

View File

@ -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);

86
inc/kern/avl_tree.h Normal file
View File

@ -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);

37
inc/kern/bitset.h Normal file
View File

@ -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)));
}

16
inc/kern/brute.h Normal file
View File

@ -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)

37
inc/kern/cdef.h Normal file
View File

@ -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)))

33
inc/kern/kinit.h Normal file
View File

@ -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
};

11
inc/kern/lds.h Normal file
View File

@ -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)

77
inc/kern/libkern.h Normal file
View File

@ -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);

90
inc/kern/list.h Normal file
View File

@ -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))

9
inc/kern/poison.h Normal file
View File

@ -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))

10
inc/kern/print.h Normal file
View File

@ -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);

27
inc/kern/spin_lock.h Normal file
View File

@ -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);

14
inc/kern/status.h Normal file
View File

@ -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
};

View File

@ -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);

View File

@ -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)

36
inc/test/ktest.h Normal file
View File

@ -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);

11
kern/CMakeLists.txt Normal file
View File

@ -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)

462
kern/avl_tree.c Normal file
View File

@ -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);
}

35
kern/kmain.c Normal file
View File

@ -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");
}

147
kern/libkern.c Normal file
View File

@ -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);
}
}

159
kern/print.c Normal file
View File

@ -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;
}

60
kern/spin_lock.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -1,12 +0,0 @@
#pragma once
#include "cdef.h"
void
ke_alloc_init(void);
void *
ke_alloc(uint32 size);
void
ke_free(void *ptr);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -1,6 +0,0 @@
#pragma once
#include "cdef.h"
void
ke_panic(uint32 reason);

View File

@ -1,9 +0,0 @@
#pragma once
#include "cdef.h"
void
ke_printf(const char *str, ...);
void
ke_vprintf(const char *str, va_list args);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}
}
}

View File

@ -1,7 +0,0 @@
include $(MK)/prologue.mk
SRC_$(d) := $(d)/pmm.c
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -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;
}

View File

@ -1,7 +0,0 @@
include $(MK)/prologue.mk
SRC_$(d) := $(d)/ref.c
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -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;
}

Some files were not shown because too many files have changed in this diff Show More