Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
530fac0
ci(github-actions): add macOS build workflow
Galfurian Feb 3, 2026
86a8da4
feature(kernel): enable FHS initialization
Galfurian Feb 3, 2026
a4ca43b
Merge pull request #172 from mentos-team/feature/enable-fhs-initializ…
Galfurian Feb 3, 2026
24bd634
feat(test): refine unit test framework
Galfurian Feb 3, 2026
da28279
refactor(test): move GDT-specific helpers to test_gdt.c
Galfurian Feb 3, 2026
74fc233
test(gdt): add pointer configuration verification
Galfurian Feb 3, 2026
e7eb5da
test(gdt): add user mode code segment (entry 3) verification
Galfurian Feb 3, 2026
dee06d3
test(gdt): add user mode data segment (entry 4) verification
Galfurian Feb 3, 2026
8ad67c7
test(gdt): add TSS descriptor verification
Galfurian Feb 3, 2026
e813445
test(gdt): verify privilege levels for kernel and user segments
Galfurian Feb 3, 2026
9e96139
test(gdt): verify granularity and operand size flags
Galfurian Feb 3, 2026
c9d4b6d
test(gdt): verify base and limit for code/data segments
Galfurian Feb 3, 2026
b280142
test(gdt): verify unused GDT entries are zeroed
Galfurian Feb 3, 2026
65106fb
test(gdt): verify kernel code/data access bytes
Galfurian Feb 3, 2026
09d1cb9
build(kernel): enable glob configure depends
Galfurian Feb 3, 2026
b0e461c
test(idt): add IDT unit test suite
Galfurian Feb 3, 2026
dbd5c45
test(isr): add ISR unit test suite
Galfurian Feb 3, 2026
6501e1f
test(paging): add paging subsystem unit tests
Galfurian Feb 3, 2026
584229a
test(scheduler): add scheduler subsystem unit tests
Galfurian Feb 3, 2026
aa85ca2
test(paging): enhance with 25 comprehensive stress tests
Galfurian Feb 3, 2026
a0dc5a0
style(tests): change log level from DEBUG to NOTICE
Galfurian Feb 3, 2026
b6efe7e
test(memory): split memory tests into suites
Galfurian Feb 4, 2026
029155c
fix(paging): guard mem_virtual_to_page
Galfurian Feb 4, 2026
7258ae7
fix(mm): skip non-present pages
Galfurian Feb 4, 2026
b14977c
test(memory): extend memory suites
Galfurian Feb 4, 2026
3573136
test(memory): add write/read and leak checks
Galfurian Feb 4, 2026
dd33b2c
test(memory): add stress leak checks
Galfurian Feb 4, 2026
6a65f4c
test(mm): add deep clone and leak checks
Galfurian Feb 4, 2026
39a8024
test(mm): add vma fuzz and multi-page clone
Galfurian Feb 4, 2026
d713b62
test(memory): add before/after memory state checks to all tests
Galfurian Feb 4, 2026
9e44862
test(memory): add buddy system and page structure tests
Galfurian Feb 4, 2026
312e184
test(memory): integrate edge case tests into existing subsystem test …
Galfurian Feb 4, 2026
3a0bb6e
test(memory): add comprehensive adversarial and DMA physical addressi…
Galfurian Feb 4, 2026
b373309
Merge pull request #173 from mentos-team/feature/refine-unit-test-fra…
Galfurian Feb 4, 2026
c8aee8a
feat(dma-zone): Implement DMA zone with proper bootloader and paging …
Galfurian Feb 4, 2026
bceb839
fix(memory): relocate DMA zone virtual mapping to avoid user space co…
Galfurian Feb 4, 2026
7b7cea8
test(memory): reduce DMA zone allocation test to realistic sizes
Galfurian Feb 4, 2026
db21638
test(memory): add dedicated DMA test suite
Galfurian Feb 4, 2026
8c871bb
test(memory): assert DMA zone fits ISA limit
Galfurian Feb 4, 2026
5fb78a6
test(memory): enforce ISA limit per DMA allocation
Galfurian Feb 4, 2026
66a574b
test(memory): add full DMA exhaustion recovery
Galfurian Feb 4, 2026
0c998c3
test(memory): ensure DMA allocation reaches last page
Galfurian Feb 4, 2026
7f54bf1
test(memory): ensure DMA allocation reaches first page
Galfurian Feb 4, 2026
009ec34
test(memory): add DMA first-page translation check
Galfurian Feb 4, 2026
b6bcd3b
test(memory): add DMA last-page translation check
Galfurian Feb 4, 2026
593fbe2
test(memory): verify DMA virt_end is invalid
Galfurian Feb 4, 2026
329ba83
test(memory): relax DMA first-page boundary check
Galfurian Feb 4, 2026
3bd2c0c
test(memory): add large-order DMA contiguity test
Galfurian Feb 4, 2026
9bf464b
test(memory): add DMA mixed-order stress
Galfurian Feb 4, 2026
7c87b6a
test(paging): verify DMA PDE flags
Galfurian Feb 4, 2026
b90e821
test(memory): fix DMA stress array sizes
Galfurian Feb 4, 2026
c0a737a
test(memory): add LowMem boundary page checks
Galfurian Feb 4, 2026
23f8c0e
test(memory): add HighMem boundary page checks
Galfurian Feb 4, 2026
622791e
test(memory): add DMA zone isolation check
Galfurian Feb 4, 2026
aaaa8bd
test(memory): check buddy status includes zone name
Galfurian Feb 4, 2026
cb8968b
test(memory): expand zone allocator space checks
Galfurian Feb 4, 2026
244d4e4
test(memory): add cached space behavior check
Galfurian Feb 4, 2026
73a68e0
test(memory): validate page_index_max
Galfurian Feb 4, 2026
ce42523
test(memory): add max supported order buddy test
Galfurian Feb 4, 2026
c13fc64
test(memory): add DMA fragmentation buddy test
Galfurian Feb 4, 2026
6ed85b5
test(memory): add cross-zone buddy accounting
Galfurian Feb 4, 2026
0971321
test(memory): add HighMem page mapping check
Galfurian Feb 4, 2026
7cb18c2
test(memory): check DMA page virtual range
Galfurian Feb 4, 2026
69607d6
test(memory): validate LowMem virt-phys offset
Galfurian Feb 4, 2026
42875a1
test(paging): verify DMA PDE coverage
Galfurian Feb 4, 2026
efcb73f
test(paging): fix DMA/user PDE separation verification
Galfurian Feb 4, 2026
c72fc63
test(paging): add DMA mapping permissions verification
Galfurian Feb 4, 2026
5eb0b05
refactor(tests): move integration tests to test_dma.c and remove inte…
Galfurian Feb 4, 2026
2a9d81e
test(vmem): add mapping collision, range, and idempotence tests
Galfurian Feb 4, 2026
d2bd48c
test(memory): add HighMem, VMEM, and buddy tests; add is_highmem_page…
Galfurian Feb 4, 2026
a266dd0
fix(test_slab): correct kmalloc signature (no GFP flags parameter)
Galfurian Feb 4, 2026
77a04d6
test(memory): fix MM/VMA and Slab tests (signatures and flags)
Galfurian Feb 4, 2026
183bc4f
test(memory): fix overlapping VMA rejection test to check map_count c…
Galfurian Feb 4, 2026
4767f41
test(memory): add TLB consistency and stack VMA lifecycle tests
Galfurian Feb 4, 2026
ef3bf63
Merge pull request #174 from mentos-team/feature/dma-zone-implementation
Galfurian Feb 4, 2026
1437bcb
fix(vsprintf): handle NULL string pointers gracefully
Galfurian Feb 4, 2026
53e2823
fix(elf): disable COW for initial PT_LOAD segments
Galfurian Feb 4, 2026
2a15d4a
fix(mm): disable COW for initial user stack
Galfurian Feb 4, 2026
a471862
fix(timer): only schedule on user-mode interrupts
Galfurian Feb 4, 2026
7ff97af
refactor(ps2): improve code organization with section headers and fix…
Galfurian Feb 6, 2026
13522fa
refactor(ps2): extract helper functions for common patterns
Galfurian Feb 6, 2026
3c9e73f
fix(rtc): use inline assembly to prevent Release-mode optimization
Galfurian Feb 6, 2026
065fec2
refactor(rtc): consolidate CMOS reads into single helper function
Galfurian Feb 6, 2026
d8c96eb
Set notice as debug level in RTC.
Galfurian Feb 6, 2026
483d79a
fix(test_paging): resolve Release-mode failures in paging unit tests
Galfurian Feb 6, 2026
3bd552c
refactor(exception): simplify ISR macros and normalize pt_regs stack …
Galfurian Feb 6, 2026
4bbcda8
fix(exception): simplify ISR handling and make PRINT_REGS safe for ke…
Galfurian Feb 6, 2026
4b1f0dd
fix(Release): volatile reads in spinlocks, mutexes, and scheduler con…
Galfurian Feb 6, 2026
c3fce4e
fix(timer): volatile reads on timer_ticks in event loop
Galfurian Feb 6, 2026
dee1db5
fix(timer): correct volatile cast type from uint32_t to unsigned long
Galfurian Feb 6, 2026
75ca640
fix(syscall): return negative ENOSYS for invalid syscall numbers
Galfurian Feb 8, 2026
e195740
Merge pull request #176 from mentos-team/fix/syscall-enosys-return-value
Galfurian Feb 8, 2026
52d8b54
Merge branch 'develop' into feature/debug-double-fault
Galfurian Feb 9, 2026
15eeb3a
fix(io): correct I/O port inline assembly constraints
Galfurian Feb 9, 2026
2d3cc85
chore: revert temporary debug changes
Galfurian Feb 9, 2026
2222860
chore(kernel): tidy logging in ps2 and allocators
Galfurian Feb 9, 2026
8c23381
build(cmake): adjust qemu and optimization flags
Galfurian Feb 9, 2026
6ffe51c
refactor(stack): replace stack macros with helpers
Galfurian Feb 9, 2026
48d4665
fix(module): treat missing modules as success
Galfurian Feb 9, 2026
a6bb45d
fix(fpu): handle default SIGILL
Galfurian Feb 9, 2026
ab1723b
style(signal): align signal enum
Galfurian Feb 9, 2026
f7b9644
fix(tests): Fix some of the tests.
Galfurian Feb 9, 2026
449263f
Merge pull request #177 from mentos-team/feature/debug-double-fault
Galfurian Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: macOS

