Compare commits

...

69 Commits

Author SHA1 Message Date
quackerd e296655010 Update '.drone.yml' 2022-06-19 14:08:29 +00:00
quackerd 2bdb8dae04 update drone 2020-06-02 06:39:47 +00:00
quackerd 42d2c1383e update drone 2020-06-02 06:38:38 +00:00
quackerd 07d1bc7f6f Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-23 09:12:52 +00:00
quackerd b79cd6b1d6 Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-23 09:03:55 +00:00
quackerd 3f717e476e
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 05:00:36 -04:00
quackerd af324eefd4
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 04:53:13 -04:00
quackerd cf99debcb4
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 04:50:46 -04:00
quackerd 35215486ec
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 04:45:55 -04:00
quackerd c471a67090 Merge branch 'master' of ssh://git.quacker.org/d/bond 2020-04-23 04:44:55 -04:00
quackerd 0ff3954be7
drone CI 2020-04-23 04:44:38 -04:00
quackerd 0327c24b11 Update 'LICENSE'
continuous-integration/drone/push Build is passing Details
2020-04-23 07:30:44 +00:00
quackerd b71c7ea715 Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-23 07:26:17 +00:00
quackerd a7fa953214 Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-23 07:25:08 +00:00
quackerd a578e85ba0 Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-23 07:24:39 +00:00
quackerd 7e1e301005
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 02:23:41 -04:00
quackerd d80d1dabcd
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-23 02:07:49 -04:00
quackerd 93dae7a29d Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-22 21:24:40 +00:00
quackerd 7560c06c0c Update 'README.md'
continuous-integration/drone/push Build is passing Details
2020-04-22 21:22:44 +00:00
quackerd 4a72667a0f
drone CI
continuous-integration/drone/push Build is passing Details
2020-04-22 16:48:07 -04:00
quackerd 9fa56f89e9 Merge branch 'working' 2019-12-07 03:56:34 -05:00
quackerd 4424d6401e
multiboot stuff 2019-12-07 03:54:18 -05:00
quackerd 4047de21ad Update 'README.md' 2019-11-28 18:18:47 +00:00
quackerd b0ad3eba32 Update 'README.md' 2019-11-28 18:18:09 +00:00
quackerd 7f880a403a Update 'README.md' 2019-11-28 18:16:58 +00:00
quackerd 747e6b9825 Update 'README.md' 2019-11-28 18:13:04 +00:00
quackerd acc6ba7601 Merge branch 'working' of d/bond into master 2019-11-28 18:04:56 +00:00
quackerd 18830d645a
refactoring complete 2019-11-28 13:02:52 -05:00
QuackeR d9e3e91109
merge 2019-06-26 01:54:40 -04:00
QuackeR 5a7bf472d8
compiling 2019-06-26 01:47:18 -04:00
QuackeR a918d405bb Update README.md 2019-05-28 18:49:59 +00:00
QuackeR c499ac6355 Update README.md 2019-05-28 18:24:53 +00:00
op52 10ebd0e3b9
cmt 2018-12-19 08:33:23 +08:00
Op52 548852f8be
working 2018-12-16 18:52:33 -05:00
Op52 8df0a67f9a Merge branch 'working' of ssh://github.com/op52/ukern into working 2018-12-05 05:51:42 -05:00
nt0s 8e7c1cf6a2 Debloat 2018-11-20 23:00:45 -05:00
nt0s 96f3b9f0d5 haha 2018-11-20 22:44:33 -05:00
nt0s e1985db58e change llvm objdump 2018-11-15 06:34:22 -05:00
nt0s 04d0168072 change objdump 2018-11-15 06:29:59 -05:00
secXsQuared 6a32f03f20 asdfasdf 2018-10-28 22:11:43 -04:00
secXsQuared 807ac4de22 + Parse multiboot_info
+ Fix multiboot_info NULL in hmain() bug
- Time to read some papers and rethink the desig
2018-10-10 03:51:09 -04:00
secXsQuared 34949452db + Set up intital page mapping to support high address
+ Add multiboot framebuffer request tag
+ Cleaned up some code
2018-10-09 15:13:31 -04:00
secXsQuared eb33f2c35c setup qemu + VNC + monitor + gdb on WSL 2018-10-04 01:02:33 -04:00
secXsQuared 5a001169cb change qemu options 2018-10-02 16:11:32 -04:00
secXsQuared 73458d7f60 Finally compiles after refactoring.. 2018-10-02 02:43:30 -04:00
secXsQuared 48388bbf01 new branch for shit 2018-10-01 13:01:00 -04:00
secXsQuared 798b3b0454 Getting rid of qemu boot files. 2018-08-23 00:10:23 +08:00
secXsQuared 5c30ace8db Added test case for pop back and pop front value check. 2018-03-29 06:50:02 -04:00
secXsQuared 83f3159b9a Added a test case to linked list 2018-03-29 06:21:34 -04:00
secXsQuared a2367a4a8e Merge branch 'master' of ssh://github.com/secxsquared/secx 2018-03-29 06:00:26 -04:00
secXsQuared 5a3f9e3419 - Got rid of bogus callback_func
- Refactored linked list interface.
- Fixed all test cases and made them standalone instead of within the kernel.
2018-03-29 06:00:22 -04:00
secXsQuared cae1da17c4
Update README.md 2018-03-23 21:05:34 -04:00
secXsQuared 4fdc39c39b
Update README.md 2018-03-23 21:05:20 -04:00
secXsQuared 2f680a5f83
Update README.md 2018-03-23 21:03:31 -04:00
secXsQuared 3fb0c6e5a6 switched to llvm 2018-03-23 20:58:24 -04:00
secXsQuared 0460c68628 KABI -> SXAPI 2018-02-18 02:48:59 -05:00
secXsQuared 1a506a754b Getting rid of an evil flag. 2018-02-18 02:14:38 -05:00
secXsQuared a3c68c6399 objdump only executable sections 2018-02-18 01:46:23 -05:00
secXsQuared 982d30f623 Change linker from gcc to ld. 2018-02-18 01:14:25 -05:00
secXsQuared f9a98cb574 update readme 2018-02-17 23:53:25 -05:00
secXsQuared 72e234e46c Update readme 2018-02-17 23:51:51 -05:00
secXsQuared ce4a8675e6 Update README.md 2018-02-17 23:50:22 -05:00
secXsQuared dc54e6a498 Update README.md 2018-02-17 23:38:23 -05:00
secXsQuared c3c2a875f3 Update README.md 2018-02-17 23:23:17 -05:00
secXsQuared c06b131b21 Update README.md 2018-02-17 23:22:46 -05:00
secXsQuared 0988ae8baf Space to Tab 2018-02-17 23:06:57 -05:00
secXsQuared 362f3d0ce8 Delete extra file 2018-02-17 23:01:37 -05:00
secXsQuared a64afda294 - Removed bogus 32-bit and 64-bit mixed hal entrance. The new entrance is ke_main.
- Removed grub dependency.
2018-02-17 23:00:54 -05:00
secXsQuared 7a297165fc
Update README.md 2018-02-16 23:44:48 -05:00
131 changed files with 4296 additions and 8093 deletions

41
.drone.yml Normal file
View File

@ -0,0 +1,41 @@
kind: pipeline
type: docker
name: default
trigger:
branch:
- master
event:
exclude:
- cron
steps:
- name: build
image: quackerd/fedora:latest
commands:
- mkdir build
- cd build
- cmake ../
- make
---
kind: pipeline
type: docker
name: docker-update
trigger:
event:
- cron
cron:
- weekly
steps:
- name: docker-update
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: quackerd/fedora
tags: latest

2
.gitignore vendored
View File

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

141
CMakeLists.txt Normal file
View File

@ -0,0 +1,141 @@
cmake_minimum_required(VERSION 3.10)
# disable in-source build
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
project(bond)
set(proj bond)
set(INC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
set(MK ${CMAKE_CURRENT_SOURCE_DIR}/mk)
set(arch amd64)
include(${MK}/${arch}.cmake)
# sanity check
set(TOOLCHAINS
AS
CC
GRUB
LD
DMP)
FOREACH(f IN LISTS TOOLCHAINS)
if(NOT ${f})
message(FATAL_ERROR "Toolchain ${f} cannot be found.")
endif()
endforeach(f)
set(CC_WARN_IGNORE
-Wno-gnu-statement-expression # this means we can assign the return val of the last statment in a block, useful in MAX, MIN, etc.
-Wno-gnu-zero-variadic-macro-arguments # this enables us to use __VA_ARGS__ in macros
)
set(CC_FLAGS
-std=c17
-c
-g
-O0
-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
-Wl,--build-id=none
${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
# Rules for generating the image
set(TARGET ${proj}_elf)
set(OBJ_${TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${proj}.elf)
add_custom_command(
OUTPUT ${OBJ_${TARGET}}
DEPENDS ${TARGETS} ${OBJS}
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
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()

3
Dockerfile Normal file
View File

@ -0,0 +1,3 @@
FROM fedora:latest
RUN dnf install -y cmake make clang nasm xorriso lld grub2-pc-modules grub2-tools-extra
CMD ["/bin/sh"]

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 secXsQuared
Copyright (c) 2020 quackerd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,77 +0,0 @@
CROSS_DIR = ~/opt/cross/bin
AS = nasm
CC = $(CROSS_DIR)/x86_64-elf-gcc
LD = $(CROSS_DIR)/x86_64-elf-gcc
DAS = $(CROSS_DIR)/x86_64-elf-objdump
INCLUDE_DIR = include
MK = mk
OUT = out
C_WARNINGS = -Wall \
-Werror \
-Wextra \
-Wpedantic \
-Winit-self \
-Wunused-parameter \
-Wuninitialized \
-Wfloat-equal \
-Wshadow \
-Wcast-qual \
-Wcast-align \
-Wstrict-prototypes \
-Wpointer-arith \
-Wno-comment
C_FLAGS = -std=c11 \
-g \
-c \
-O2 \
-mcmodel=kernel \
-fno-exceptions \
-ffreestanding \
-mno-red-zone \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-masm=intel \
$(C_WARNINGS) \
$(addprefix -I, $(INCLUDE_DIR))
AS_FLAGS = -w+all \
-w+error \
-f elf64 \
-F dwarf \
-g \
$(addprefix -I, $(INCLUDE_DIR)/)
LD_FLAGS = -lgcc \
-nodefaultlibs \
-nostartfiles \
-nostdlib \
-mno-red-zone \
-Wl,-n \
-Wl,--build-id=none
DUMP_FLAGS = -M intel \
-D
PREP_FLAGS = -E \
-x c \
-P \
-traditional-cpp \
$(C_FLAGS)
GDEP_FLAGS = $(PREP_FLAGS) \
-MMD \
-MT $@
MKDIR = mkdir -p $(dir $@)
COMP = $(CC) $(C_FLAGS) $< -o $@
COMPAS = $(AS) $(AS_FLAGS) $< -o $@
LINK = $(LD) $(LD_FLAGS) $^ -o $@
DUMP = $(DAS) $(DUMP_FLAGS) $< > $@
PREP = $(CC) $(PREP_FLAGS) $< > $@
GDEP = $(CC) $(GDEP_FLAGS) -MF $(addsuffix .d, $@) $< > /dev/null
include Rules.top

View File

@ -1,43 +1,66 @@
My Hobby x86-64 OS kernel.
[![Build Status](https://ci.quacker.org/api/badges/d/bond/status.svg)](https://ci.quacker.org/d/bond)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
# Building
### Environment
Any Linux distribution / Bash for Windows + GCC cross compiler.
### Required packages
To compile the kernel, the following modules are required on linux system, please install these:
nasm, xorriso, grub-common, grub-pc-bin
### Cross-compiler
##### Method 1 - Compile one yourself.
Just follow the instructions here: https://wiki.osdev.org/GCC_Cross-Compiler
Remember to set the "TARGET" to x86_64-elf instead of i686-elf and build libgcc without redzone https://wiki.osdev.org/Libgcc_without_red_zone.
##### Method 2 - Precompiled binaries
Here is my precompiled cross compiler. Feel free to use it.
VERSION: GCC 7.3 + Binutils 2.30
HOST: x86_64-pc-linux-gnu
CONFIGURED WITH: --target=x86_64-elf --disable-nls --enable-languages=c,c++ --without-headers
1. Download "cross.tar.gz" from the release page.
2. Run "tar -xvf cross.tar.gz -C $HOME/opt/cross"
Fedora: dnf install -y cmake make clang nasm xorriso lld grub2-pc-modules grub2-tools-extra
### Compiling
Run "make all" in the root directory
mkdir build
The makefile generates secxkrnl.iso (kernel image), secxkrnl.elf(kernel executable), secxkrnl.dmp(kernel disassembly) at the end.
cd build
To clean all generated files, run "make clean"
cmake ../
make
# Running
On windows run "qemu.bat"
Load the iso with QEMU/your favorite simulator.
On linux run "./qemu.bat"
# C vs 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. Especially while enforcing "modern" C++, sometimes I find myself struggling more with the language itself than getting work done. **I have had lengthy thoughts myself regarding C++ but decided to drop it**. Here are some of the pros and cons I came up with.
## Good features
### 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. Update: this might not be true after trying to implement type safe in-place linked list in C++. I feel like template is just as inelegant for that.
### namespace
Oh boy how I wish C standard would include namespace, if it weren't for backward compaibility and stable ABI.
### Ownership management
But rust did better?
## Banned features (tentative)
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 bond.

View File

@ -1,55 +0,0 @@
include $(MK)/prologue.mk
.DEFAULT_GOAL := all
#OBJ var holds all object files
dir := hal
include $(dir)/Rules.mk
dir := kernel
include $(dir)/Rules.mk
dir := lib
include $(dir)/Rules.mk
dir := test
include $(dir)/Rules.mk
dir := mk
include $(dir)/Rules.mk
LD_SCRIPT = $(OUT)/$(MK)/linker.ld
GRUB_CFG = $(OUT)/$(MK)/grub.cfg
TGT := $(OUT)/secxkrnl.elf
DMP := $(OUT)/secxkrnl.dmp
ISO := $(OUT)/secxkrnl.iso
$(TGT): $(OBJ) $(LD_SCRIPT)
$(LD) $(LD_FLAGS) -print-libgcc-file-name
$(LINK) -T $(LD_SCRIPT)
$(DMP): $(TGT)
$(DUMP)
.PHONY: clean
clean:
rm -f $(CLEAN) $(TGT) $(DMP) $(ISO)
find $(OUT) -empty -type d -delete
.PHONY: compile
compile: $(TGT)
.PHONY: dump
dump: $(DMP)
.PHONY: iso
iso: $(TGT) $(GRUB_CFG)
mkdir -p temp/secX
mkdir -p temp/boot
mkdir -p temp/boot/grub
cp $(TGT) temp/secX/
cp $(GRUB_CFG) temp/boot/grub/
grub-mkrescue -o $(ISO) temp
rm -r temp
.PHONY: all
all: compile dump 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
main.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)

189
arch/boot.asm Normal file
View File

@ -0,0 +1,189 @@
#define ASM_FILE
#include <arch/mlayout.h>
#include "multiboot2.h"
%define BOCHS_BREAK xchg bx, bx
%define GET_PADDR(x) ((x) - KERN_BASE_START)
%define GET_PML4(vaddr) (((vaddr) >> 39 ) & 0x1FF)
%define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF)
%define GET_PDE(vaddr) (((vaddr) >> 21 ) & 0x1FF)
; make arch_init_32 visiable
global arch_init_32
; arch_main is the C long mode entry point
extern arch_main
section .text
bits 32
; the bootloader calls this dude, we switch to long mode with some basic setup:
; Identity map the first 4G memory, where the kernel binary and multiboot info is
; Map the first 4G memory to KERN_PMAP temporarily so we have access to printf
; Map the first 1G memory, which contains the kernel, to KERN_BASE_START
arch_init_32:
cli ; close interrupt
cld ; set direction
cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC ; compare with multiboot2 magic
jne .end ; if not loaded by multiboot2 compliant bootloader, loop infinitely
BOCHS_BREAK
; save multiboot info
mov dword [GET_PADDR(multiboot_info_ptr)], ebx
; disable paging first
mov eax, cr0 ; Set the A-register to control register 0.
and eax, ~(1 << 31) & 0xFFFFFFFF ; Clear the PG-bit, which is bit 31, and hack to get rid of warning
mov cr0, eax ; Set control register 0 to the A-register.
; identity map the first 4G page
mov eax, GET_PADDR(kern_early_pml4)
add eax, GET_PML4(0) * 8 ; eax = offset of pml4e in pml4 for the 0th GB
mov dword [eax], GET_PADDR(kern_early_ident_pdpt) + 11b ; let the corresponding pml4e point to the kern_early_ident_pdpt
mov eax, GET_PADDR(kern_early_ident_pdpt)
add eax, GET_PDPT(0) * 8
mov ebx, 10000011b ; ebx lower bits is attribute = R/W + SU + 1G page, high bits = physical 0th GB
mov ecx, 4 ; 4 times = 4GB
.l0:
mov dword [eax], ebx ; set the corresponding pdpte to map 1GB pages in ebx
add ebx, 1*1024*1024*1024 ; add another 1G to ebx higher bits
add eax, 8 ; increment to next pdpte
loop .l0
; map the first 4G to pmap
mov eax, GET_PADDR(kern_early_pml4)
add eax, GET_PML4(KERN_PMAP_START) * 8 ; eax = offset of pml4e in pml4 for PMAP region
mov dword [eax], GET_PADDR(kern_early_pmap_pdpt) + 11b ; let the corresponding pml4e point to the kern_early_pmap_pdpt
mov eax, GET_PADDR(kern_early_pmap_pdpt)
add eax, GET_PDPT(KERN_PMAP_START) * 8
mov ebx, 10000011b ; ebx lower bits is attribute = R/W + SU + 1G page, high bits = physical 0th GB
mov ecx, 4 ; 4 times = 4GB
.l1:
mov dword [eax], ebx ; set the corresponding pdpte to map 1GB pages in ebx
add ebx, 1*1024*1024*1024 ; add another 1G to ebx higher bits
add eax, 8 ; increment to next pdpte
loop .l1
; map the first 1G to kern_base
; point the first PML4 entry to the identity pdpt
mov eax, GET_PADDR(kern_early_pml4)
add eax, GET_PML4(KERN_BASE_START) * 8
mov dword [eax], GET_PADDR(kern_early_img_pdpt) + 11b ; let the corresponding pml4e point to the kern_early_img_pdpt
mov eax, GET_PADDR(kern_early_img_pdpt)
add eax, GET_PDPT(KERN_BASE_START) * 8
mov dword [eax], 10000011b ; ebx lower bits is attribute = R/W + SU + 1G page, high bits = physical 0th GB
BOCHS_BREAK
; enable PAE
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
; enable long mode
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
rdmsr ; Read from the model-specific register.
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
wrmsr ; Write to the model-specific register.
; let cr3 point at page table
mov eax, GET_PADDR(kern_early_pml4)
mov cr3, eax
xchg bx, bx
; enable paging, enter compatibility mode
mov eax, cr0 ; Set the A-register to control register 0.
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
; now we are in compat mode
; load the long mode GDT
lgdt [GET_PADDR(kern_early_gdt.ptr)]
; switch to long mode
jmp kern_early_gdt.code:GET_PADDR(arch_init_64)
; should not reach this point
.end:
jmp $
section .data
bits 32
multiboot_info_ptr:
dd 0
section .text
bits 64
arch_init_64:
; note that we are in long mode but rip is still lower
; switch to high address
mov rax, .high
jmp rax
.high:
; set proper segment registers
mov ax,kern_early_gdt.data
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
; initial kernel stack, 4k
mov rsp, kern_early_stack
xor rdi, rdi
mov edi, dword [multiboot_info_ptr]
; init arch
call arch_main
; should not reach this point
jmp $
section .data
bits 64
align 0x1000
times KERN_PAGE_SZ db 0
kern_early_stack:
align 0x1000
kern_early_pml4:
times 0x1000 db 0
align 0x1000
kern_early_ident_pdpt:
times 0x1000 db 0
align 0x1000
kern_early_pmap_pdpt:
times 0x1000 db 0
align 0x1000
kern_early_img_pdpt:
times 0x1000 db 0
kern_early_gdt: ; Global Descriptor Table (long mode).
.null: equ $ - kern_early_gdt ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.code: equ $ - kern_early_gdt ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011010b ; Access (exec/read).
db 00100000b ; Granularity.
db 0 ; Base (high).
.data: equ $ - kern_early_gdt ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access (read/write).
db 00000000b ; Granularity.
db 0 ; Base (high).
.ptr:
; GDT PTR
dw $ - kern_early_gdt - 1 ; Limit.
dq GET_PADDR(kern_early_gdt) ; Base.

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,7 +1,3 @@
; Copyright 2016 secXsQuared
; Distributed under GPL license
; See COPYING under root for details
%macro PUSHAQ 0
push rax ;save current rax
push rbx ;save current rbx
@ -29,7 +25,7 @@
pop r10 ;restore current r10
pop r9 ;restore current r9
pop r8 ;restore current r8
pop rsi ;restore current rsi
pop rsi ;restore current rsix
pop rdi ;restore current rdi
pop rbp ;restore current rbp
pop rdx ;restore current rdx
@ -77,6 +73,7 @@ hal_interrupt_handler_%1:
; +0 RBP
push rbp
mov rbp,rsp
PUSHAQ
cld
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);
}

47
arch/main.c Normal file
View File

@ -0,0 +1,47 @@
#include <kern/cdef.h>
#include <kern/print.h>
#include <arch/print.h>
#include <arch/brute.h>
// private headers
#include "multiboot2.h"
ATTR_USED void
arch_main(void *mb_info)
{
/* init printf related stuff */
arch_print_init();
kprintf("Multiboot info: 0x%p\n", mb_info);
kprintf("Initializing arch layer...\n");
for (struct multiboot_tag *tag = (struct multiboot_tag *) ((uintptr) mb_info + 8);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag
+ ((tag->size + 7) & ~7u))) {
kprintf("Tag 0x%p: %d, Size %d\n", (void *) tag, tag->type, tag->size);
switch (tag->type) {
case MULTIBOOT_TAG_TYPE_MMAP:
for (struct multiboot_mmap_entry *entry = ((struct multiboot_tag_mmap *) tag)->entries;
(multiboot_uint8_t *) entry < (multiboot_uint8_t *) tag + tag->size;
entry = (multiboot_memory_map_t *) ((uintptr) entry +
((struct multiboot_tag_mmap *) tag)->entry_size))
kprintf(" base_addr = 0x%lx,"
" length = 0x%lx, type = 0x%x\n",
(ulong) entry->addr,
(ulong) entry->len,
entry->type);
break;
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
kprintf("BoND is loaded by: %s\n", ((struct multiboot_tag_string *) tag)->string);
break;
default:
kprintf("Unhandled multiboot tag type: %d\n", tag->type);
break;
}
}
kprintf("Arch layer initialized.\n");
arch_brute();
}

44
arch/mb_hdr.asm Normal file
View File

@ -0,0 +1,44 @@
#define ASM_FILE
#include "multiboot2.h"
#include <arch/mlayout.h>
ASM_MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + ASM_MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCHITECTURE_I386) + 1)
section .multiboot_header
bits 32
align 0x1000
;====================
align MULTIBOOT_HEADER_ALIGN
start_hdr:
dd MULTIBOOT2_HEADER_MAGIC
dd MULTIBOOT_ARCHITECTURE_I386
dd ASM_MULTIBOOT_HEADER_SIZE
dd ASM_MULTIBOOT_CHECK_SUM
;====================
align MULTIBOOT_INFO_ALIGN
dw MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
dw 0 ; flag
dd (8+4*3) ; size
dd MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
dd MULTIBOOT_TAG_TYPE_MMAP
dd MULTIBOOT_TAG_TYPE_ACPI_NEW
;====================
align MULTIBOOT_INFO_ALIGN
dw MULTIBOOT_HEADER_TAG_FRAMEBUFFER; type=5
dw 0 ; flag
dw 20 ; size
dd 0 ; width
dd 0 ; depth
dd 0 ; height
;====================
align MULTIBOOT_INFO_ALIGN
dw MULTIBOOT_HEADER_TAG_MODULE_ALIGN; type=6
dw 0 ; flag
dd 8 ; size
;====================
align MULTIBOOT_INFO_ALIGN
dw MULTIBOOT_HEADER_TAG_END
dw 0 ; flag
dd 8 ; size
;====================
ASM_MULTIBOOT_HEADER_SIZE equ ($ - start_hdr)