# Trigger the workflow on push or pull requests for main and develop branches
on:
push:
branches:
- main
- develop
paths:
- '**/*.c'
- '**/*.cpp'
- '**/*.h'
- '**/*.hpp'
- '**/*.S'
- '**/*.asm'
- '**/CMakeLists.txt'
- '**/Makefile'
- '**/cmake/**'
- '**/tools/toolchain-i686-elf.cmake'
- '.github/workflows/macos.yml'
pull_request:
branches:
- main
- develop
paths:
- '**/*.c'
- '**/*.cpp'
- '**/*.h'
- '**/*.hpp'
- '**/*.S'
- '**/*.asm'
- '**/CMakeLists.txt'
- '**/Makefile'
- '**/cmake/**'
- '**/tools/toolchain-i686-elf.cmake'
- '.github/workflows/macos.yml'

jobs:
build:
name: Build and Compile (macOS)
strategy:
fail-fast: false
matrix:
include:
# macOS runners come with clang, we test with the system clang
# i686-elf-gcc is installed via Homebrew for cross-compilation
- { os: macos-14, arch: "Intel" }
- { os: macos-14-large, arch: "Apple Silicon" }
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: Clone repository
uses: actions/checkout@v4

- name: Install dependencies via Homebrew
run: |
# Update Homebrew
brew update || true

# Install required tools
brew install nasm cmake

# Install cross-compiler for i386 (bare-metal)
# This is critical - we need i686-elf-gcc, not i686-linux-gnu
brew install i686-elf-gcc

# Verify installation
echo "=== Checking installed tools ==="
nasm --version
cmake --version
i686-elf-gcc --version

- name: Build with cross-compilation toolchain
run: |
# Create build directory
mkdir -p build
cd build

# Configure with the i686-elf toolchain file
# This is essential for macOS (which is ARM-based)
cmake .. -DCMAKE_TOOLCHAIN_FILE=../tools/toolchain-i686-elf.cmake \
-DCMAKE_BUILD_TYPE=Release

# Build all targets
cmake --build . --parallel $(sysctl -n hw.ncpu)

- name: Verify build artifacts
run: |
echo "=== Build artifacts ==="
ls -lh build/mentos/ || echo "mentos/ not found"
ls -lh build/*.bin 2>/dev/null || echo "*.bin files not found"
file build/mentos/bootloader.bin 2>/dev/null || echo "bootloader.bin not found"

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,5 @@ iso/boot/*.bin

# Wiki content (do not commit)
WIKI/
# Summary documentation files (do not commit)
*.summary.md
53 changes: 29 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ cmake_minimum_required(VERSION 3.1...3.22)
# Initialize the project.
project(mentos C ASM)

# Set the default build type to Debug.
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to 'Debug' as none was specified.")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
endif()
# Add the CMAKE_BUILD_TYPE option with the full list of possible values.
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build: Debug, Release, RelWithDebInfo, MinSizeRel")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel")

# -----------------------------------------------------------------------------
# ENABLE FETCH CONTENT
Expand Down Expand Up @@ -48,21 +46,21 @@ if((${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin") OR APPLE)
# Specify the linker flags.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib")
elseif((${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") OR WIN32)
# Windows set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -sdl)
# Windows set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -sdl)
else()
# Generic Unix System.
# Find the `lsb_release` program.
find_program(LSB_RELEASE_EXEC lsb_release HINTS /usr/bin/ /usr/local/bin/)
mark_as_advanced(LSB_RELEASE_EXEC)

if(LSB_RELEASE_EXEC)
execute_process(
COMMAND "${LSB_RELEASE_EXEC}" --short --release
OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "LSB version : ${LSB_RELEASE_VERSION_SHORT}")

# Use GTK display for Ubuntu 19+
if(LSB_RELEASE_VERSION_SHORT MATCHES "^(19|2[0-9])")
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -display gtk)
Expand Down Expand Up @@ -105,7 +103,7 @@ set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O0 -F dwarf -o <OBJECT> <SOURCE>")
else()
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O3 -o <OBJECT> <SOURCE>")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -f elf -g -O2 -o <OBJECT> <SOURCE>")
endif()

# =============================================================================
Expand Down Expand Up @@ -153,7 +151,7 @@ endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -ggdb -O0")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
endif()

# Set the assembly compiler flags.
Expand Down Expand Up @@ -198,9 +196,13 @@ set(EMULATOR qemu-system-i386)
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -vga std)
# Set the amount of memory.
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -m 1096M)
# Set the RTC to use local time.
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -rtc base=localtime)
# Disables all default devices (e.g., serial ports, network cards, VGA
# adapters). Only devices we explicitly specify will be added.
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -nodefaults)
# Disable reboot and shutdown.
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -no-reboot)
# Set the debug type.
if(${EMULATOR_OUTPUT_TYPE} STREQUAL OUTPUT_LOG)
set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -serial file:${CMAKE_BINARY_DIR}/serial.log)
Expand Down Expand Up @@ -271,11 +273,13 @@ add_custom_target(

# First, we need to build the ISO for the cdrom.
add_custom_target(
cdrom.iso
COMMAND cp -rf ${CMAKE_SOURCE_DIR}/iso .
COMMAND cp ${CMAKE_BINARY_DIR}/mentos/bootloader.bin ${CMAKE_BINARY_DIR}/iso/boot
COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom.iso ${CMAKE_BINARY_DIR}/iso
DEPENDS bootloader.bin
cdrom.iso
COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/iso
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/iso ${CMAKE_BINARY_DIR}/iso
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/mentos/bootloader.bin ${CMAKE_BINARY_DIR}/iso/boot/bootloader.bin
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/iso/boot/grub/grub.cfg ${CMAKE_BINARY_DIR}/iso/boot/grub/grub.cfg
COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom.iso ${CMAKE_BINARY_DIR}/iso
DEPENDS bootloader.bin
)

# This third target runs the emualtor, but this time, the kernel binary file is
Expand All @@ -295,11 +299,12 @@ add_custom_target(
# First, we need to build the ISO for the cdrom. It has a slightly different
# kernel command line including 'test'.
add_custom_target(
cdrom_test.iso
COMMAND cp -rf ${CMAKE_SOURCE_DIR}/iso .
COMMAND mv ${CMAKE_BINARY_DIR}/iso/boot/grub/grub.cfg.runtests ${CMAKE_BINARY_DIR}/iso/boot/grub/grub.cfg
COMMAND cp ${CMAKE_BINARY_DIR}/mentos/bootloader.bin ${CMAKE_BINARY_DIR}/iso/boot
COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom_test.iso ${CMAKE_BINARY_DIR}/iso
cdrom_test.iso
COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/iso_test
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/iso ${CMAKE_BINARY_DIR}/iso_test
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/iso/boot/grub/grub.cfg.runtests ${CMAKE_BINARY_DIR}/iso_test/boot/grub/grub.cfg
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/mentos/bootloader.bin ${CMAKE_BINARY_DIR}/iso_test/boot/bootloader.bin
COMMAND grub-mkrescue -o ${CMAKE_BINARY_DIR}/cdrom_test.iso ${CMAKE_BINARY_DIR}/iso_test
DEPENDS bootloader.bin filesystem
)

Expand All @@ -308,7 +313,7 @@ add_custom_target(
# after the tests are done.
add_custom_target(
qemu-test
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -serial file:${CMAKE_BINARY_DIR}/test.log -nographic -device isa-debug-exit -boot d -cdrom ${CMAKE_BINARY_DIR}/cdrom_test.iso
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -nographic -device isa-debug-exit -boot d -cdrom ${CMAKE_BINARY_DIR}/cdrom_test.iso
DEPENDS cdrom_test.iso
)

Expand Down Expand Up @@ -356,8 +361,8 @@ endif()
# DOCUMENTATION
# -----------------------------------------------------------------------------

if (DOXYGEN_FOUND)
if(DOXYGEN_FOUND)

# FetchContent: Doxygen Awesome CSS
FetchContent_Declare(doxygenawesome
GIT_REPOSITORY https://github.com/jothepro/doxygen-awesome-css
Expand Down Expand Up @@ -431,4 +436,4 @@ if (DOXYGEN_FOUND)
${ALL_PROJECT_FILES}
COMMENT "Generating Doxygen documentation"
)
endif (DOXYGEN_FOUND)
endif(DOXYGEN_FOUND)
5 changes: 4 additions & 1 deletion boot/src/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,13 @@ void boot_main(uint32_t magic, multiboot_info_t *header, uint32_t esp)
// size of the kernel (virt_high - virt_low).
boot_info.kernel_phy_end = boot_info.kernel_phy_start + boot_info.kernel_size;

// Start lowmem right after the kernel end (page-aligned).
// DMA zone will be carved from physical memory below 16MB during zone init.
boot_info.lowmem_phy_start = __align_rup(boot_info.kernel_phy_end, PAGE_SIZE);
boot_info.lowmem_phy_end = 896 * 1024 * 1024; // 896 MB of low memory max
boot_info.lowmem_size = boot_info.lowmem_phy_end - boot_info.lowmem_phy_start;
boot_info.lowmem_virt_start = __align_rup(boot_info.kernel_end, PAGE_SIZE);
// Use linear mapping offset so lowmem virtual addresses match physical addresses.
boot_info.lowmem_virt_start = boot_info.kernel_start + (boot_info.lowmem_phy_start - boot_info.kernel_phy_start);
boot_info.lowmem_virt_end = boot_info.lowmem_virt_start + boot_info.lowmem_size;

boot_info.highmem_phy_start = boot_info.lowmem_phy_end;
Expand Down
2 changes: 1 addition & 1 deletion kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ option(ENABLE_SCHEDULER_FEEDBACK "Enables scheduling feedback on terminal." OFF)

# =============================================================================
# Collect the kernel source files.
file(GLOB_RECURSE KERNEL_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/*.S")
file(GLOB_RECURSE KERNEL_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/*.S")
# Remove the tests from the kernel sources if the tests are disabled.
if(NOT ENABLE_KERNEL_TESTS)
list(FILTER KERNEL_SOURCES EXCLUDE REGEX ".*/tests/.*")
Expand Down
7 changes: 5 additions & 2 deletions kernel/inc/io/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ struct pt_regs;
dbg_fn(" EIP = 0x%-09x\n", (frame)->eip); \
dbg_fn(" CS = 0x%-04x\n", (frame)->cs); \
dbg_fn(" EFLAGS = 0x%-09x\n", (frame)->eflags); \
dbg_fn(" UESP = 0x%-09x\n", (frame)->useresp); \
dbg_fn(" SS = 0x%-04x\n", (frame)->ss); \
/* Only print user mode stack info if exception came from user mode (CS privilege bits = 3) */ \
if (((frame)->cs & 0x3) == 3) { \
dbg_fn(" UESP = 0x%-09x\n", (frame)->useresp); \
dbg_fn(" SS = 0x%-04x\n", (frame)->ss); \
} \
} while (0)
120 changes: 104 additions & 16 deletions kernel/inc/klib/stack_helper.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,110 @@
/// @file stack_helper.h
/// @brief Couple of macros that help accessing the stack.
/// @brief Inline functions for safe stack manipulation with proper sequencing.
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.