66
arch/mem.c Normal file
View File

@ -0,0 +1,66 @@
#include <kern/cdef.h>
#include <arch/mem.h>
#include <arch/mlayout.h>
/**
Page Table Definitions
**/
#define PML4_PRESENT (1ull << 0)
#define PML4_WRITE (1ull << 1)
#define PML4_USER (1ull << 2)
#define PML4_WRITE_THROUGH (1ull << 3)
#define PML4_CACHE_DISABLED (1ull << 4)
#define PML4_ACCESSED (1ull << 5)
#define PML4_EXECUTION_DISABLED (1ull << 63)
#define PDPT_PRESENT (1ull << 0)
#define PDPT_WRITE (1ull << 1)
#define PDPT_USER (1ull << 2)
#define PDPT_WRITE_THROUGH (1ull << 3)
#define PDPT_CACHE_DISABLED (1ull << 4)
#define PDPT_ACCESSED (1ull << 5)
#define PDPT_EXECUTION_DISABLED (1ull << 63)
#define PD_PRESENT (1ull << 0)
#define PD_WRITE (1ull << 1)
#define PD_USER (1ull << 2)
#define PD_WRITE_THROUGH (1ull << 3)
#define PD_CACHE_DISABLED (1ull << 4)
#define PD_ACCESSED (1ull << 5)
#define PD_EXECUTION_DISABLED (1ull << 63)
#define PT_PRESENT (1ull << 0)
#define PT_WRITE (1ull << 1)
#define PT_USER (1ull << 2)
#define PT_WRITE_THROUGH (1ull << 3)
#define PT_CACHE_DISABLED (1ull << 4)
#define PT_ACCESSED (1ull << 5)
#define PT_DIRTY (1ull << 6)
#define PT_ATTRIBUTE_TABLE (1ull << 7)
#define PT_GLOBAL (1ull << 8)
#define PT_EXECUTION_DISABLED (1ull << 63)
#define PML4_ENTRY_NUM(vaddr) (((vaddr) >> 39) & 0x1FF)
#define PDPT_ENTRY_NUM(vaddr) (((vaddr) >> 30) & 0x1FF)
#define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF)
#define PT_ENTRY_NUM(vaddr) (((vaddr) >> 12) & 0x1FF)
void
write_page_tbl(void *base, uintptr pdpt_addr, uint64 attr)
{
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);
}

View File

@ -19,8 +19,7 @@
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _HAL_MULTIBOOT_H_
#define _HAL_MULTIBOOT_H_
#pragma once
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 32768
@ -111,7 +110,7 @@ struct multiboot_header_tag_information_request
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t requests[0];
multiboot_uint32_t requests[];
};
struct multiboot_header_tag_address
@ -189,7 +188,7 @@ struct multiboot_tag_string
{
multiboot_uint32_t type;
multiboot_uint32_t size;
char string[0];
char string[];
};
struct multiboot_tag_module
@ -198,7 +197,7 @@ struct multiboot_tag_module
multiboot_uint32_t size;
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
char cmdline[0];
char cmdline[];
};
struct multiboot_tag_basic_meminfo
@ -224,7 +223,7 @@ struct multiboot_tag_mmap
multiboot_uint32_t size;
multiboot_uint32_t entry_size;
multiboot_uint32_t entry_version;
struct multiboot_mmap_entry entries[0];
struct multiboot_mmap_entry entries[];
};
struct multiboot_vbe_info_block
@ -277,7 +276,7 @@ struct multiboot_tag_framebuffer
struct
{
multiboot_uint16_t framebuffer_palette_num_colors;
struct multiboot_color framebuffer_palette[0];
struct multiboot_color framebuffer_palette[];
};
struct
{
@ -298,7 +297,7 @@ struct multiboot_tag_elf_sections
multiboot_uint32_t num;
multiboot_uint32_t entsize;
multiboot_uint32_t shndx;
char sections[0];
char sections[];
};
struct multiboot_tag_apm
@ -337,28 +336,28 @@ struct multiboot_tag_smbios
multiboot_uint8_t major;
multiboot_uint8_t minor;
multiboot_uint8_t reserved[6];
multiboot_uint8_t tables[0];
multiboot_uint8_t tables[];
};
struct multiboot_tag_old_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
multiboot_uint8_t rsdp[];
};
struct multiboot_tag_new_acpi
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t rsdp[0];
multiboot_uint8_t rsdp[];
};
struct multiboot_tag_network
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint8_t dhcpack[0];
multiboot_uint8_t dhcpack[];
};
struct multiboot_tag_efi_mmap
@ -367,9 +366,7 @@ struct multiboot_tag_efi_mmap
multiboot_uint32_t size;
multiboot_uint32_t descr_size;
multiboot_uint32_t descr_vers;
multiboot_uint8_t efi_mmap[0];
multiboot_uint8_t efi_mmap[];
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

62
arch/print.c Normal file
View File

@ -0,0 +1,62 @@
#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));
// clear the last line
memset(base + (FB_ROW - 1) * FB_COL * BYTE_PER_CHAR, 0, 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;
}

57
bochsrc Normal file
View File

@ -0,0 +1,57 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, iodebug=1
config_interface: textconfig
display_library: x, options="gui_debug"
memory: host=256, guest=256
romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x0, options=none
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: cdrom
floppy_bootsig_check: disabled=0
# no floppya
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=none
ata0-slave: type=cdrom, path="bond.iso", status=inserted, model="Generic 1234", biosdetect=auto
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=0
ata3: enabled=0
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5, realtime=1
cpu: count=1:1:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor"
cpuid: mmx=1, apic=x2apic, simd=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0
cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, x86_64=1, 1g_pages=1, pcid=0, fsgsbase=0
cpuid: smep=0, smap=0, mwait=1
print_timestamps: enabled=0
debugger_log: -
magic_break: enabled=1
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
# no loader
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=0, toggle=ctrl+mbutton
speaker: enabled=1, mode=system
parport1: enabled=1, file=none
parport2: enabled=0
com1: enabled=1, mode=null
com2: enabled=0
com3: enabled=0
com4: enabled=0

View File