#pragma once

/// @brief Access the value of the pointer.
#define __ACCESS_PTR(type, ptr) (*(type *)(ptr))
/// @brief Moves the pointer down.
#define __MOVE_PTR_DOWN(type, ptr) ((ptr) -= sizeof(type))
/// @brief Moves the pointer up.
#define __MOVE_PTR_UP(type, ptr) ((ptr) += sizeof(type))
/// @brief First, it moves the pointer down, and then it pushes the value at that memory location.
#define PUSH_VALUE_ON_STACK(ptr, value) \
(__ACCESS_PTR(__typeof__(value), __MOVE_PTR_DOWN(__typeof__(value), ptr)) = (value))
/// @brief First, it access the value at the given memory location, and then it moves the pointer up.
#define POP_VALUE_FROM_STACK(value, ptr) \
({ \
(value) = __ACCESS_PTR(__typeof__(value), ptr); \
__MOVE_PTR_UP(__typeof__(value), ptr); \
})
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/// @brief Push a 32-bit value onto the stack, decrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be decremented).
/// @param value The 32-bit value to push.
static inline void stack_push_u32(uint32_t *sp, uint32_t value)
{
*sp -= sizeof(uint32_t);
__asm__ __volatile__("" ::: "memory");
*(volatile uint32_t *)(*sp) = value;
__asm__ __volatile__("" ::: "memory");
}

/// @brief Push a signed 32-bit value onto the stack, decrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be decremented).
/// @param value The signed 32-bit value to push.
static inline void stack_push_s32(uint32_t *sp, int32_t value)
{
*sp -= sizeof(int32_t);
__asm__ __volatile__("" ::: "memory");
*(volatile int32_t *)(*sp) = value;
__asm__ __volatile__("" ::: "memory");
}

/// @brief Push a pointer value onto the stack, decrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be decremented).
/// @param ptr The pointer value to push.
static inline void stack_push_ptr(uint32_t *sp, const void *ptr)
{
*sp -= sizeof(uint32_t);
__asm__ __volatile__("" ::: "memory");
*(volatile uint32_t *)(*sp) = (uint32_t)ptr;
__asm__ __volatile__("" ::: "memory");
}

/// @brief Push a single byte onto the stack, decrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be decremented).
/// @param byte The byte value to push.
static inline void stack_push_u8(uint32_t *sp, uint8_t byte)
{
*sp -= sizeof(uint8_t);
__asm__ __volatile__("" ::: "memory");
*(volatile uint8_t *)(*sp) = byte;
__asm__ __volatile__("" ::: "memory");
}

/// @brief Pop a 32-bit value from the stack, incrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be incremented).
/// @return The 32-bit value popped from the stack.
static inline uint32_t stack_pop_u32(uint32_t *sp)
{
uint32_t value = *(volatile uint32_t *)(*sp);
__asm__ __volatile__("" ::: "memory");
*sp += sizeof(uint32_t);
return value;
}