@ -1,25 +0,0 @@
include $(MK)/prologue.mk
SRC_$(d) := $(d)/boot.c \
$(d)/intr.c \
$(d)/mem.c \
$(d)/print.c
SRCAS_$(d) := $(d)/cpu.asm \
$(d)/intr.asm
SRCIN_$(d) := $(d)/boot.asm.in
#special rules for boot.asm
#no dependencies for ASM objects
$(OUT)/$(d)/boot.a: $(OUT)/$(d)/boot.asm
$(MKDIR)
$(COMPAS)
OBJ := $(OBJ) $(OUT)/$(d)/boot.a
CLEAN := $(CLEAN) $(OUT)/$(d)/boot.a
# include this at last
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -1,216 +0,0 @@
#define ASM_FILE
#include "kernel/hal/mem.h"
#include "hal/multiboot2.h"
%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR + KERNEL_IMAGE_PADDR)
%define BOCHS_BREAK xchg bx,bx
extern hal_main
extern hal_write_initial_page_table
global hal_entry_32
section .multiboot_header
bits 32
MULTIBOOT_ARCH equ 0
MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH) + 1)
MULTIBOOT_REQ_LOADERNAME equ 2
MULTIBOOT_REQ_MMAP equ 6
MULTIBOOT_REQ_ACPI_RSDP equ 15
;====================
;header tag
align MULTIBOOT_HEADER_ALIGN
multiboot_header_tag:
dd MULTIBOOT2_HEADER_MAGIC
dd MULTIBOOT_ARCH
dd MULTIBOOT_HEADER_SIZE
dd MULTIBOOT_CHECK_SUM
;====================
;INFO_REQUEST_TAG
align MULTIBOOT_INFO_ALIGN
multiboot_info_tag:
dw 0x1 ; type=1
dw 0x0 ; flag=0
dd MULTIBOOT_INFO_TAG_SIZE
dd MULTIBOOT_REQ_LOADERNAME
dd MULTIBOOT_REQ_MMAP
MULTIBOOT_INFO_TAG_SIZE equ ($ - multiboot_info_tag)
;====================
;MODULE ALIGNMENT TAG
align MULTIBOOT_INFO_ALIGN
dw 0x6; type=6
dw 0x0; flag=0
dd 0x8
;====================
align MULTIBOOT_INFO_ALIGN
;End_tag
dw 0x0
dw 0x0
dd 0x8
;====================
MULTIBOOT_HEADER_SIZE equ ($ - multiboot_header_tag)
section .text
bits 32
align KERNEL_PAGE_SIZE
hal_entry_32:
cli
cld
cmp eax,MULTIBOOT2_BOOTLOADER_MAGIC
je .loaded_by_grub
hlt
.loaded_by_grub:
; save multiboot_info*
mov esi,ebx
call halp_check_long_mode
cmp eax,1
je .init_long_mode
hlt
.init_long_mode:
; disable paging first
mov eax, cr0 ; Set the A-register to control register 0.
and eax, 0x7FFFFFFF ; Clear the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
; identity map the first 4GB
; ATTRIBUTE = READ/WRITE + SU
mov eax, GET_PADDR(_pml4)
mov dword [eax], GET_PADDR(_pdpt) + 11b
; write values for pdpt
mov ecx, 10000011b
mov eax, GET_PADDR(_pdpt)
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
add eax,8
add ecx,0x40000000 ;1G
mov dword [eax], ecx
BOCHS_BREAK
; enable PAE
mov eax, cr4 ; Set the A-register to control register 4.
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
mov cr4, eax ; Set control register 4 to the A-register.
; enable long mode
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
rdmsr ; Read from the model-specific register.
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
wrmsr ; Write to the model-specific register.
; let cr3 point at page table
mov eax, GET_PADDR(_pml4)
mov cr3, eax
; enable paging, enter compatibility mode
mov eax, cr0 ; Set the A-register to control register 0.
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
mov cr0, eax ; Set control register 0 to the A-register.
; enter long mode
lgdt [GET_PADDR(_gdt.ptr)]
jmp _gdt.code:GET_PADDR(halp_entry_64)
hlt
halp_check_long_mode:
push ebp
mov ebp,esp
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz .not_supported
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb .not_supported ; It is less, there is no long mode.
mov eax, 0x80000001 ; Set the A-register to 0x80000001.
cpuid ; CPU identification.
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
jz .not_supported ; They aren't, there is no long mode.
mov eax,1
jmp .end
.not_supported:
xor eax,eax
.end:
mov esp,ebp
pop ebp
ret
section .text
bits 64
halp_entry_64:
; note that we are still at the identity mapping
mov ax,_gdt.data
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov rsp, GET_PADDR(_stack)
mov rdi, rsi ; multiboot_info*
call hal_write_initial_page_table
test rax,rax
jne .end
call hal_main
.end:
hlt
section .data
bits 64
align KERNEL_PAGE_SIZE
times 4096 db 0
_stack:
_pml4:
align KERNEL_PAGE_SIZE
times 4096 db 0
_pdpt:
align KERNEL_PAGE_SIZE
times 4096 db 0
_gdt: ; Global Descriptor Table (long mode).
.null: equ $ - _gdt ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.code: equ $ - _gdt ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011010b ; Access (exec/read).
db 00100000b ; Granularity.
db 0 ; Base (high).
.data: equ $ - _gdt ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access (read/write).
db 00000000b ; Granularity.
db 0 ; Base (high).
.ptr:
; GDT PTR
dw $ - _gdt - 1 ; Limit.
dq GET_PADDR(_gdt) ; Base.

View File

@ -1,50 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#include "hal/print.h"
#include "hal/mem.h"
#include "hal/intr.h"
#include "hal/cpu.h"
#include "lib/sxtdlib.h"
#include "hal/boot.h"
static void KABI halp_obtain_cpu_info(boot_info_t *hal_info)
{
if(hal_info == NULL)
return;
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
hal_cpuid(&eax,&ebx,&ecx,&edx);
lb_mem_copy(&ebx, &hal_info->cpu_vd_str[0], sizeof(uint32_t));
lb_mem_copy(&edx, &hal_info->cpu_vd_str[4], sizeof(uint32_t));
lb_mem_copy(&ecx, &hal_info->cpu_vd_str[8], sizeof(uint32_t));
hal_info->cpu_vd_str[12] = 0;
}
void KABI hal_main(void *m_info)
{
if (m_info == NULL || (uint64_t) m_info & lb_bit_field_mask(0, 2))
return;
// init HAL infrastructures
hal_print_init();
hal_mem_init();
boot_info_t* boot_info = halloc(sizeof(boot_info_t));
boot_info->krnl_end = KERNEL_IMAGE_END_VADDR;
// obtain cpu info
halp_obtain_cpu_info(boot_info);
// init interrupt
if(hal_interrupt_init() != 0)
{
return;
}
// pass the control to the kernel
ke_main(boot_info);
return;
}

View File

@ -1,256 +0,0 @@
; Copyright 2016 secXsQuared
; Distributed under GPL license
; See COPYING under root for details
;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
[SECTION .text]
[BITS 64]
;======================
global hal_flush_gdt
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
;======================
global hal_flush_tlb
;void flush_tlb(void)
hal_flush_tlb:
mov rax,cr3
mov cr3,rax
ret
;======================
global hal_flush_idt
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
; ============================
; int32_t KAPI hal_interlocked_exchange_32(int32_t *target, int32_t val)
global hal_interlocked_exchange_32
hal_interlocked_exchange_32:
lock xchg dword [rdi], esi
xor rax, rax
mov eax, esi
ret
; ============================
; int32_t KAPI hal_interlocked_compare_exchange_32(int32_t *dst, int32_t compare, int32_t val);
global hal_interlocked_compare_exchange_32
hal_interlocked_compare_exchange_32:
mov eax, esi; eax = compare
lock cmpxchg dword [rdi], edx ; edx = val, rdi = ptr to dst
ret
; ============================
; int32_t KAPI hal_interlocked_increment_32(int32_t *target, int32_t 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
; ============================
; extern void KAPI hal_cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* 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_write_port_32
hal_write_port_32:
mov rdx,rdi
mov rax,rsi
out dx,eax
nop
nop
nop
ret
;====================
global hal_write_port_16
hal_write_port_16:
mov rdx,rdi
mov rax,rsi
out dx,ax
nop
nop
nop
ret
;====================
global hal_write_port_8
hal_write_port_8:
mov rdx,rdi
mov rax,rsi
out dx,al
nop
nop
nop
ret
;====================
global hal_read_port_8
hal_read_port_8:
mov rdx,rdi
xor rax,rax
in al,dx
nop
nop
nop
ret
;====================
global hal_read_port_16
hal_read_port_16:
mov rdx,rdi
xor rax,rax
in ax,dx
nop
nop
nop
ret
;====================
global hal_read_port_32
hal_read_port_32:
mov rdx,rdi
xor rax,rax
in eax,dx
nop
nop
nop
ret
;====================
global hal_write_mem_32
; (void* target, uint32_t* data)
hal_write_mem_32:
mov dword [rdi], esi
ret
;====================
global hal_write_mem_64
; (void* target, uint64_t data)
hal_write_mem_64:
mov qword [rdi], rsi
ret
;====================
global hal_disable_interrupt
hal_disable_interrupt:
cli
ret
;====================
global hal_enable_interrupt
hal_enable_interrupt:
sti
ret
;====================
global hal_halt_cpu
hal_halt_cpu:
.loop:
hlt
jmp .loop
;====================
;(uint32_t *ecx, uint32_t* edx, uint32_t* 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_t *ecx, uint32_t* edx, uint32_t* 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,462 +0,0 @@
#include "type.h"
#include "hal/cpu.h"
#include "hal/intr.h"
#include "hal/print.h"
#include "hal/mem.h"
#include "lib/sxtdlib.h"
static uint8_t _idts[HAL_CORE_COUNT][IDT_ENTRY_NUM*IDT_ENTRY_SIZE];
static hal_idt_ptr_t _idt_ptrs[HAL_CORE_COUNT];
static intr_handler_t _intr_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
static void* _intr_handler_context_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
static exc_handler_t _exc_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
irql_t KABI hal_set_irql(irql_t irql)
{
UNREFERENCED(irql)
hal_assert(false,"Unimplemented function called.");
return 0;
}
irql_t KABI hal_get_irql(void)
{
hal_assert(false,"Unimplemented function called.");
return 0;
}
void KABI hal_write_gate(void *const gate,
uint64_t const offset,
uint32_t const selector,
uint32_t const attr)
{
((uint8_t *) gate)[0] = (uint8_t) (offset & 0xFF);
((uint8_t *) gate)[1] = (uint8_t) ((offset >> 8) & 0xFF);
((uint8_t *) gate)[2] = (uint8_t) (selector & 0xFF);
((uint8_t *) gate)[3] = (uint8_t) ((selector >> 8) & 0xFF);
((uint8_t *) gate)[4] = (uint8_t) (attr & 0xFF);
((uint8_t *) gate)[5] = (uint8_t) ((attr >> 8) & 0xFF);
((uint8_t *) gate)[6] = (uint8_t) ((offset >> 16) & 0xFF);
((uint8_t *) gate)[7] = (uint8_t) ((offset >> 24) & 0xFF);
((uint8_t *) gate)[8] = (uint8_t) ((offset >> 32) & 0xFF);
((uint8_t *) gate)[9] = (uint8_t) ((offset >> 40) & 0xFF);
((uint8_t *) gate)[10] = (uint8_t) ((offset >> 48) & 0xFF);
((uint8_t *) gate)[11] = (uint8_t) ((offset >> 56) & 0xFF);
((uint8_t *) gate)[12] = 0;
((uint8_t *) gate)[13] = 0;
((uint8_t *) gate)[14] = 0;
((uint8_t *) gate)[15] = 0;
return;
}
void KABI hal_set_interrupt_handler(uint64_t index,
void (*handler)(void))
{
if (index < IDT_ENTRY_NUM)
{
hal_write_gate(_idts[hal_get_core_id()] + 16 * index, (uint64_t) handler, seg_selector(1, 0),
GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT);
}
return;
}
void KABI hal_issue_interrupt(uint32_t target_core, uint32_t vector)
{
UNREFERENCED(target_core);
UNREFERENCED(vector);
hal_assert(false,"Unimplemented function called.");
return;
}
void KABI hal_register_interrupt_handler(uint32_t coreid, uint32_t index, intr_handler_t handler, void* context)
{
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
{
_intr_handler_table[coreid][index] = handler;
_intr_handler_context_table[coreid][index] = context;
}
return;
}
void KABI hal_deregister_interrupt_handler(uint32_t coreid, uint32_t index)
{
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
{
_intr_handler_table[coreid][index] = NULL;
}
return;
}
void KABI hal_register_exception_handler(uint32_t coreid, uint32_t index, exc_handler_t handler)
{
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
{
_exc_handler_table[coreid][index] = handler;
}
return;
}
void KABI hal_deregister_exception_handler(uint32_t coreid, uint32_t index)
{
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
{
_exc_handler_table[coreid][index] = NULL;
}
return;
}
void KABI hal_interrupt_dispatcher(uint64_t int_vec, hal_interrupt_context_t *context)
{
uint32_t coreid = hal_get_core_id();
if (_intr_handler_table[int_vec] == NULL)
{
hal_printf("Unhandled interrupt %d at 0x%X.\n", int_vec, context->rip);
}
else
{
_intr_handler_table[coreid][int_vec](context, _intr_handler_context_table[coreid][int_vec]);
}
return;
}
void KABI hal_exception_dispatcher(uint64_t exc_vec, hal_interrupt_context_t* context, uint64_t errorcode)
{
uint32_t coreid = hal_get_core_id();
if (_exc_handler_table[exc_vec] == NULL)
{
hal_printf("Unhandled exception %d at 0x%X.\n", exc_vec, context->rip);
}
else
{
_exc_handler_table[coreid][exc_vec](context->rip, context->rsp, errorcode);
}
return;
}
static void KABI halp_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);
return;
}
uint32_t KABI hal_get_core_id(void)
{
// TODO
return 0;
}
int32_t KABI hal_interrupt_init(void)
{
uint32_t coreid = hal_get_core_id();
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
eax = 1;
hal_cpuid(&eax, &ebx, &ecx, &edx);
if (!(edx & lb_bit_mask(9)))
{
hal_printf("ERROR: APIC not supported by CPU.\n");
return 1;
}
// get idt ptr ready
_idt_ptrs[coreid].base = (uint64_t) &_idts[coreid];
_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1;
// clear dispatch table
for (uint64_t i = 0; i < IDT_ENTRY_NUM; i++)
{
_intr_handler_table[coreid][i] = NULL;
_exc_handler_table[coreid][i] = NULL;
_intr_handler_context_table[coreid][i] = NULL;
}
// hook asm interrupt handlers
halp_populate_idt();
hal_flush_idt(&_idt_ptrs[coreid]);
// disable PIC
hal_write_port_8(0xa1, 0xff);
hal_write_port_8(0x21, 0xff);
uint64_t apic_base_reg = 0;
uint64_t apic_base = 0;
ecx = MSR_IA32_APIC_BASE;
hal_read_msr(&ecx, &edx, &eax);
apic_base_reg = ((uint64_t) edx << 32) + (uint64_t) eax;
apic_base = apic_base_reg & lb_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_t *) ((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET));
// hardware enable APIC
ecx = MSR_IA32_APIC_BASE;
eax = (uint32_t) ((apic_base_reg & lb_bit_field_mask(0, 31)) | lb_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_t *) (apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET) | (uint32_t)lb_bit_mask(8));
// hal_issue_interrupt(1, 255);
// hal_enable_interrupt();
return 0;
}

197
hal/mem.c
View File

@ -1,197 +0,0 @@
#include "type.h"
#include "hal/mem.h"
#include "hal/cpu.h"
#include "lib/salloc.h"
#include "hal/intr.h"
#include "status.h"
static uint8_t _gdts[HAL_CORE_COUNT][GDT_ENTRY_NUM * GDT_ENTRY_SIZE];
static hal_gdt_ptr_t _gdt_ptrs[HAL_CORE_COUNT];
#define KERNEL_HEAP_SIZE 8192
char kernel_heap[KERNEL_HEAP_SIZE];
/**
* helper for boot.asm, not open to C headers
* @param k_start kernel start paddr
* @param k_end kernel end paddr
* @param multiboot_info multibootinfo paddr
* @param pt_base page table base paddr
* @param pt_end page table entry paddr
*/
status_t KABI hal_write_initial_page_table(void* multiboot_info)
{
UNREFERENCED(multiboot_info);
/*
// still identity mapping
uint32_t pt_num = 0;
uint32_t pd_num = 0;
uint32_t pdpt_num = 0;
uint32_t pml4_num = 0;
// calculate the number of page tables required:
uint64_t k_size = (uintptr_t)KERNEL_IMAGE_END_VADDR - (uintptr_t)KERNEL_IMAGE_VADDR;
// see multiboot boot info header
uint32_t m_size = *(uint32_t *)multiboot_info;
// how many pages do we need to hold the entries
// 512 page table entries per 4k page
pt_num = (1 + (uint32_t)((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_t)(pt_end) - (uintptr_t)(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_t)pt_base, PML4_PRESENT | PML4_WRITE);
*/
return STATUS_SUCCESS;
}
void KABI hal_write_pt(void *const base, uintptr_t const p_addr, uint64_t const attr)
{
if (base == NULL)
return;
uint64_t entry = (p_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t *) base)[0] = (uint8_t) (entry & 0xFF);
((uint8_t *) base)[1] = (uint8_t) ((entry >> 8) & 0xFF);
((uint8_t *) base)[2] = (uint8_t) ((entry >> 16) & 0xFF);
((uint8_t *) base)[3] = (uint8_t) ((entry >> 24) & 0xFF);
((uint8_t *) base)[4] = (uint8_t) ((entry >> 32) & 0xFF);
((uint8_t *) base)[5] = (uint8_t) ((entry >> 40) & 0xFF);
((uint8_t *) base)[6] = (uint8_t) ((entry >> 48) & 0xFF);
((uint8_t *) base)[7] = (uint8_t) ((entry >> 56) & 0xFF);
return;
}
void KABI hal_write_pd(void *const base, uintptr_t const pt_addr, uint64_t const attr)
{
if (base == NULL)
return;
uint64_t entry = (pt_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t *) base)[0] = (uint8_t) (entry & 0xFF);
((uint8_t *) base)[1] = (uint8_t) ((entry >> 8) & 0xFF);
((uint8_t *) base)[2] = (uint8_t) ((entry >> 16) & 0xFF);
((uint8_t *) base)[3] = (uint8_t) ((entry >> 24) & 0xFF);
((uint8_t *) base)[4] = (uint8_t) ((entry >> 32) & 0xFF);
((uint8_t *) base)[5] = (uint8_t) ((entry >> 40) & 0xFF);
((uint8_t *) base)[6] = (uint8_t) ((entry >> 48) & 0xFF);
((uint8_t *) base)[7] = (uint8_t) ((entry >> 56) & 0xFF);
return;
}
void KABI hal_write_pdpt(void *const base, uintptr_t const pd_addr, uint64_t const attr)
{
if (base == NULL)
return;
uint64_t entry = (pd_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t *) base)[0] = (uint8_t) (entry & 0xFF);
((uint8_t *) base)[1] = (uint8_t) ((entry >> 8) & 0xFF);
((uint8_t *) base)[2] = (uint8_t) ((entry >> 16) & 0xFF);
((uint8_t *) base)[3] = (uint8_t) ((entry >> 24) & 0xFF);
((uint8_t *) base)[4] = (uint8_t) ((entry >> 32) & 0xFF);
((uint8_t *) base)[5] = (uint8_t) ((entry >> 40) & 0xFF);
((uint8_t *) base)[6] = (uint8_t) ((entry >> 48) & 0xFF);
((uint8_t *) base)[7] = (uint8_t) ((entry >> 56) & 0xFF);
return;
}
void KABI hal_write_pml4(void *const base, uintptr_t const pdpt_addr, uint64_t const attr)
{
if (base == NULL)
return;
uint64_t const entry = (pdpt_addr & 0xFFFFFFFFFF000) | attr;
((uint8_t *) base)[0] = (uint8_t) (entry & 0xFF);
((uint8_t *) base)[1] = (uint8_t) ((entry >> 8) & 0xFF);
((uint8_t *) base)[2] = (uint8_t) ((entry >> 16) & 0xFF);
((uint8_t *) base)[3] = (uint8_t) ((entry >> 24) & 0xFF);
((uint8_t *) base)[4] = (uint8_t) ((entry >> 32) & 0xFF);
((uint8_t *) base)[5] = (uint8_t) ((entry >> 40) & 0xFF);
((uint8_t *) base)[6] = (uint8_t) ((entry >> 48) & 0xFF);
((uint8_t *) base)[7] = (uint8_t) ((entry >> 56) & 0xFF);
return;
}
void KABI hal_write_segment_descriptor(void *const gdt, uint32_t const base, uint32_t const limit,
uint64_t const attr)
{
if (gdt == NULL)
return;
uint64_t const seg_desc = (((uint64_t) base & 0xFFFF) << 16) | ((((uint64_t) base >> 16) & 0xFF) << 32) |
((((uint64_t) base >> 24) & 0xFF) << 56) | ((uint64_t) limit & 0xFFFF) |
((((uint64_t) limit >> 16) & 0xF) << 48) | attr;
((uint8_t *) gdt)[0] = (uint8_t) (seg_desc & 0xFF);
((uint8_t *) gdt)[1] = (uint8_t) ((seg_desc >> 8) & 0xFF);
((uint8_t *) gdt)[2] = (uint8_t) ((seg_desc >> 16) & 0xFF);
((uint8_t *) gdt)[3] = (uint8_t) ((seg_desc >> 24) & 0xFF);
((uint8_t *) gdt)[4] = (uint8_t) ((seg_desc >> 32) & 0xFF);
((uint8_t *) gdt)[5] = (uint8_t) ((seg_desc >> 40) & 0xFF);
((uint8_t *) gdt)[6] = (uint8_t) ((seg_desc >> 48) & 0xFF);
((uint8_t *) gdt)[7] = (uint8_t) ((seg_desc >> 56) & 0xFF);
return;
}
void *KABI halloc(uint32_t size)
{
return lb_salloc(kernel_heap, size);
}
void KABI hfree(void *ptr)
{
lb_sfree(kernel_heap, ptr);
return;
}
static void KABI _hal_init_gdt(void)
{
uint32_t 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_t) &_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 KABI hal_mem_init()
{
_hal_init_gdt();
lb_salloc_init(kernel_heap, KERNEL_HEAP_SIZE);
return;
}

View File

@ -1,212 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#include "type.h"
#include "lib/sxtdlib.h"
#include "hal/print.h"
#include "hal/cpu.h"
#define get_column(pos) ((pos) % 80)
#define get_row(pos) ((pos) / 80)
#define get_pos(row,col) ((row) * 80 + (col))
static uint64_t text_pos;
void KABI hal_print_init(void)
{
text_pos = 0;
}
static void KABI halp_print_scroll(void)
{
lb_mem_move((void *) (0xb8000 + get_pos(1, 0) * 2), (void *) (0xb8000 + get_pos(0, 0) * 2), (80 * 24) * 2);
return;
}
static void KABI 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();
lb_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++;
}
}
return;
}
static void KABI halp_print_uint(uint64_t number)
{
char arr[21]; // do not need to initialize
arr[20] = 0; //zero-terminated
uint32_t index = 19;
uint32_t const div = 10;
while (1)
{
uint64_t quo = number / div;
uint64_t rmd = number % div;
number = quo;
arr[index--] = (char) ('0' + rmd);
if (number == 0)
break;
}
halp_print_str(&(arr[index + 1]));
return;
}
static void KABI halp_print_int(int64_t number)
{
char arr[21]; // do not need to initialize
arr[20] = 0; //zero-terminated
uint32_t index = 19;
uint32_t isNegative = 0;
uint32_t const div = 10;
if (number < 0)
{
isNegative = 1;
number *= -1;
}
while (1)
{
int64_t quo = number / div;
int64_t rmd = number % div;
number = quo;
arr[index--] = (char) ('0' + rmd);
if (number == 0)
break;
}
if (isNegative)
{
arr[index--] = '-';
}
halp_print_str(&(arr[index + 1]));
return;
}
static void KABI halp_print_hex(uint64_t number, uint64_t 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_t index = 15;
uint32_t const div = 16;
while (1)
{
uint64_t quo = number / div;
uint64_t rmd = number % div;
number = quo;
arr[index--] = look_up[rmd];
if (number == 0)
break;
}
halp_print_str(&(arr[index + 1]));
return;
}
void KABI hal_clear_screen(void)
{
text_pos = 0; // reset text_pos
lb_mem_set((void *) 0xb8000, 0, 25 * 80 * 2);
return;
}
void KABI hal_vprintf(char const * format, va_list args)
{
char buf[2] = {0, 0};
int64_t d;
uint64_t u;
char* s;
char c;
for(;*format != '\0';format++)
{
if (*format != '%')
{
buf[0] = *format;
halp_print_str(buf);
continue;
}
format++;
switch (*format)
{
case 'd':
d = va_arg(args, int64_t);
halp_print_int(d);
break;
case 'u':
u = va_arg(args, uint64_t);
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_t);
buf[0] = c;
halp_print_str(buf);
break;
case 'x':
u = va_arg(args, uint64_t);
halp_print_hex(u, 0);
break;
case 'X':
u = va_arg(args, uint64_t);
halp_print_hex(u, 1);
break;
case '%':
buf[0] = '%';
halp_print_str(buf);
break;
default:
buf[0] = '%';
halp_print_str(buf);
format--;
break;
}
}
}
void KABI hal_printf(char const *format, ...)
{
va_list args;
va_start(args, format);
hal_vprintf(format, args);
va_end(args);
}
void KABI hal_assert(uint32_t expression, char *message)
{
if (!expression)
{
hal_printf("HAL: Assertion failed. Detail: %s", message == NULL ? "NULL" : message);
hal_halt_cpu();
}
return;
}

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 + KERN_PMAP_START);
}

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

@ -0,0 +1,47 @@
#pragma once
/**
* Kernel Memory Layout
* ----------------------- 0x0000,0000,0000,0000 - User Space
* Application SIZE: 0x0000,8000,0000,0000 (256x PML4, 128TB)
* ----------------------- 0x0000,8000,0000,0000
* Non-canonical
* ----------------------- 0xFFFF,8000,0000,0000 - Kernel Space
* Unused
* ----------------------- 0xFFFF,9000,0000,0000
* PMAP SIZE: 0x0000,0400,0000,0000 (8x PML4, 4TB)
* ----------------------- 0xFFFF,9400,0000,0000
* Unused
* ----------------------- 0xFFFF,FFFF,8000,0000
* Kernel Image SIZE: 0x0000,0000,8000,0000 (2GB)
* ----------------------- 0xFFFF,FFFF,FFFF,FFFF
**/
/**
* kernel loaded at physical address 32MB
* 0x2000000 = 2 * 16777216 = 2 * 16 * 1024 * 1024
*/
#ifdef ASM_FILE
#define KERN_IMG_PADDR 0x2000000
#define KERN_PAGE_SZ 0x1000
#define KERN_PMAP_START 0xFFFF900000000000
#define KERN_PMAP_STOP 0xFFFF940000000000
#define KERN_BASE_START 0xFFFFFFFF80000000
#define KERN_BASE_STOP 0x0000000000000000
#else
#define KERN_IMG_PADDR (0x2000000)
#define KERN_PAGE_SZ (0x1000)
extern const char KERN_IMG_START[];
extern const char KERN_IMG_STOP[];
#define KERN_PMAP_START (0xFFFF900000000000)
#define KERN_PMAP_STOP (0xFFFF940000000000)
#define KERN_BASE_START (0xFFFFFFFF80000000)
#define KERN_BASE_STOP (0x0000000000000000)
#endif

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

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)

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

@ -0,0 +1,39 @@
#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)))
#define BOCHS_BREAK __asm__("xchg %bx, %bx")

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 *fmt, ...);
int
kvprintf(const char *fmt, 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
};

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

View File

@ -1,6 +0,0 @@
#ifndef _HAL_BOOT_H_
#define _HAL_BOOT_H_
#include "kernel/hal/boot.h"
#endif

View File

@ -1,82 +0,0 @@
#ifndef _HAL_CPU_H_
#define _HAL_CPU_H_
#include "type.h"
#include "kernel/hal/atomic.h"
#define HAL_CORE_COUNT 1
typedef struct
{
uint16_t limit;
uint64_t base;
} STRUCT_PACKED hal_gdt_ptr_t;
typedef struct
{
uint16_t limit;
uint64_t base;
} STRUCT_PACKED hal_idt_ptr_t;
/**
* CPU Instructions
*/
extern void KABI hal_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
extern void KABI hal_halt_cpu(void);
extern void KABI hal_enable_interrupt(void);
extern void KABI hal_disable_interrupt(void);
/**
* IO Port Operations
*/
extern int8_t KABI hal_read_port_8(uint16_t port);
extern int16_t KABI hal_read_port_16(uint16_t port);
extern int32_t KABI hal_read_port_32(uint16_t port);
extern void KABI hal_write_port_8(uint16_t port, uint8_t data);
extern void KABI hal_write_port_16(uint16_t port, uint16_t data);
extern void KABI hal_write_port_32(uint16_t port, uint32_t data);
/**
* CPU Structure Operations
*/
extern void KABI hal_flush_gdt(hal_gdt_ptr_t *gdt_ptr, uint64_t code_slct, uint64_t data_slct);
extern void KABI hal_flush_tlb(void);
extern void KABI hal_flush_idt(hal_idt_ptr_t *idt_ptr);
extern void KABI hal_read_idt(hal_idt_ptr_t **idt_ptr);
/**
* Control Register Operations
*/
#define MSR_IA32_APIC_BASE 0x1B
extern void KABI hal_read_msr(uint32_t *ecx, uint32_t *edx, uint32_t *eax);
extern void KABI hal_write_msr(uint32_t *ecx, uint32_t *edx, uint32_t *eax);
extern void KABI hal_write_cr3(uint64_t base);
extern uint64_t KABI hal_read_cr3(void);
extern void KABI hal_write_cr8(uint64_t pri);
extern uint64_t KABI hal_read_cr8(void);
#endif

View File