/// @brief Pop a signed 32-bit value from the stack, incrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be incremented).
/// @return The signed 32-bit value popped from the stack.
static inline int32_t stack_pop_s32(uint32_t *sp)
{
int32_t value = *(volatile int32_t *)(*sp);
__asm__ __volatile__("" ::: "memory");
*sp += sizeof(int32_t);
return value;
}

/// @brief Pop a pointer value from the stack, incrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be incremented).
/// @return The pointer value popped from the stack.
static inline void *stack_pop_ptr(uint32_t *sp)
{
void *value = (void *)*(volatile uint32_t *)(*sp);
__asm__ __volatile__("" ::: "memory");
*sp += sizeof(uint32_t);
return value;
}

/// @brief Push arbitrary data onto the stack, decrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be decremented by size).
/// @param data Pointer to data to push.
/// @param size Number of bytes to push.
static inline void stack_push_data(uint32_t *sp, const void *data, size_t size)
{
*sp -= size;
__asm__ __volatile__("" ::: "memory");
memcpy((void *)*sp, data, size);
__asm__ __volatile__("" ::: "memory");
}

/// @brief Pop arbitrary data from the stack, incrementing the stack pointer.
/// @param sp Pointer to 32-bit stack pointer (will be incremented by size).
/// @param data Pointer to buffer where popped data will be stored.
/// @param size Number of bytes to pop.
static inline void stack_pop_data(uint32_t *sp, void *data, size_t size)
{
memcpy(data, (void *)*sp, size);
__asm__ __volatile__("" ::: "memory");
*sp += size;
}
Loading