@ -1,307 +0,0 @@
#ifndef _HAL_INTR_H_
#define _HAL_INTR_H_
#include "type.h"
#include "kernel/hal/intr.h"
/**
* Interrupt context structure
*/
typedef struct
{
const uint64_t rip;
const uint64_t cs;
const uint64_t rflags;
const uint64_t rsp;
const uint64_t ss;
} hal_interrupt_context_t;
/**
* 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
/**
* intr.h
*/
int32_t KABI hal_interrupt_init(void);
/**
* System exception Handlers
*/
extern void KABI hal_interrupt_handler_0(void);
extern void KABI hal_interrupt_handler_1(void);
extern void KABI hal_interrupt_handler_2(void);
extern void KABI hal_interrupt_handler_3(void);
extern void KABI hal_interrupt_handler_4(void);
extern void KABI hal_interrupt_handler_5(void);
extern void KABI hal_interrupt_handler_6(void);
extern void KABI hal_interrupt_handler_7(void);
extern void KABI hal_interrupt_handler_8(void);
extern void KABI hal_interrupt_handler_9(void);
extern void KABI hal_interrupt_handler_10(void);
extern void KABI hal_interrupt_handler_11(void);
extern void KABI hal_interrupt_handler_12(void);
extern void KABI hal_interrupt_handler_13(void);
extern void KABI hal_interrupt_handler_14(void);
extern void KABI hal_interrupt_handler_15(void);
extern void KABI hal_interrupt_handler_16(void);
extern void KABI hal_interrupt_handler_17(void);
extern void KABI hal_interrupt_handler_18(void);
extern void KABI hal_interrupt_handler_19(void);
extern void KABI hal_interrupt_handler_20(void);
extern void KABI hal_interrupt_handler_21(void);
extern void KABI hal_interrupt_handler_22(void);
extern void KABI hal_interrupt_handler_23(void);
extern void KABI hal_interrupt_handler_24(void);
extern void KABI hal_interrupt_handler_25(void);
extern void KABI hal_interrupt_handler_26(void);
extern void KABI hal_interrupt_handler_27(void);
extern void KABI hal_interrupt_handler_28(void);
extern void KABI hal_interrupt_handler_29(void);
extern void KABI hal_interrupt_handler_30(void);
extern void KABI hal_interrupt_handler_31(void);
/**
* Kernel defined interrupt handlers
*/
extern void KABI hal_interrupt_handler_32(void);
extern void KABI hal_interrupt_handler_33(void);
extern void KABI hal_interrupt_handler_34(void);
extern void KABI hal_interrupt_handler_35(void);
extern void KABI hal_interrupt_handler_36(void);
extern void KABI hal_interrupt_handler_37(void);
extern void KABI hal_interrupt_handler_38(void);
extern void KABI hal_interrupt_handler_39(void);
extern void KABI hal_interrupt_handler_40(void);
extern void KABI hal_interrupt_handler_41(void);
extern void KABI hal_interrupt_handler_42(void);
extern void KABI hal_interrupt_handler_43(void);
extern void KABI hal_interrupt_handler_44(void);
extern void KABI hal_interrupt_handler_45(void);
extern void KABI hal_interrupt_handler_46(void);
extern void KABI hal_interrupt_handler_47(void);
extern void KABI hal_interrupt_handler_48(void);
extern void KABI hal_interrupt_handler_49(void);
extern void KABI hal_interrupt_handler_50(void);
extern void KABI hal_interrupt_handler_51(void);
extern void KABI hal_interrupt_handler_52(void);
extern void KABI hal_interrupt_handler_53(void);
extern void KABI hal_interrupt_handler_54(void);
extern void KABI hal_interrupt_handler_55(void);
extern void KABI hal_interrupt_handler_56(void);
extern void KABI hal_interrupt_handler_57(void);
extern void KABI hal_interrupt_handler_58(void);
extern void KABI hal_interrupt_handler_59(void);
extern void KABI hal_interrupt_handler_60(void);
extern void KABI hal_interrupt_handler_61(void);
extern void KABI hal_interrupt_handler_62(void);
extern void KABI hal_interrupt_handler_63(void);
extern void KABI hal_interrupt_handler_64(void);
extern void KABI hal_interrupt_handler_65(void);
extern void KABI hal_interrupt_handler_66(void);
extern void KABI hal_interrupt_handler_67(void);
extern void KABI hal_interrupt_handler_68(void);
extern void KABI hal_interrupt_handler_69(void);
extern void KABI hal_interrupt_handler_70(void);
extern void KABI hal_interrupt_handler_71(void);
extern void KABI hal_interrupt_handler_72(void);
extern void KABI hal_interrupt_handler_73(void);
extern void KABI hal_interrupt_handler_74(void);
extern void KABI hal_interrupt_handler_75(void);
extern void KABI hal_interrupt_handler_76(void);
extern void KABI hal_interrupt_handler_77(void);
extern void KABI hal_interrupt_handler_78(void);
extern void KABI hal_interrupt_handler_79(void);
extern void KABI hal_interrupt_handler_80(void);
extern void KABI hal_interrupt_handler_81(void);
extern void KABI hal_interrupt_handler_82(void);
extern void KABI hal_interrupt_handler_83(void);
extern void KABI hal_interrupt_handler_84(void);
extern void KABI hal_interrupt_handler_85(void);
extern void KABI hal_interrupt_handler_86(void);
extern void KABI hal_interrupt_handler_87(void);
extern void KABI hal_interrupt_handler_88(void);
extern void KABI hal_interrupt_handler_89(void);
extern void KABI hal_interrupt_handler_90(void);
extern void KABI hal_interrupt_handler_91(void);
extern void KABI hal_interrupt_handler_92(void);
extern void KABI hal_interrupt_handler_93(void);
extern void KABI hal_interrupt_handler_94(void);
extern void KABI hal_interrupt_handler_95(void);
extern void KABI hal_interrupt_handler_96(void);
extern void KABI hal_interrupt_handler_97(void);
extern void KABI hal_interrupt_handler_98(void);
extern void KABI hal_interrupt_handler_99(void);
extern void KABI hal_interrupt_handler_100(void);
extern void KABI hal_interrupt_handler_101(void);
extern void KABI hal_interrupt_handler_102(void);
extern void KABI hal_interrupt_handler_103(void);
extern void KABI hal_interrupt_handler_104(void);
extern void KABI hal_interrupt_handler_105(void);
extern void KABI hal_interrupt_handler_106(void);
extern void KABI hal_interrupt_handler_107(void);
extern void KABI hal_interrupt_handler_108(void);
extern void KABI hal_interrupt_handler_109(void);
extern void KABI hal_interrupt_handler_110(void);
extern void KABI hal_interrupt_handler_111(void);
extern void KABI hal_interrupt_handler_112(void);
extern void KABI hal_interrupt_handler_113(void);
extern void KABI hal_interrupt_handler_114(void);
extern void KABI hal_interrupt_handler_115(void);
extern void KABI hal_interrupt_handler_116(void);
extern void KABI hal_interrupt_handler_117(void);
extern void KABI hal_interrupt_handler_118(void);
extern void KABI hal_interrupt_handler_119(void);
extern void KABI hal_interrupt_handler_120(void);
extern void KABI hal_interrupt_handler_121(void);
extern void KABI hal_interrupt_handler_122(void);
extern void KABI hal_interrupt_handler_123(void);
extern void KABI hal_interrupt_handler_124(void);
extern void KABI hal_interrupt_handler_125(void);
extern void KABI hal_interrupt_handler_126(void);
extern void KABI hal_interrupt_handler_127(void);
extern void KABI hal_interrupt_handler_128(void);
extern void KABI hal_interrupt_handler_129(void);
extern void KABI hal_interrupt_handler_130(void);
extern void KABI hal_interrupt_handler_131(void);
extern void KABI hal_interrupt_handler_132(void);
extern void KABI hal_interrupt_handler_133(void);
extern void KABI hal_interrupt_handler_134(void);
extern void KABI hal_interrupt_handler_135(void);
extern void KABI hal_interrupt_handler_136(void);
extern void KABI hal_interrupt_handler_137(void);
extern void KABI hal_interrupt_handler_138(void);
extern void KABI hal_interrupt_handler_139(void);
extern void KABI hal_interrupt_handler_140(void);
extern void KABI hal_interrupt_handler_141(void);
extern void KABI hal_interrupt_handler_142(void);
extern void KABI hal_interrupt_handler_143(void);
extern void KABI hal_interrupt_handler_144(void);
extern void KABI hal_interrupt_handler_145(void);
extern void KABI hal_interrupt_handler_146(void);
extern void KABI hal_interrupt_handler_147(void);
extern void KABI hal_interrupt_handler_148(void);
extern void KABI hal_interrupt_handler_149(void);
extern void KABI hal_interrupt_handler_150(void);
extern void KABI hal_interrupt_handler_151(void);
extern void KABI hal_interrupt_handler_152(void);
extern void KABI hal_interrupt_handler_153(void);
extern void KABI hal_interrupt_handler_154(void);
extern void KABI hal_interrupt_handler_155(void);
extern void KABI hal_interrupt_handler_156(void);
extern void KABI hal_interrupt_handler_157(void);
extern void KABI hal_interrupt_handler_158(void);
extern void KABI hal_interrupt_handler_159(void);
extern void KABI hal_interrupt_handler_160(void);
extern void KABI hal_interrupt_handler_161(void);
extern void KABI hal_interrupt_handler_162(void);
extern void KABI hal_interrupt_handler_163(void);
extern void KABI hal_interrupt_handler_164(void);
extern void KABI hal_interrupt_handler_165(void);
extern void KABI hal_interrupt_handler_166(void);
extern void KABI hal_interrupt_handler_167(void);
extern void KABI hal_interrupt_handler_168(void);
extern void KABI hal_interrupt_handler_169(void);
extern void KABI hal_interrupt_handler_170(void);
extern void KABI hal_interrupt_handler_171(void);
extern void KABI hal_interrupt_handler_172(void);
extern void KABI hal_interrupt_handler_173(void);
extern void KABI hal_interrupt_handler_174(void);
extern void KABI hal_interrupt_handler_175(void);
extern void KABI hal_interrupt_handler_176(void);
extern void KABI hal_interrupt_handler_177(void);
extern void KABI hal_interrupt_handler_178(void);
extern void KABI hal_interrupt_handler_179(void);
extern void KABI hal_interrupt_handler_180(void);
extern void KABI hal_interrupt_handler_181(void);
extern void KABI hal_interrupt_handler_182(void);
extern void KABI hal_interrupt_handler_183(void);
extern void KABI hal_interrupt_handler_184(void);
extern void KABI hal_interrupt_handler_185(void);
extern void KABI hal_interrupt_handler_186(void);
extern void KABI hal_interrupt_handler_187(void);
extern void KABI hal_interrupt_handler_188(void);
extern void KABI hal_interrupt_handler_189(void);
extern void KABI hal_interrupt_handler_190(void);
extern void KABI hal_interrupt_handler_191(void);
extern void KABI hal_interrupt_handler_192(void);
extern void KABI hal_interrupt_handler_193(void);
extern void KABI hal_interrupt_handler_194(void);
extern void KABI hal_interrupt_handler_195(void);
extern void KABI hal_interrupt_handler_196(void);
extern void KABI hal_interrupt_handler_197(void);
extern void KABI hal_interrupt_handler_198(void);
extern void KABI hal_interrupt_handler_199(void);
extern void KABI hal_interrupt_handler_200(void);
extern void KABI hal_interrupt_handler_201(void);
extern void KABI hal_interrupt_handler_202(void);
extern void KABI hal_interrupt_handler_203(void);
extern void KABI hal_interrupt_handler_204(void);
extern void KABI hal_interrupt_handler_205(void);
extern void KABI hal_interrupt_handler_206(void);
extern void KABI hal_interrupt_handler_207(void);
extern void KABI hal_interrupt_handler_208(void);
extern void KABI hal_interrupt_handler_209(void);
extern void KABI hal_interrupt_handler_210(void);
extern void KABI hal_interrupt_handler_211(void);
extern void KABI hal_interrupt_handler_212(void);
extern void KABI hal_interrupt_handler_213(void);
extern void KABI hal_interrupt_handler_214(void);
extern void KABI hal_interrupt_handler_215(void);
extern void KABI hal_interrupt_handler_216(void);
extern void KABI hal_interrupt_handler_217(void);
extern void KABI hal_interrupt_handler_218(void);
extern void KABI hal_interrupt_handler_219(void);
extern void KABI hal_interrupt_handler_220(void);
extern void KABI hal_interrupt_handler_221(void);
extern void KABI hal_interrupt_handler_222(void);
extern void KABI hal_interrupt_handler_223(void);
extern void KABI hal_interrupt_handler_224(void);
extern void KABI hal_interrupt_handler_225(void);
extern void KABI hal_interrupt_handler_226(void);
extern void KABI hal_interrupt_handler_227(void);
extern void KABI hal_interrupt_handler_228(void);
extern void KABI hal_interrupt_handler_229(void);
extern void KABI hal_interrupt_handler_230(void);
extern void KABI hal_interrupt_handler_231(void);
extern void KABI hal_interrupt_handler_232(void);
extern void KABI hal_interrupt_handler_233(void);
extern void KABI hal_interrupt_handler_234(void);
extern void KABI hal_interrupt_handler_235(void);
extern void KABI hal_interrupt_handler_236(void);
extern void KABI hal_interrupt_handler_237(void);
extern void KABI hal_interrupt_handler_238(void);
extern void KABI hal_interrupt_handler_239(void);
extern void KABI hal_interrupt_handler_240(void);
extern void KABI hal_interrupt_handler_241(void);
extern void KABI hal_interrupt_handler_242(void);
extern void KABI hal_interrupt_handler_243(void);
extern void KABI hal_interrupt_handler_244(void);
extern void KABI hal_interrupt_handler_245(void);
extern void KABI hal_interrupt_handler_246(void);
extern void KABI hal_interrupt_handler_247(void);
extern void KABI hal_interrupt_handler_248(void);
extern void KABI hal_interrupt_handler_249(void);
extern void KABI hal_interrupt_handler_250(void);
extern void KABI hal_interrupt_handler_251(void);
extern void KABI hal_interrupt_handler_252(void);
extern void KABI hal_interrupt_handler_253(void);
extern void KABI hal_interrupt_handler_254(void);
extern void KABI hal_interrupt_handler_255(void);
#endif

View File

@ -1,102 +0,0 @@
#ifndef _HAL_MEM_H_
#define _HAL_MEM_H_
#include "type.h"
#include "kernel/hal/mem.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
**/
#define PML4_PRESENT (1ull << 0)
#define PML4_WRITE (1ull << 1)
#define PML4_USER (1ull << 2)
#define PML4_WRITE_THROUGH (1ull << 3)
#define PML4_CACHE_DISABLED (1ull << 4)
#define PML4_ACCESSED (1ull << 5)
#define PML4_EXECUTION_DISABLED (1ull << 63)
#define PDPT_PRESENT (1ull << 0)
#define PDPT_WRITE (1ull << 1)
#define PDPT_USER (1ull << 2)
#define PDPT_WRITE_THROUGH (1ull << 3)
#define PDPT_CACHE_DISABLED (1ull << 4)
#define PDPT_ACCESSED (1ull << 5)
#define PDPT_EXECUTION_DISABLED (1ull << 63)
#define PD_PRESENT (1ull << 0)
#define PD_WRITE (1ull << 1)
#define PD_USER (1ull << 2)
#define PD_WRITE_THROUGH (1ull << 3)
#define PD_CACHE_DISABLED (1ull << 4)
#define PD_ACCESSED (1ull << 5)
#define PD_EXECUTION_DISABLED (1ull << 63)
#define PT_PRESENT (1ull << 0)
#define PT_WRITE (1ull << 1)
#define PT_USER (1ull << 2)
#define PT_WRITE_THROUGH (1ull << 3)
#define PT_CACHE_DISABLED (1ull << 4)
#define PT_ACCESSED (1ull << 5)
#define PT_DIRTY (1ull << 6)
#define PT_ATTRIBUTE_TABLE (1ull << 7)
#define PT_GLOBAL (1ull << 8)
#define PT_EXECUTION_DISABLED (1ull << 63)
#define PML4_ENTRY_NUM(vaddr) (((vaddr) >> 39) & 0x1FF)
#define PDPT_ENTRY_NUM(vaddr) (((vaddr) >> 30) & 0x1FF)
#define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF)
#define PT_ENTRY_NUM(vaddr) (((vaddr) >> 12) & 0x1FF)
static inline uint32_t KABI seg_selector(uint32_t index, uint32_t rpl)
{
return (index << 3) + rpl;
}
void KABI hal_write_segment_descriptor(void *const gdt, uint32_t const base, uint32_t const limit, uint64_t const attr);
void KABI hal_write_pml4(void *const base, uintptr_t const pdpt_addr, uint64_t const attr);
void KABI hal_write_pdpt(void *const base, uintptr_t const pd_addr, uint64_t const attr);
void KABI hal_write_pd(void *const base, uintptr_t const pt_addr, uint64_t const attr);
void KABI hal_write_pt(void *const base, uintptr_t const p_addr, uint64_t const attr);
/**
Function Defn
**/
void *KABI halloc(uint32_t size);
void KABI hfree(void *ptr);
void KABI hal_mem_init(void);
#endif

View File

@ -1,15 +0,0 @@
#ifndef _HAL_PRINT_H_
#define _HAL_PRINT_H_
#include "type.h"
#include "kernel/hal/print.h"
void KABI hal_assert(uint32_t expression, char *message);
void KABI hal_printf(const char *str, ...);
void KABI hal_clear_screen(void);
void KABI hal_print_init(void);
#endif

View File

@ -1,16 +0,0 @@
#ifndef _KERNEL_HAL_ATOMIC_H_
#define _KERNEL_HAL_ATOMIC_H_
#include "type.h"
/**
* Atomic operations
*/
extern int32_t KABI hal_interlocked_exchange_32(int32_t *target, int32_t val);
extern int32_t KABI hal_interlocked_increment_32(int32_t *target, int32_t increment);
extern int32_t KABI hal_interlocked_compare_exchange_32(int32_t *target, int32_t compare, int32_t val);
#endif

View File

@ -1,21 +0,0 @@
#ifndef _KERNEL_HAL_BOOT_H_
#define _KERNEL_HAL_BOOT_H_
#include "type.h"
#include "kernel/hal/intr.h"
#include "kernel/hal/mem.h"
/**
* Required OS boot info
*/
typedef struct
{
void* krnl_end;
intr_info_t intr_info;
char cpu_vd_str[13];
} boot_info_t;
void KABI ke_main(boot_info_t* info);
#endif

View File

@ -1,55 +0,0 @@
#ifndef _KERNEL_HAL_INTR_H_
#define _KERNEL_HAL_INTR_H_
#include "type.h"
/**
* IRQL Definitions
*/
typedef uint32_t irql_t;
#define IRQL_DISABLED_LEVEL (1 << 3)
#define IRQL_DPC_LEVEL (1 << 2)
#define IRQL_APC_LEVEL (1 << 1)
#define IRQL_PASSIVE_LEVEL (1 << 0)
irql_t KABI hal_set_irql(irql_t irql);
irql_t KABI hal_get_irql(void);
uint32_t KABI hal_get_core_id(void);
/**
* Interrupt Handler Registration
*/
typedef struct
{
uint32_t timer_intr_vec;
uint32_t apc_intr_vec;
uint32_t dpc_intr_vec;
} intr_info_t;
typedef void (KABI * intr_handler_t)(void *context, void *intr_stack);
void KABI hal_register_interrupt_handler(uint32_t coreid, uint32_t index, intr_handler_t handler, void* context);
void KABI hal_deregister_interrupt_handler(uint32_t coreid, uint32_t index);
/**
* Exception Handler Registration
*/
typedef enum
{
unrecoverable_exc,
div_by_zero_exc,
general_protection_exc,
invalid_op_exc,
page_fault_exc,
unsupported_exc,
debug_exc
} exc_type_t;
typedef void (KABI *exc_handler_t)(uint64_t exc_addr, uint64_t exc_stack, uint64_t error_code);
void KABI hal_register_exception_handler(uint32_t coreid, uint32_t index, exc_handler_t handler);
void KABI hal_deregister_exception_handler(uint32_t coreid, uint32_t index);
#endif

View File

@ -1,62 +0,0 @@
#ifndef _KERNEL_HAL_MEM_H_
#define _KERNEL_HAL_MEM_H_
/**
* 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
**/
#define KERNEL_IMAGE_PADDR (0x1000000)
#define KERNEL_PAGE_SIZE (0x1000)
#define KERNEL_SPACE_VADDR (0xFFFF800000000000)
#define KERNEL_RESERVED_VADDR KERNEL_SPACE_VADDR
#define KERNEL_RESERVED_SIZE (0x00007F0000000000)
#define KERNEL_PAGE_TABLE_VADDR (0xFFFFFF0000000000)
#define KERNEL_PAGE_TABLE_SIZE (0x0000008000000000)
#define KERNEL_DYNAMIC_VADDR (0xFFFFFF8000000000)
#define KERNEL_DYNAMIC_SIZE (0x0000007F80000000)
#define KERNEL_IMAGE_VADDR (0xFFFFFFFF80000000)
#define KERNEL_IMAGE_SIZE (0x0000000080000000)
#ifndef ASM_FILE
#include "type.h"
#include "lib/linked_list.h"
/**
* From linker.inc
*/
extern char KERNEL_IMAGE_END_VADDR[];
/**
* PMM init info
*/
typedef struct
{
uintptr_t base;
uint64_t size;
uint32_t attr;
} pmm_node_t;
typedef struct
{
uint32_t num_of_nodes;
pmm_node_t nodes[];
} pmm_info_t;
#endif
#endif

View File

@ -1,8 +0,0 @@
#ifndef _KERNEL_HAL_PRINT_H_
#define _KERNEL_HAL_PRINT_H_
#include "type.h"
void KABI hal_vprintf(const char* str, va_list args);
#endif

View File

@ -1,12 +0,0 @@
#ifndef _KERNEL_KE_ALLOC_H_
#define _KERNEL_KE_ALLOC_H_
#include "type.h"
void KABI ke_alloc_init(void);
void* KABI ke_alloc(uint32_t size);
void KABI ke_free(void *ptr);
#endif

View File

@ -1,10 +0,0 @@
#ifndef _KERNEL_KE_ASSERT_H_
#define _KERNEL_KE_ASSERT_H_
#include "type.h"
void KABI ke_assert_ex(const char* expr_str, const char* file, int32_t line, int32_t expr);
#define ke_assert(expr) ke_assert_ex(#expr, __FILE__, __LINE__, expr)
#endif

View File

@ -1,13 +0,0 @@
#ifndef _KERNEL_KE_ATOMIC_H_
#define _KERNEL_KE_ATOMIC_H_
#include "type.h"
#include "kernel/hal/atomic.h"
int32_t KABI ke_interlocked_exchange_32(int32_t *target, int32_t val);
int32_t KABI ke_interlocked_increment_32(int32_t *target, int32_t increment);
int32_t KABI ke_interlocked_compare_exchange_32(int32_t *target, int32_t compare, int32_t val);
#endif

View File

@ -1,6 +0,0 @@
#ifndef _KERNEL_KE_BOOT_H_
#define _KERNEL_KE_BOOT_H_
#include "kernel/hal/boot.h"
#endif

View File

@ -1,11 +0,0 @@
#ifndef _KERNEL_KE_BUG_CHECK_H_
#define _KERNEL_KE_BUG_CHECK_H_
#include "type.h"
#define BUG_CHECK_IRQL_MISMATCH 0
#define BUG_CHECK_PMM_UNALIGNED 1
void KABI ke_bug_check(uint64_t reason);
#endif

View File

@ -1,15 +0,0 @@
#ifndef _KERNEL_KE_INTR_H_
#define _KERNEL_KE_INTR_H_
#include "kernel/hal/intr.h"
#include "type.h"
irql_t KABI ke_raise_irql(irql_t irql);
irql_t KABI ke_lower_irql(irql_t irql);
int KABI ke_get_current_core(void);
irql_t KABI ke_get_irql(void);
#endif

View File

@ -1,10 +0,0 @@
#ifndef _KERNEL_KE_PRINT_H_
#define _KERNEL_KE_PRINT_H_
#include "type.h"
#include "kernel/hal/print.h"
void KABI ke_printf(const char* str, ...);
void KABI ke_vprintf(const char* str, va_list args);
#endif

View File

@ -1,34 +0,0 @@
#ifndef _KERNEL_KE_RWLOCK_H_
#define _KERNEL_KE_RWLOCK_H_
#include "kernel/ke/spin_lock.h"
#include "type.h"
typedef struct
{
k_spin_lock_t w_mutex;
k_spin_lock_t r_mutex;
k_spin_lock_t res_lock;
k_spin_lock_t r_try;
uint32_t reader_ct;
uint32_t writer_ct;
} k_rwwlock_t;
void KABI ke_rwwlock_init(k_rwwlock_t *lock);
void KABI ke_rwwlock_reader_lock(k_rwwlock_t *lock);
void KABI ke_rwwlock_reader_unlock(k_rwwlock_t *lock);
void KABI ke_rwwlock_writer_lock(k_rwwlock_t *lock);
void KABI ke_rwwlock_writer_unlock(k_rwwlock_t *lock);
irql_t KABI ke_rwwlock_reader_lock_raise_irql(k_rwwlock_t *lock, irql_t irql);
void KABI ke_rwwlock_reader_unlock_lower_irql(k_rwwlock_t *lock, irql_t irql);
irql_t KABI ke_rwwlock_writer_lock_raise_irql(k_rwwlock_t *lock, irql_t irql);
void KABI ke_rwwlock_writer_unlock_lower_irql(k_rwwlock_t *lock, irql_t irql);
#endif

View File

@ -1,22 +0,0 @@
#ifndef _KERNEL_KE_SPIN_LOCK_H_
#define _KERNEL_KE_SPIN_LOCK_H_
#include "type.h"
#include "kernel/ke/intr.h"
typedef struct
{
int32_t val;
} k_spin_lock_t;
void KABI ke_spin_lock_init(k_spin_lock_t *lock);
void KABI ke_spin_lock(k_spin_lock_t *lock);
void KABI ke_spin_unlock(k_spin_lock_t *lock);
irql_t KABI ke_spin_lock_raise_irql(k_spin_lock_t *lock, irql_t irql);
void KABI ke_spin_unlock_lower_irql(k_spin_lock_t *lock, irql_t irql);
#endif

View File

@ -1,6 +0,0 @@
#ifndef _KERNEL_MM_MEM_H_
#define _KERNEL_MM_MEM_H_
#include "kernel/hal/mem.h"
#endif

View File

@ -1,36 +0,0 @@
#ifndef _KERNEL_MM_PMM_H_
#define _KERNEL_MM_PMM_H_
#include "type.h"
#include "lib/avl_tree.h"
#include "lib/linked_list.h"
#include "kernel/mm/mem.h"
#include "kernel/ke/atomic.h"
#include "status.h"
//#define PMM_PAGE_ATTR_FREE_BIT 0
//#define PMM_PAGE_ATTR_PAGED_BIT 1
//
//typedef struct
//{
// uint32_t attr;
//} k_physical_page_attr_t;
status_t KABI sx_pmm_init(pmm_info_t *info);
status_t KABI mm_alloc_page(uintptr_t *out);
status_t KABI mm_free_page(uintptr_t base);
status_t KABI mm_query_page_attr(uintptr_t base,
int32_t *out);
// TODO: implement these somehow, i might just reserve the first 16MB for these
int32_t KABI mm_alloc_contiguous_pages(uint64_t num_of_page,
uintptr_t highest_p_addr,
uintptr_t *out);
int32_t KABI mm_free_contiguous_pages(uintptr_t base);
#endif

View File

@ -1,38 +0,0 @@
#ifndef _KERNEL_RF_REF_H_
#define _KERNEL_RF_REF_H_
#include "type.h"
#include "status.h"
typedef uint32_t handle_t;
typedef struct
{
int32_t ref_count;
callback_func_t free_routine;
} ref_node_t;
#define K_HANDLE_BASE 0x80000000
//
// All functions are sx since users or kernel devs should not be
// specifying where the allocations take place
//
status_t KABI rf_reference_setup(void);
status_t KABI rf_reference_create(ref_node_t *ref,
callback_func_t free_func);
status_t KABI rf_reference_obj(ref_node_t *ref);
status_t KABI rf_dereference_obj(ref_node_t *ref);
// HANDLES
status_t KABI sx_open_obj_by_handle(handle_t handle, ref_node_t **out);
status_t KABI sx_create_handle(ref_node_t *ref, handle_t *out);
status_t KABI sx_close_handle(handle_t handle);
#endif

View File

@ -1,54 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#ifndef _LIB_AVL_TREE_H_
#define _LIB_AVL_TREE_H_
#include "type.h"
#include "lib/sxtdlib.h"
typedef struct _k_avl_tree_node_t
{
struct _k_avl_tree_node_t *left;
struct _k_avl_tree_node_t *right;
struct _k_avl_tree_node_t *parent;
int32_t height;
} avl_tree_node_t;
/*
* 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
*/
typedef struct _k_avl_tree_t
{
callback_func_t compare;
avl_tree_node_t *root;
} avl_tree_t;
avl_tree_node_t *KABI lb_avl_tree_search(avl_tree_t *tree, avl_tree_node_t *entry);
void KABI lb_avl_tree_insert(avl_tree_t *tree, avl_tree_node_t *entry);
avl_tree_node_t *KABI lb_avl_tree_delete(avl_tree_t *tree, avl_tree_node_t *entry);
void KABI lb_avl_tree_init(avl_tree_t *tree, callback_func_t compare);
avl_tree_node_t *KABI lb_avl_tree_largest(avl_tree_t *tree);
avl_tree_node_t *KABI lb_avl_tree_smallest(avl_tree_t *tree);
avl_tree_node_t *KABI lb_avl_tree_larger(avl_tree_node_t *entry);
avl_tree_node_t *KABI lb_avl_tree_smaller(avl_tree_node_t *entry);
bool KABI lb_avl_tree_validate(avl_tree_t *tree);
int32_t KABI lb_avl_tree_size(avl_tree_t *tree);
#endif

View File

@ -1,61 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#ifndef _LIB_LINKED_LIST_H_
#define _LIB_LINKED_LIST_H_
#include "type.h"
typedef struct _linked_list_node_t
{
struct _linked_list_node_t *prev;
struct _linked_list_node_t *next;
} linked_list_node_t;
typedef struct _linked_list_t
{
linked_list_node_t *head;
linked_list_node_t *tail;
} linked_list_t;
/*
* Returns true if current list node == your node
* false otherwise
*/
void KABI lb_linked_list_init(linked_list_t *list);
int32_t KABI lb_linked_list_size(linked_list_t *list);
void KABI lb_linked_list_push_front(linked_list_t *list, linked_list_node_t *node);
void KABI lb_linked_list_push_back(linked_list_t *list, linked_list_node_t *node);
linked_list_node_t *KABI lb_linked_list_pop_front(linked_list_t *list);
linked_list_node_t *KABI lb_linked_list_pop_back(linked_list_t *list);
void KABI lb_linked_list_insert(linked_list_t *list, int32_t index, linked_list_node_t *node);
void KABI lb_linked_list_insert_ref(linked_list_t *list, linked_list_node_t *prev_node, linked_list_node_t *node);
linked_list_node_t *KABI lb_linked_list_remove(linked_list_t *list, int32_t index);
linked_list_node_t *KABI lb_linked_list_remove_ref(linked_list_t *list, linked_list_node_t *node);
linked_list_node_t *KABI lb_linked_list_get(linked_list_t *list, int32_t index);
linked_list_node_t *KABI lb_linked_list_next(linked_list_node_t *node);
linked_list_node_t *KABI lb_linked_list_prev(linked_list_node_t *node);
linked_list_node_t *KABI lb_linked_list_first(linked_list_t *list);
linked_list_node_t *KABI lb_linked_list_last(linked_list_t *list);
int32_t KABI lb_linked_list_search(linked_list_t *list, linked_list_node_t *target,
callback_func_t equals);
#endif

View File

@ -1,20 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#ifndef _LIB_SALLOC_H_
#define _LIB_SALLOC_H_
#include "type.h"
void KABI lb_salloc_init(void *base, uint32_t size);
void* KABI lb_salloc(void *base, uint32_t size);
void KABI lb_sfree(void *base, void *ptr);
bool KABI lb_salloc_assert(void *base, uint32_t *blk_size, bool *blk_free, uint32_t size);
#endif

View File

@ -1,137 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#ifndef _LIB_SXTDLIB_H_
#define _LIB_SXTDLIB_H_
#include "type.h"
uint32_t KABI lb_rand(void);
void KABI lb_srand(uint32_t _seed);
void KABI lb_mrand(uint32_t max);
uint64_t KABI lb_str_len(char const *str);
uint64_t KABI lb_str_cmp(char const *str1, char const *str2);
void KABI lb_mem_copy(void *src, void *dst, uint64_t size);
void KABI lb_mem_move(void *src, void *dst, uint64_t size);
void KABI lb_mem_set(void *src, uint8_t const val, uint64_t size);
static inline uint64_t KABI lb_align_down(uint64_t val, uint64_t alignment)
{
return (val / alignment) * alignment;
}
static inline uint64_t KABI lb_align_up(uint64_t val, uint64_t alignment)
{
return ((((val) % (alignment)) == 0) ? (((val) / (alignment)) * (alignment)) : (
(((val) / (alignment)) * (alignment)) + 1));
}
static inline uint64_t KABI lb_is_overlap(uint64_t x1, uint64_t x2, uint64_t y1, uint64_t y2)
{
return ((x1 <= y2) && (y1 <= x2)) ? 1 : 0;
}
static inline int64_t KABI lb_max_64(int64_t a, int64_t b)
{
return (a) > (b) ? a : b;
}
static inline int64_t KABI lb_min_64(int64_t a, int64_t b)
{
return (a) < (b) ? a : b;
}
static inline int32_t KABI lb_max_32(int32_t a, int32_t b)
{
return (a) > (b) ? a : b;
}
static inline int32_t KABI lb_min_32(int32_t a, int32_t b)
{
return (a) < (b) ? a : b;
}
/*
static inline uint64_t KAPI round_up_power_of_2(uint64_t num)
{
num--;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
num |= num >> 32;
num++;
return (uint64_t)num;
}
static inline uint32_t KAPI log_base_2(uint64_t num)
{
uint32_t result = 0;
while (num >>= 1)
{
result++;
}
return result;
}
*/
#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr_t)(member_addr) - (uintptr_t)(&(((struct_name*)0)->member_name))))
static inline uint64_t KABI lb_bit_mask(uint32_t bit)
{
return (uint64_t)1 << bit;
}
static inline uint64_t KABI lb_bit_field_mask(uint32_t low, uint32_t high)
{
return ~(~(uint64_t)0 << high << 1) << low;
}
static inline void KABI lb_bit_map_set(void *bit_map, uint64_t bit)
{
if(bit_map != NULL)
{
uint64_t quot = bit >> 3;
uint32_t rmd = (uint32_t)(bit & lb_bit_field_mask(0, 2));
*((uint8_t*)(bit_map) + quot) |= (uint8_t) lb_bit_mask(rmd);
}
}
static inline void KABI lb_bit_map_clear(void *bit_map, uint64_t bit)
{
if(bit_map != NULL)
{
uint64_t quot = bit >> 3;
uint32_t rmd = (uint32_t)(bit & lb_bit_field_mask(0, 2));
*((uint8_t*)(bit_map) + quot) &= ~(uint8_t) lb_bit_mask(rmd);
}
}
static inline uint32_t KABI lb_bit_map_read(void *bit_map, uint64_t bit)
{
if(bit_map != NULL)
{
uint64_t quot = bit >> 3;
uint32_t rmd = (uint32_t)(bit & lb_bit_field_mask(0, 2));
return (*((uint8_t*)(bit_map) + quot) & (uint8_t) lb_bit_mask(rmd)) == 0 ? 0 : 1;
}
return 0;
}
#endif

View File

@ -1,50 +0,0 @@
#ifndef _STATUS_H_
#define _STATUS_H_
#include "type.h"
#include "lib/sxtdlib.h"
typedef uint32_t status_t;
//
// 32 bit ints
//
// bits 30 - 31 - Error/Success
// 00 = Success
// 01 = Error
//
// bits 0-14 - Return Code - 32768 in total
// bits 15-29 - Facility 32768 in total
//
#define SX_MAKE_STATUS(Severity, Facility, Return) (((Severity) << 30) | ((Facility) << 16) | (Return))
#define SEVERITY_ERROR 0x3
#define SEVERITY_SUCCESS 0x0
#define SEVERITY_INFO 0x1
#define FACILITY_GENERIC 0
#define FACILITY_RF 1
#define FACILITY_MM 2
static inline bool sx_success(status_t status)
{
uint32_t severity = status >> 30;
return (severity == SEVERITY_INFO) || (severity == SEVERITY_SUCCESS);
}
#define STATUS_SUCCESS (SX_MAKE_STATUS(SEVERITY_SUCCESS, FACILITY_GENERIC, 0))
#define STATUS_FAIL (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_GENERIC, 0))
#define RF_UNINITIALIZED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 1))
#define RF_ALLOCATION_FAILED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 2))
#define RF_INVALID_ARGUMENTS (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 3))
#define RF_INVALID_HANDLE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 4))
#define RF_DUPLICATED_HANDLE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 5))
#define MM_INVALID_ARGUMENTS (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 1))
#define MM_ALLOCATION_FAILED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 2))
#define MM_UNINITIALIZED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 3))
#define MM_NOT_ENOUGH_PAGE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 4))
#endif

View File

@ -1,14 +0,0 @@
#ifndef _TEST_DRIVER_H_
#define _TEST_DRIVER_H_
#include "type.h"
void KABI test_begin(char *name);
void KABI test_end(void);
void *KABI talloc(uint32_t size);
void KABI run_case(char *name, bool result);
#endif

View File

@ -1,12 +0,0 @@
#ifndef _TEST_TEST_H_
#define _TEST_TEST_H_
#include "type.h"
void KABI linked_list_test(void);
void KABI avl_tree_test(void);
void KABI salloc_test(void);
#endif

View File

@ -1,23 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#ifndef _TYPE_H_
#define _TYPE_H_
#define KABI __attribute__((sysv_abi))
#define UAPI __attribute__((sysv_abi))
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>
typedef int32_t (*callback_func_t)(void *kernel_args, void *user_args);
#define STRUCT_PACKED __attribute__((packed))
#define UNREFERENCED(x) {(x) = (x);}
#endif

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

167
kern/print.c Normal file
View File

@ -0,0 +1,167 @@
#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;
if (num == 0) {
buf[0] = '0';
return 1;
}
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;
base = 16;
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);
for(int i = len - 1; i >= 0; i--) {
arch_putc(nbuf[i]);
}
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,10 +0,0 @@
include $(MK)/prologue.mk
dir := $(d)/ke
include $(dir)/Rules.mk
dir := $(d)/mm
include $(dir)/Rules.mk
dir := $(d)/rf
include $(dir)/Rules.mk
include $(MK)/epilogue.mk

View File

@ -1,15 +0,0 @@
include $(MK)/prologue.mk
SRC_$(d) := $(d)/alloc.c \
$(d)/assert.c \
$(d)/atomic.c \
$(d)/boot.c \
$(d)/bug_check.c \
$(d)/intr.c \
$(d)/print.c \
$(d)/rwwlock.c \
$(d)/spin_lock.c
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -1,30 +0,0 @@
#include "type.h"
#include "kernel/ke/alloc.h"
#include "lib/salloc.h"
#define K_KERNEL_HEAP_SIZE 8192
static _Bool alloc_initialized;
static uint8_t alloc_heap[K_KERNEL_HEAP_SIZE];
void KABI ke_alloc_init(void)
{
if (!alloc_initialized)
{
lb_salloc_init(alloc_heap, K_KERNEL_HEAP_SIZE);
alloc_initialized = true;
}
}
void *KABI ke_alloc(uint32_t size)
{
return alloc_initialized ? lb_salloc(alloc_heap, size) : NULL;
}
void KABI ke_free(void *ptr)
{
if (alloc_initialized)
{
lb_sfree(alloc_heap, ptr);
}
}

View File

@ -1,11 +0,0 @@
#include "type.h"
#include "kernel/ke/assert.h"
#include "kernel/ke/print.h"
void ke_assert_ex(const char* expr_str, const char* file, int32_t line, int32_t expr)
{
if(!expr)
{
ke_printf("Assertion \"%s\" failed at %s:%d.\n", expr_str, file, line);
}
}

View File

@ -1,17 +0,0 @@
#include "type.h"
#include "kernel/ke/atomic.h"
int32_t KABI ke_interlocked_exchange_32(int32_t *target, int32_t val)
{
return hal_interlocked_exchange_32(target, val);
}
int32_t KABI ke_interlocked_increment_32(int32_t *target, int32_t increment)
{
return hal_interlocked_increment_32(target, increment);
}
int32_t KABI ke_interlocked_compare_exchange_32(int32_t *target, int32_t compare, int32_t val)
{
return hal_interlocked_compare_exchange_32(target, compare, val);
}

View File

@ -1,42 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#include "kernel/ke/boot.h"
#include "kernel/ke/alloc.h"
#include "test/test_case.h"
#include "kernel/ke/print.h"
// returning from this function results in halting the cpu
void KABI ke_main(boot_info_t *boot_info)
{
if (boot_info == NULL)
{
// failed.
ke_printf("KERNEL: HAL init failed.\n");
return;
}
// init kernel heap
//sx_pmm_init(boot_info->pmm_info);
ke_alloc_init();
// ke_printf("KERNEL: Base Addr is 0x%X. Size is %uB, %uKB.\n",
// boot_info->krnl_start,
// (boot_info->krnl_end - boot_info->krnl_start),
// (boot_info->krnl_end - boot_info->krnl_start) / 1024);
ke_printf("KERNEL: CPU Vendor is \"%s\".\n", boot_info->cpu_vd_str);
linked_list_test();
avl_tree_test();
salloc_test();
ke_printf("KERNEL: Kernel tasks finished.\n");
return;
}

View File

@ -1,9 +0,0 @@
#include "type.h"
#include "kernel/ke/print.h"
#include "kernel/ke/bug_check.h"
void KABI ke_bug_check(uint64_t reason)
{
ke_printf("BugCheck: Reason - %ul\n", reason);
while(true){};
}

View File

@ -1,25 +0,0 @@
#include "kernel/ke/assert.h"
#include "kernel/ke/intr.h"
irql_t KABI ke_raise_irql(irql_t irql)
{
ke_assert(ke_get_irql() <= irql);
return hal_set_irql(irql);
}
irql_t KABI ke_lower_irql(irql_t irql)
{
irql_t old_irql = ke_get_irql();
ke_assert(old_irql >= irql);
return hal_set_irql(irql);
}
irql_t KABI ke_get_irql(void)
{
return hal_get_irql();
}
int KABI ke_get_current_core(void)
{
return hal_get_core_id();
}

View File

@ -1,16 +0,0 @@
#include "kernel/ke/print.h"
void KABI ke_printf(const char* str, ...)
{
va_list args;
va_start(args, str);
ke_vprintf(str, args);
va_end(args);
return;
}
void KABI ke_vprintf(const char* str, va_list args)
{
hal_vprintf(str, args);
return;
}

View File

@ -1,100 +0,0 @@
#include "kernel/ke/rwwlock.h"
void ke_rwwlock_init(k_rwwlock_t *lock)
{
if (lock != NULL)
{
ke_spin_lock_init(&lock->w_mutex);
ke_spin_lock_init(&lock->r_mutex);
ke_spin_lock_init(&lock->res_lock);
ke_spin_lock_init(&lock->r_try);
lock->reader_ct = 0;
lock->writer_ct = 0;
}
return;
}
void ke_rwwlock_reader_lock(k_rwwlock_t *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);
}
return;
}
void ke_rwwlock_reader_unlock(k_rwwlock_t *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);
}
return;
}
void ke_rwwlock_writer_lock(k_rwwlock_t *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_rwwlock_writer_unlock(k_rwwlock_t *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);
}
irql_t ke_rwwlock_reader_lock_raise_irql(k_rwwlock_t *lock, irql_t irql)
{
irql_t old_irql = ke_raise_irql(irql);
ke_rwwlock_reader_lock(lock);
return old_irql;
}
void ke_rwwlock_reader_unlock_lower_irql(k_rwwlock_t *lock, irql_t irql)
{
ke_rwwlock_reader_unlock(lock);
ke_lower_irql(irql);
return;
}
irql_t ke_rwwlock_writer_lock_raise_irql(k_rwwlock_t *lock, irql_t irql)
{
irql_t old_irql = ke_raise_irql(irql);
ke_rwwlock_writer_lock(lock);
return old_irql;
}
void ke_rwwlock_writer_unlock_lower_irql(k_rwwlock_t *lock, irql_t irql)
{
ke_rwwlock_writer_unlock(lock);
ke_lower_irql(irql);
return;
}

View File

@ -1,49 +0,0 @@
#include "kernel/ke/atomic.h"
#include "kernel/ke/spin_lock.h"
void KABI ke_spin_lock_init(k_spin_lock_t *lock)
{
if (lock != NULL)
{
lock->val = 0;
}
}
void KABI ke_spin_lock(k_spin_lock_t *lock)
{
if (lock != NULL)
{
while (ke_interlocked_compare_exchange_32(&lock->val, 0, 1) != 0);
}
return;
}
void KABI ke_spin_unlock(k_spin_lock_t *lock)
{
if (lock != NULL)
{
lock->val = 0;
}
return;
}
irql_t KABI ke_spin_lock_raise_irql(k_spin_lock_t *lock, irql_t irql)
{
irql_t prev_irql = ke_get_irql();
if (lock != NULL)
{
ke_raise_irql(irql);
ke_spin_lock(lock);
}
return prev_irql;
}
void KABI ke_spin_unlock_lower_irql(k_spin_lock_t *lock, irql_t irql)
{
if (lock != NULL)
{
ke_spin_unlock(lock);
ke_lower_irql(irql);
}
return;
}

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,188 +0,0 @@
#include "kernel/ke/assert.h"
#include "kernel/ke/rwwlock.h"
#include "status.h"
#include "kernel/ke/alloc.h"
#include "kernel/mm/pmm.h"
typedef struct
{
linked_list_node_t free_list_node;
avl_tree_node_t avl_tree_node;
uintptr_t base;
int32_t attr;
} physical_page_descriptor_t;
static avl_tree_t active_tree;
static linked_list_t free_list;
static k_rwwlock_t lock;
static _Bool initialized;
/*
* 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_t mmp_base_paddr_compare(void *tree_node, void *my_node)
{
uintptr_t tree_base = OBTAIN_STRUCT_ADDR(tree_node,
physical_page_descriptor_t,
avl_tree_node)->base;
uintptr_t my_base = OBTAIN_STRUCT_ADDR(my_node,
physical_page_descriptor_t,
avl_tree_node)->base;
if (tree_base > my_base)
return 1;
else if (tree_base < my_base)
return -1;
else
return 0;
}
status_t KABI sx_pmm_init(pmm_info_t *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_t 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_t 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 :)
physical_page_descriptor_t *page_info = ke_alloc(sizeof(physical_page_descriptor_t));
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_SUCCESS;
}
// 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
status_t KABI mm_alloc_page(uintptr_t *out)
{
if (!initialized)
{
return MM_UNINITIALIZED;
}
if (out == NULL)
{
return MM_INVALID_ARGUMENTS;
}
irql_t irql = ke_rwwlock_writer_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
status_t result = STATUS_SUCCESS;
linked_list_node_t *node = NULL;
physical_page_descriptor_t *page_info = NULL;
node = lb_linked_list_pop_front(&free_list);
if (node != NULL)
{
page_info = OBTAIN_STRUCT_ADDR(node,
physical_page_descriptor_t,
free_list_node);
lb_avl_tree_insert(&active_tree, &page_info->avl_tree_node);
*out = page_info->base;
} else
{
result = MM_NOT_ENOUGH_PAGE;
}
ke_rwwlock_writer_unlock_lower_irql(&lock, irql);
return result;
}
status_t KABI mm_query_page_attr(uintptr_t base,
int32_t *out)
{
if (!initialized)
{
return MM_UNINITIALIZED;
}
if (out == NULL)
{
return MM_INVALID_ARGUMENTS;
}
irql_t irql = ke_rwwlock_reader_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
status_t result = STATUS_SUCCESS;
avl_tree_node_t *node = NULL;
// search for dummy
physical_page_descriptor_t dummy, *page_info = NULL;
dummy.base = base;
node = lb_avl_tree_delete(&active_tree, &dummy.avl_tree_node);
if (node != NULL)
{
page_info = OBTAIN_STRUCT_ADDR(node, physical_page_descriptor_t, avl_tree_node);
*out = page_info->attr;
} else
{
result = MM_INVALID_ARGUMENTS;
}
ke_rwwlock_reader_unlock_lower_irql(&lock, irql);
return result;
}
status_t KABI mm_free_page(uintptr_t base)
{
if (!initialized)
{
return MM_UNINITIALIZED;
}
// just lock since not sharing with anyone
irql_t irql = ke_rwwlock_writer_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
status_t result = STATUS_SUCCESS;
avl_tree_node_t *node = NULL;
// search for dummy
physical_page_descriptor_t dummy, *page_info;
dummy.base = base;
node = lb_avl_tree_delete(&active_tree, &dummy.avl_tree_node);
if (node != NULL)
{
page_info = OBTAIN_STRUCT_ADDR(node, physical_page_descriptor_t, avl_tree_node);
lb_linked_list_push_back(&free_list, &page_info->free_list_node);
} else
{
result = MM_INVALID_ARGUMENTS;
}
ke_rwwlock_writer_unlock_lower_irql(&lock, 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,303 +0,0 @@
#include "kernel/rf/ref.h"
#include "kernel/ke/alloc.h"
#include "kernel/ke/spin_lock.h"
#include "kernel/ke/assert.h"
#include "kernel/ke/atomic.h"
#include "lib/avl_tree.h"
#include "status.h"
typedef struct
{
avl_tree_node_t tree_node;
handle_t handle;
ref_node_t *ref;
callback_func_t free_routine;
} handle_node_t;
static int32_t rfp_handle_node_free(void *node, void *up)
{
UNREFERENCED(up);
ke_free(node);
return 0;
}
// ===========================
// Ke Functions
// ===========================
static avl_tree_t handle_tree;
static bool initialized;
static k_spin_lock_t handle_tree_lock;
static int32_t handle_base;
static int32_t rfp_handle_compare(void *tree_node, void *my_node)
{
handle_node_t *tcb = OBTAIN_STRUCT_ADDR(tree_node, handle_node_t, tree_node);
handle_node_t *my_tcb = OBTAIN_STRUCT_ADDR(my_node, handle_node_t, tree_node);
if ((uintptr_t) tcb->handle > (uintptr_t) my_tcb->handle)
return -1;
else if ((uintptr_t) tcb->handle == (uintptr_t) my_tcb->handle)
return 0;
else
return 1;
}
static handle_node_t *rfp_search_handle_node(handle_t handle)
{
avl_tree_node_t *result;
handle_node_t temp;
temp.handle = handle;
result = lb_avl_tree_search(&handle_tree, &temp.tree_node);
return result == NULL ? NULL : OBTAIN_STRUCT_ADDR(result, handle_node_t, tree_node);
}
status_t KABI rf_reference_setup(void)
{
if (!initialized)
{
lb_avl_tree_init(&handle_tree, rfp_handle_compare);
ke_spin_lock_init(&handle_tree_lock);
handle_base = K_HANDLE_BASE;
initialized = true;
}
return STATUS_SUCCESS;
}
status_t KABI rf_reference_create(ref_node_t *ref,
callback_func_t free_func)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (ref == NULL || free_func == NULL)
return RF_INVALID_ARGUMENTS;
ref->free_routine = free_func;
ref->ref_count = 1;
return STATUS_SUCCESS;
}
status_t KABI rf_reference_obj(ref_node_t *ref_node)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (ref_node == NULL)
return RF_INVALID_ARGUMENTS;
int32_t old_ref_count = ke_interlocked_increment_32(&ref_node->ref_count, 1);
ke_assert(old_ref_count >= 1);
return STATUS_SUCCESS;
}
status_t KABI rf_dereference_obj(ref_node_t *ref_node)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (ref_node == NULL)
return RF_INVALID_ARGUMENTS;
status_t result = STATUS_SUCCESS;
int32_t old_ref_count = ke_interlocked_increment_32(&ref_node->ref_count, -1);
ke_assert(old_ref_count >= 1);
if (old_ref_count == 1)
{
ref_node->free_routine(ref_node, NULL);
}
return result;
}
static status_t KABI rf_open_obj_by_handle(handle_t handle, ref_node_t **out)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
{
return RF_UNINITIALIZED;
}
if (out == NULL)
{
return RF_INVALID_ARGUMENTS;
}
irql_t irql;
status_t status = STATUS_SUCCESS;
ref_node_t *ref = NULL;
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
handle_node_t *handle_node = rfp_search_handle_node(handle);
if (handle_node == NULL)
{
status = RF_INVALID_HANDLE;
} else
{
ref = handle_node->ref;
}
// 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_reference_obj(ref);
*out = ref;
}
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
return status;
}
static status_t KABI rf_create_handle(ref_node_t *ref,
handle_node_t *node,
handle_t *out)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
return RF_UNINITIALIZED;
if (ref == NULL || node == NULL || out == NULL)
return RF_INVALID_ARGUMENTS;
status_t result = STATUS_SUCCESS;
irql_t irql;
if (sx_success(result))
{
// TODO: CHECK OVERFLOW
node->handle = (handle_t) ke_interlocked_increment_32(&handle_base, 1);
node->ref = ref;
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
handle_node_t *existing_node = rfp_search_handle_node(node->handle);
if (existing_node == NULL)
{
lb_avl_tree_insert(&handle_tree, &node->tree_node);
} else
{
result = RF_DUPLICATED_HANDLE;
}
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
}
if (sx_success(result))
{
rf_reference_obj(ref);
*out = node->handle;
} else
{
node->free_routine(node, NULL);
}
return result;
}
static status_t KABI rf_close_handle(handle_t handle)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
return RF_UNINITIALIZED;
irql_t irql;
status_t status = STATUS_SUCCESS;
ref_node_t *ref = NULL;
bool free = false;
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
handle_node_t *handle_node = rfp_search_handle_node(handle);
if (handle_node == NULL)
{
status = RF_INVALID_HANDLE;
} else
{
ref = handle_node->ref;
lb_avl_tree_delete(&handle_tree, &handle_node->tree_node);
free = true;
}
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
if (free)
{
handle_node->free_routine(handle_node, NULL);
}
if (sx_success(status))
{
// dereference the object
rf_dereference_obj(ref);
}
return status;
}
// ===========================
// SX Functions
// ===========================
status_t KABI sx_create_handle(ref_node_t *ref, handle_t *out)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
return RF_UNINITIALIZED;
handle_node_t *node;
node = (handle_node_t *) ke_alloc(sizeof(handle_node_t));
if (node == NULL)
{
return RF_ALLOCATION_FAILED;
}
node->free_routine = rfp_handle_node_free;
return rf_create_handle(ref, node, out);
}
status_t KABI sx_close_handle(handle_t handle)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
return RF_UNINITIALIZED;
// need to keep sx version since need to do handle check here
return rf_close_handle(handle);
}
status_t KABI sx_open_obj_by_handle(handle_t handle, ref_node_t **out)
{
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
if (!initialized)
return RF_UNINITIALIZED;
if (out == NULL)
return RF_INVALID_ARGUMENTS;
// check special handles first
// if (handle == K_HANDLE_CURRENT_THREAD)
// {
// // no need to ref first since definitely current thread context
// hw_tcb_t *tcb = ke_current_thread();
// ke_reference_obj(&tcb->ref_node);
// *out = &tcb->ref_node;
// return STATUS_SUCCESS;
// }
return rf_open_obj_by_handle(handle, out);
}

View File

@ -1,10 +0,0 @@
include $(MK)/prologue.mk
SRC_$(d) := $(d)/avl_tree.c \
$(d)/linked_list.c \
$(d)/salloc.c \
$(d)/sxtdlib.c
include $(MK)/stdrules.mk
include $(MK)/epilogue.mk

View File

@ -1,489 +0,0 @@
/* Copyright 2016 secXsQuared
* Distributed under GPL license
* See COPYING under root for details
*/
#include "lib/avl_tree.h"
static inline int32_t KABI lbp_avl_tree_node_get_height(avl_tree_node_t *node)
{
return node == NULL ? -1 : node->height;
}
static inline int32_t KABI lbp_avl_tree_node_get_balance_factor(avl_tree_node_t *node)
{
if (node == NULL)
return 0;
return lbp_avl_tree_node_get_height(node->left) - lbp_avl_tree_node_get_height(node->right);
}
static avl_tree_node_t *KABI lbp_avl_tree_node_right_rotate(avl_tree_node_t *root)
{
avl_tree_node_t *left_children = root->left;
//adjust parents first
left_children->parent = root->parent;
root->parent = left_children;
if (left_children->right != NULL)
left_children->right->parent = root;
//perform rotation
root->left = root->left->right;
left_children->right = root;
//adjust height
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
left_children->height =
lb_max_32(lbp_avl_tree_node_get_height(left_children->left),
lbp_avl_tree_node_get_height(left_children->right)) + 1;
return left_children;
}
static avl_tree_node_t *KABI lbp_avl_tree_node_left_rotate(avl_tree_node_t *root)
{
avl_tree_node_t *right_children = root->right;
//adjust parents
right_children->parent = root->parent;
root->parent = right_children;
if (right_children->left != NULL)
right_children->left->parent = root;
//perform rotation
root->right = root->right->left;
right_children->left = root;
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
right_children->height =
lb_max_32(lbp_avl_tree_node_get_height(right_children->left),
lbp_avl_tree_node_get_height(right_children->right)) +
1;
return right_children;
}
static avl_tree_node_t *KABI lbp_avl_tree_node_balance(avl_tree_node_t *node)
{
const int32_t bf = lbp_avl_tree_node_get_balance_factor(node);
if (bf > 1)
{
const int32_t left_bf = lbp_avl_tree_node_get_balance_factor(node->left);
if (left_bf >= 0)
//left left
return lbp_avl_tree_node_right_rotate(node);
else
{
//left right
node->left = lbp_avl_tree_node_left_rotate(node->left);
return lbp_avl_tree_node_right_rotate(node);
}
}
else if (bf < -1)
{
const int32_t right_bf = lbp_avl_tree_node_get_balance_factor(node->right);
if (right_bf <= 0)
{
// right right
return lbp_avl_tree_node_left_rotate(node);
}
else
{
// right left
node->right = lbp_avl_tree_node_right_rotate(node->right);
return lbp_avl_tree_node_left_rotate(node);
}
}
else
return node;
}
static avl_tree_node_t *KABI lbp_avl_tree_node_insert(avl_tree_node_t *root, avl_tree_node_t *node,
callback_func_t compare,
avl_tree_node_t *parent)
{
if (node == NULL || compare == NULL)
return root;
if (root == NULL)
{
node->parent = parent;
return node;
}
const int32_t comp = compare(root, node);
if (comp < 0)
root->right = lbp_avl_tree_node_insert(root->right, node, compare, root);
else if (comp == 0)
return root;
else
root->left = lbp_avl_tree_node_insert(root->left, node, compare, root);
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
return lbp_avl_tree_node_balance(root);
}
static void lbp_avl_tree_swap_nodes(avl_tree_node_t *node1, avl_tree_node_t *node2)
{
if (node1 == NULL || node2 == NULL)
return;
avl_tree_node_t *parent = NULL;
avl_tree_node_t *child = NULL;
avl_tree_node_t *temp = NULL;
//swap node but does not change anything else other than node1,node2
if (node1->parent != NULL && node1->parent == node2)
{
parent = node2;
child = node1;
}
else if (node2->parent != NULL && node2->parent == node1)
{
parent = node1;
child = node2;
}
if (parent != NULL && child != NULL)
{
//connected case
if (parent->parent != NULL)
{
if (parent->parent->left == parent)
parent->parent->left = child;
else
parent->parent->right = child;
}
//update left/right for parent
if (parent->left != NULL && child != parent->left)
{
parent->left->parent = child;
}
if (parent->right != NULL && child != parent->right)
{
parent->right->parent = child;
}
//update left/right for children
if (child->left != NULL)
child->left->parent = parent;
if (child->right != NULL)
child->right->parent = parent;
child->parent = parent->parent;
parent->parent = child;
if (child == parent->left)
{
/* parent
/ \
children */
parent->left = child->left;
child->left = parent;
temp = parent->right;
parent->right = child->right;
child->right = temp;
}
else
{
/* parent
/ \
children */
parent->right = child->right;
child->right = parent;
temp = parent->left;
parent->left = child->left;
child->left = temp;
}
}
else
{
//not connected case
//adjust all the nodes other than node1,node2
if (node1->left != NULL)
node1->left->parent = node2;
if (node1->right != NULL)
node1->right->parent = node2;
if (node2->left != NULL)
node2->left->parent = node1;
if (node2->right != NULL)
node2->right->parent = node1;
if (node1->parent != NULL)
{
if (node1->parent->left == node1)
node1->parent->left = node2;
else
node1->parent->right = node2;
}
if (node2->parent != NULL)
{
if (node2->parent->left == node2)
node2->parent->left = node1;
else
node2->parent->right = node1;
}
//adjust node1,node2
temp = node1->parent;
node1->parent = node2->parent;
node2->parent = temp;
temp = node1->left;
node1->left = node2->left;
node2->left = temp;
temp = node1->right;
node1->right = node2->right;
node2->right = temp;
}
//swap height
int32_t height = node1->height;
node1->height = node2->height;
node2->height = height;
return;
}
static avl_tree_node_t *KABI lbp_avl_tree_node_delete(avl_tree_node_t *root,
avl_tree_node_t *node,
callback_func_t compare,
avl_tree_node_t **deleted_node)
{
if (root == NULL || node == NULL || compare == NULL || deleted_node == NULL)
return root;
const int32_t comp = compare(root, node);
if (comp < 0)
root->right = lbp_avl_tree_node_delete(root->right, node, compare, deleted_node);
else if (comp > 0)
root->left = lbp_avl_tree_node_delete(root->left, node, compare, deleted_node);
else
{
*deleted_node = root;
// node with only one child or no child
if ((root->left == NULL) || (root->right == NULL))
{
avl_tree_node_t *child = root->left != NULL ? root->left : root->right;
if (child == NULL)
{ // 0 child
root = NULL;
}
else // 1 child
{
child->parent = root->parent;
root = child;
}
}
else
{
// node with two children: Get the inorder successor (smallest
// in the right subtree)
avl_tree_node_t *successor = lb_avl_tree_larger(root);
//swap fields
lbp_avl_tree_swap_nodes(successor, root);
// Detach the inorder successor
successor->right = lbp_avl_tree_node_delete(successor->right, root, compare, deleted_node);
root = successor;
}
}
if (root == NULL)
return root;
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
root = lbp_avl_tree_node_balance(root);
return root;
}
static avl_tree_node_t *KABI lbp_avl_tree_node_search(avl_tree_node_t *root, avl_tree_node_t *node,
callback_func_t compare)
{
if (root == NULL || compare == NULL)
return NULL;
const int32_t comp = compare(root, node);
if (comp < 0)
return lbp_avl_tree_node_search(root->right, node, compare);
else if (comp == 0)
return root;
else
return lbp_avl_tree_node_search(root->left, node, compare);
}
static void KABI lbp_avl_tree_node_init(avl_tree_node_t *it)
{
if (it != NULL)
{
it->height = 0;
it->left = NULL;
it->right = NULL;
it->parent = NULL;
}
return;
}
avl_tree_node_t *KABI lb_avl_tree_smallest(avl_tree_t *tree)
{
if (tree == NULL)
return NULL;
avl_tree_node_t *entry = tree->root;
if (entry == NULL)
return NULL;
while (entry->left != NULL)
entry = entry->left;
return entry;
}
avl_tree_node_t *KABI lb_avl_tree_largest(avl_tree_t *tree)
{
if (tree == NULL)
return NULL;
avl_tree_node_t *entry = tree->root;
if (entry == NULL)
return NULL;
while (entry->right != NULL)
entry = entry->right;
return entry;
}
avl_tree_node_t *KABI lb_avl_tree_larger(avl_tree_node_t *it)
{
if (it == NULL)
return NULL;
avl_tree_node_t *root = it;
if (root->right != NULL)
{
root = root->right;
while (root->left != NULL)
root = root->left;
return root;
}
else
{
while (root->parent != NULL)
{
if (root->parent->left == root)
return root->parent;
root = root->parent;
}
return NULL;
}
}
avl_tree_node_t *KABI lb_avl_tree_smaller(avl_tree_node_t *it)
{
if (it == NULL)
return NULL;
avl_tree_node_t *root = it;
if (root->left != NULL)
{
root = root->left;
while (root->right != NULL)
root = root->right;
return root;
}
else
{
while (root->parent != NULL)
{
if (root->parent->right == root)
return root->parent;
root = root->parent;
}
return NULL;
}
}
avl_tree_node_t *KABI lb_avl_tree_search(avl_tree_t *tree, avl_tree_node_t *node)
{
return lbp_avl_tree_node_search(tree->root, node, tree->compare);
}
void KABI lb_avl_tree_insert(avl_tree_t *tree, avl_tree_node_t *data)
{
if (tree != NULL && data != NULL)
{
lbp_avl_tree_node_init(data);
tree->root = lbp_avl_tree_node_insert(tree->root, data, tree->compare, NULL);
}
return;
}
avl_tree_node_t *KABI lb_avl_tree_delete(avl_tree_t *tree, avl_tree_node_t *data)
{
avl_tree_node_t *node = NULL;
if (tree != NULL && data != NULL)
{
tree->root = lbp_avl_tree_node_delete(tree->root, data, tree->compare, &node);
}
return node;
}
int32_t KABI lb_avl_tree_size(avl_tree_t *tree)
{
if (tree == NULL)
return -1;
if (tree->root == NULL)
return 0;
int32_t size = 0;
avl_tree_node_t *entry = lb_avl_tree_smallest(tree);
while (entry != NULL)
{
size++;
entry = lb_avl_tree_larger(entry);
}
return size;
}
void KABI lb_avl_tree_init(avl_tree_t *tree, callback_func_t compare)
{
if (tree != NULL)
{
tree->compare = compare;
tree->root = NULL;
}
return;
}
// TESTING STUFF
static int32_t KABI lbp_avl_tree_node_calculate_height(avl_tree_node_t *tree)
{
if (tree == NULL)
return -1;
return lb_max_32(lbp_avl_tree_node_calculate_height(tree->left), lbp_avl_tree_node_calculate_height(tree->right)) + 1;
}
static bool KABI lbp_avl_tree_node_test(avl_tree_node_t *tree, callback_func_t compare)
{
if (tree == NULL)
return true;
if (lbp_avl_tree_node_get_balance_factor(tree) < -1 || lbp_avl_tree_node_get_balance_factor(tree) > 1 ||
lbp_avl_tree_node_calculate_height(tree) != tree->height)
return false;
if (tree->left != NULL)
{
if (tree->left->parent != tree)
return false;
}
if (tree->right != NULL)
{
if (tree->right->parent != tree)
return false;
}
if (compare != NULL)
{
if ((tree->right != NULL && compare(tree, tree->right) > 0) ||
(tree->left != NULL && compare(tree, tree->left) < 0))
return false;
}
return lbp_avl_tree_node_test(tree->left, compare) && lbp_avl_tree_node_test(tree->right, compare);
}
bool KABI lb_avl_tree_validate(avl_tree_t *tree)
{
if (tree == NULL)
return true;
return lbp_avl_tree_node_test(tree->root, tree->compare);
}

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