From 97538aa09867272cb9bb787911bdfe93a185c26f Mon Sep 17 00:00:00 2001 From: karina Date: Wed, 22 Apr 2026 09:32:01 +0400 Subject: [PATCH 1/9] wip: vectors, panics and lsp fix --- .gitignore | 1 + .sourcekit-lsp/config.json | 8 +++ Kernel/CMakeLists.txt | 52 +++++++++++--- Kernel/Source/Arch/ExceptionContext.swift | 74 ++++++++++++++++++++ Kernel/Source/Arch/dtb.swift | 2 + Kernel/Source/Arch/vectors.S | 83 +++++++++++++++++++++++ Kernel/Source/OS/panic.swift | 6 ++ Kernel/Source/Support/BridgingHeader.h | 4 ++ Kernel/Source/kernel.swift | 8 +++ Kernel/justfile | 3 +- justfile | 4 ++ 11 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 .sourcekit-lsp/config.json create mode 100644 Kernel/Source/Arch/ExceptionContext.swift create mode 100644 Kernel/Source/Arch/vectors.S create mode 100644 Kernel/Source/OS/panic.swift diff --git a/.gitignore b/.gitignore index 377b8fa..ddf013f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .vscode .DS_Store compile_commands.json +ide-swift-toolchain.txt .cache \ No newline at end of file diff --git a/.sourcekit-lsp/config.json b/.sourcekit-lsp/config.json new file mode 100644 index 0000000..96d4543 --- /dev/null +++ b/.sourcekit-lsp/config.json @@ -0,0 +1,8 @@ +{ + "defaultWorkspaceType": "compilationDatabase", + "compilationDatabase": { + "searchPaths": [".", "Kernel"] + }, + "backgroundIndexing": true, + "backgroundPreparationMode": "enabled" +} diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index c44dd52..2fc76c2 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.20) project(ksOSKernel LANGUAGES ASM C) set(KERNEL_MODULE_NAME "Kernel") +# Where to emit compile_commands.json for SourceKit-LSP. Empty: Kernel/ +# (ancestor of SWIFT_SOURCES). Override: -DKERNEL_COMPILE_COMMANDS_DIR=/path +# or env KERNEL_COMPILE_COMMANDS_DIR. +set(KERNEL_COMPILE_COMMANDS_DIR "" CACHE PATH + "Directory for Swift compile_commands.json (SourceKit-LSP)") + # --- Locate Swift toolchain with Embedded Swift stdlib --- # Priority: cmake var > env var > auto-detect if(NOT SWIFT_TOOLCHAIN AND DEFINED ENV{SWIFT_TOOLCHAIN}) @@ -52,6 +58,18 @@ endif() message(STATUS "Swift: ${SWIFTC}") message(STATUS "Swift resource dir: ${SWIFT_RESOURCE_DIR}") +# Hint for SourceKit: VSCode must use this toolchain (same as compile_commands), +# not Xcode's default; otherwise: "Loading the standard library failed" with Embedded. +get_filename_component(_SWIFT_IDE_PATH "${SWIFTC}" DIRECTORY) +set(_ide_hint +"# If SourceKit reports \"Loading the standard library failed\", set the Swift +# extension's swift.path to the directory on the line below and restart +# \"Swift: Restart SourceKit LSP\". (Embedded Swift — must match this toolchain, not Xcode.) +# Regenerated on each CMake configure. +") +string(APPEND _ide_hint "${_SWIFT_IDE_PATH}\n") +file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/../ide-swift-toolchain.txt" "${_ide_hint}") + # --- Build --- add_compile_options(-ffreestanding -nostdlib -O0 -g) @@ -64,9 +82,11 @@ add_link_options( ) set(SWIFT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/Source/kernel.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/dtb.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/uart.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Kernel.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/DTB.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/UART.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/ExceptionContext.swift + ${CMAKE_CURRENT_SOURCE_DIR}/Source/OS/panic.swift # idfk why but sourcekit-lsp dont see Panic.swift but see panic.swift perfectly ) set(SWIFT_OBJ ${CMAKE_CURRENT_BINARY_DIR}/kernel_swift.o) @@ -94,7 +114,7 @@ set_source_files_properties(${SWIFT_OBJ} PROPERTIES GENERATED TRUE ) -add_executable(kernel.elf Source/Arch/entry.S Source/Support/stubs.c ${SWIFT_OBJ}) +add_executable(kernel.elf Source/Arch/entry.S Source/Support/stubs.c Source/Arch/vectors.S ${SWIFT_OBJ}) add_custom_command(TARGET kernel.elf POST_BUILD COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin @@ -109,8 +129,10 @@ set(SWIFT_ARGS "\"-enable-experimental-feature\"" "\"Embedded\"" "\"-module-name\"" "\"${KERNEL_MODULE_NAME}\"" "\"-parse-as-library\"" + "\"-wmo\"" "\"-import-bridging-header\"" "\"${_BRIDGING_HEADER}\"" "\"-Xcc\"" "\"-I${CMAKE_CURRENT_SOURCE_DIR}/../Common\"" + "\"-Xcc\"" "\"-fno-stack-protector\"" "\"-resource-dir\"" "\"${SWIFT_RESOURCE_DIR}\"" ) foreach(_src IN LISTS SWIFT_SOURCES) @@ -137,14 +159,24 @@ foreach(_src IN LISTS SWIFT_SOURCES) math(EXPR _idx "${_idx} + 1") endforeach() -if(DEFINED ENV{TEMP_DIR}) - set(COMPDB_OUTPUT_DIR "$ENV{TEMP_DIR}/Kernel") -elseif(DEFINED ENV{BUILD_DIR}) - set(COMPDB_OUTPUT_DIR "$ENV{BUILD_DIR}/temp/Kernel") +# Precedence: CMake -D > env > Kernel/ (ancestor of all SWIFT_SOURCES). +if(NOT KERNEL_COMPILE_COMMANDS_DIR STREQUAL "") + set(COMPDB_OUTPUT_DIR "${KERNEL_COMPILE_COMMANDS_DIR}") +elseif(DEFINED ENV{KERNEL_COMPILE_COMMANDS_DIR} AND NOT "$ENV{KERNEL_COMPILE_COMMANDS_DIR}" STREQUAL "") + set(COMPDB_OUTPUT_DIR "$ENV{KERNEL_COMPILE_COMMANDS_DIR}") else() - set(COMPDB_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + set(COMPDB_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") endif() +# Same JSON twice: (1) optional Kernel/ or KERNEL_COMPILE_COMMANDS_DIR, (2) repo +# root. SourceKit/Cursor/VSCode Swift extension resolve compile_commands at the +# workspace root first; a DB only under Kernel/ often yields no language service +# and broken cross-file resolution (WMO) even though the build works. +set(KERNEL_COMPDB_CONTENT "[\n${COMPDB_ENTRIES}]\n") file(GENERATE OUTPUT "${COMPDB_OUTPUT_DIR}/compile_commands.json" - CONTENT "[\n${COMPDB_ENTRIES}]\n" + CONTENT "${KERNEL_COMPDB_CONTENT}" +) +set(_REPO_COMPDB "${CMAKE_CURRENT_SOURCE_DIR}/../compile_commands.json") +file(GENERATE OUTPUT "${_REPO_COMPDB}" + CONTENT "${KERNEL_COMPDB_CONTENT}" ) \ No newline at end of file diff --git a/Kernel/Source/Arch/ExceptionContext.swift b/Kernel/Source/Arch/ExceptionContext.swift new file mode 100644 index 0000000..2949d7a --- /dev/null +++ b/Kernel/Source/Arch/ExceptionContext.swift @@ -0,0 +1,74 @@ +@frozen +public struct ExceptionContext { + public var x0: UInt64 + public var x1: UInt64 + public var x2: UInt64 + public var x3: UInt64 + public var x4: UInt64 + public var x5: UInt64 + public var x6: UInt64 + public var x7: UInt64 + public var x8: UInt64 + public var x9: UInt64 + public var x10: UInt64 + public var x11: UInt64 + public var x12: UInt64 + public var x13: UInt64 + public var x14: UInt64 + public var x15: UInt64 + public var x16: UInt64 + public var x17: UInt64 + public var x18: UInt64 + public var x19: UInt64 + public var x20: UInt64 + public var x21: UInt64 + public var x22: UInt64 + public var x23: UInt64 + public var x24: UInt64 + public var x25: UInt64 + public var x26: UInt64 + public var x27: UInt64 + public var x28: UInt64 + public var x29: UInt64 // fp + public var x30: UInt64 // lr + public var elr_el1: UInt64 // pc + public var spsr_el1: UInt64 // cpu status + public var esr_el1: UInt64 // error reason +} + +@frozen +public enum ExceptionType: UInt64 { + // curr el with sp0 (EL1t) + // usually dont happen cuz we switch to sp_el1, but just in case + case syncEL1t = 0 + case irqEL1t = 1 + case fiqEL1t = 2 + case seErrorEL1t = 3 + + // curr el with sp1 (EL1h) + // exception in kernel space + case syncEL1h = 4 + case irqEL1h = 5 + case fiqEL1h = 6 + case seErrorEL1h = 7 + + // lower EL 64-bit from userspace + case syncEL0_64 = 8 + case irqEL0_64 = 9 + case fiqEL0_64 = 10 + case seErrorEL0_64 = 11 + + // lower EL 32-bit from userspace + case syncEL0_32 = 12 + case irqEL0_32 = 13 + case fiqEL0_32 = 14 + case seErrorEL0_32 = 15 +} + +@_cdecl("swift_trap_handler") +public func trapHandler(context: UnsafeMutableRawPointer, rawType: UInt64) { + let context = context.assumingMemoryBound(to: ExceptionContext.self) + let type = ExceptionType(rawValue: rawType)! + + panic(context: context.pointee) +} \ No newline at end of file diff --git a/Kernel/Source/Arch/dtb.swift b/Kernel/Source/Arch/dtb.swift index 04f8b8b..15f7dda 100644 --- a/Kernel/Source/Arch/dtb.swift +++ b/Kernel/Source/Arch/dtb.swift @@ -69,6 +69,8 @@ func parseDTB(at pointer: UnsafeRawPointer) { structBase = structBase.advanced(by: 8) // skip header structBase = structBase.advanced(by: alignUp(dataLength, to: 4)) // skip data for now + + // TODO: finish it :D case .endNode: continue case .nop: diff --git a/Kernel/Source/Arch/vectors.S b/Kernel/Source/Arch/vectors.S new file mode 100644 index 0000000..aab9215 --- /dev/null +++ b/Kernel/Source/Arch/vectors.S @@ -0,0 +1,83 @@ +.macro ventry type + .align 7 + sub sp, sp, #272 // save 272 bytes of stack + stp x0, x1, [sp, #0] // move stack + mov x1, #\type // move type to x1 + b common_trap_entry +.endm + +.section .text.vectors +.align 11 +.global vectors +vector_table: + // EL1t (curr EL with SP0) + ventry 0 // Sync + ventry 1 // IRQ + ventry 2 // FIQ + ventry 3 // SError + + // EL1h (curr EL with SP1) + ventry 4 // Sync + ventry 5 // IRQ + ventry 6 // FIQ + ventry 7 // SError + + // EL0 (lower EL 64-bit from userspace) + ventry 8 // Sync + ventry 9 // IRQ + ventry 10 // FIQ + ventry 11 // SError + + // EL0 (lower EL 32-bit from userspace) + ventry 12; ventry 13; ventry 14; ventry 15 + +common_trap_entry: + stp x2, x3, [sp, #16 * 1] + stp x4, x5, [sp, #16 * 2] + stp x6, x7, [sp, #16 * 3] + stp x8, x9, [sp, #16 * 4] + stp x10, x11, [sp, #16 * 5] + stp x12, x13, [sp, #16 * 6] + stp x14, x15, [sp, #16 * 7] + stp x16, x17, [sp, #16 * 8] + stp x18, x19, [sp, #16 * 9] + stp x20, x21, [sp, #16 * 10] + stp x22, x23, [sp, #16 * 11] + stp x24, x25, [sp, #16 * 12] + stp x26, x27, [sp, #16 * 13] + stp x28, x29, [sp, #16 * 14] + + mrs x21, elr_el1 + mrs x22, spsr_el1 + mrs x23, esr_el1 + + stp x30, x21, [sp, #16 * 15] + stp x22, x23, [sp, #16 * 16] + + mov x0, sp + bl swift_trap_handler + + ldp x22, x23, [sp, #16 * 16] + msr spsr_el1, x22 + + ldp x30, x21, [sp, #16 * 15] + msr elr_el1, x21 + + ldp x28, x29, [sp, #16 * 14] + ldp x26, x27, [sp, #16 * 13] + ldp x24, x25, [sp, #16 * 12] + ldp x22, x23, [sp, #16 * 11] + ldp x20, x21, [sp, #16 * 10] + ldp x18, x19, [sp, #16 * 9] + ldp x16, x17, [sp, #16 * 8] + ldp x14, x15, [sp, #16 * 7] + ldp x12, x13, [sp, #16 * 6] + ldp x10, x11, [sp, #16 * 5] + ldp x8, x9, [sp, #16 * 4] + ldp x6, x7, [sp, #16 * 3] + ldp x4, x5, [sp, #16 * 2] + ldp x2, x3, [sp, #16 * 1] + ldp x0, x1, [sp, #0] + + add sp, sp, #272 + eret \ No newline at end of file diff --git a/Kernel/Source/OS/panic.swift b/Kernel/Source/OS/panic.swift new file mode 100644 index 0000000..c8f2205 --- /dev/null +++ b/Kernel/Source/OS/panic.swift @@ -0,0 +1,6 @@ +// idfk why but sourcekit-lsp dont see Panic.swift but see panic.swift perfectly + +public func panic(context: ExceptionContext) { + kprint("kernel panic stub meow") + _wfi() +} \ No newline at end of file diff --git a/Kernel/Source/Support/BridgingHeader.h b/Kernel/Source/Support/BridgingHeader.h index 9208982..a041a31 100644 --- a/Kernel/Source/Support/BridgingHeader.h +++ b/Kernel/Source/Support/BridgingHeader.h @@ -7,4 +7,8 @@ static inline void mmio_write32(uintptr_t addr, uint32_t val) { static inline uint32_t mmio_read32(uintptr_t addr) { return *(volatile uint32_t *)addr; +} + +static inline void _wfi(void) { + __asm__ volatile("wfi"); } \ No newline at end of file diff --git a/Kernel/Source/kernel.swift b/Kernel/Source/kernel.swift index a438c9e..0f68ce9 100644 --- a/Kernel/Source/kernel.swift +++ b/Kernel/Source/kernel.swift @@ -1,4 +1,12 @@ +@inline(never) +func getDenominator() -> Int { + return 0 +} + @_cdecl("kmain") public func kernelMain(_ bootInfo: UnsafeMutablePointer) { kprint("Test nya") + let a: Int = 10 + let b = getDenominator() + let c = a / b } diff --git a/Kernel/justfile b/Kernel/justfile index 417ef27..2d9764b 100644 --- a/Kernel/justfile +++ b/Kernel/justfile @@ -10,4 +10,5 @@ build: @echo "✅ Kernel ready at: {{BUILD_DIR}}/Kernel/ksOSKernel.bin" clean: - rm -rf {{TEMP_DIR}}/Kernel \ No newline at end of file + rm -rf {{TEMP_DIR}}/Kernel + rm -f compile_commands.json \ No newline at end of file diff --git a/justfile b/justfile index 0566df1..d843608 100644 --- a/justfile +++ b/justfile @@ -86,4 +86,8 @@ _prep: just run @clean: + just Bootloader clean + just Kernel clean rm -rf {{BUILD_DIR}} + rm -f compile_commands.json + rm -f ide-swift-toolchain.txt \ No newline at end of file From bfa84040b8a7b80823e5ae94db924c484c0c2ada Mon Sep 17 00:00:00 2001 From: karina Date: Wed, 22 Apr 2026 23:12:06 +0400 Subject: [PATCH 2/9] wip: bare bones for C in kernel --- .gitignore | 1 + Kernel/CMakeLists.txt | 199 ++++------------------ Kernel/Source/Arch/ExceptionContext.swift | 74 -------- Kernel/Source/Arch/dtb.swift | 83 --------- Kernel/Source/Arch/entry.S | 6 +- Kernel/Source/Arch/vectors.S | 83 --------- Kernel/Source/IO/uart.swift | 20 --- Kernel/Source/KernelMain.c | 3 + Kernel/Source/OS/panic.swift | 6 - Kernel/Source/Support/BridgingHeader.h | 14 -- Kernel/Source/Support/stubs.c | 42 ----- Kernel/Source/kernel.swift | 12 -- Kernel/cmake/aarch64-bare.cmake | 10 ++ 13 files changed, 46 insertions(+), 507 deletions(-) delete mode 100644 Kernel/Source/Arch/ExceptionContext.swift delete mode 100644 Kernel/Source/Arch/dtb.swift delete mode 100644 Kernel/Source/Arch/vectors.S delete mode 100644 Kernel/Source/IO/uart.swift create mode 100644 Kernel/Source/KernelMain.c delete mode 100644 Kernel/Source/OS/panic.swift delete mode 100644 Kernel/Source/Support/BridgingHeader.h delete mode 100644 Kernel/Source/Support/stubs.c delete mode 100644 Kernel/Source/kernel.swift diff --git a/.gitignore b/.gitignore index ddf013f..04b9ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .build +build .vscode .DS_Store compile_commands.json diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 2fc76c2..d25b339 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -1,182 +1,43 @@ cmake_minimum_required(VERSION 3.20) project(ksOSKernel LANGUAGES ASM C) -set(KERNEL_MODULE_NAME "Kernel") -# Where to emit compile_commands.json for SourceKit-LSP. Empty: Kernel/ -# (ancestor of SWIFT_SOURCES). Override: -DKERNEL_COMPILE_COMMANDS_DIR=/path -# or env KERNEL_COMPILE_COMMANDS_DIR. -set(KERNEL_COMPILE_COMMANDS_DIR "" CACHE PATH - "Directory for Swift compile_commands.json (SourceKit-LSP)") +file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/Source/KernelMain.c + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/entry.S + ${CMAKE_CURRENT_SOURCE_DIR}/Source/**/*.c +) -# --- Locate Swift toolchain with Embedded Swift stdlib --- -# Priority: cmake var > env var > auto-detect -if(NOT SWIFT_TOOLCHAIN AND DEFINED ENV{SWIFT_TOOLCHAIN}) - set(SWIFT_TOOLCHAIN "$ENV{SWIFT_TOOLCHAIN}") -endif() +add_executable(Kernel ${KERNEL_SOURCES}) +target_include_directories(Kernel PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/Include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../Common +) -if(SWIFT_TOOLCHAIN) - set(SWIFTC "${SWIFT_TOOLCHAIN}/usr/bin/swiftc") - set(SWIFT_RESOURCE_DIR "${SWIFT_TOOLCHAIN}/usr/lib/swift") -elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - # Scan for a swift.org toolchain that ships the embedded stdlib. - # APPLE is false here (target is Generic), so we check the HOST OS. - file(GLOB _tc_candidates - "$ENV{HOME}/Library/Developer/Toolchains/*.xctoolchain" - "/Library/Developer/Toolchains/*.xctoolchain" - ) - foreach(_tc ${_tc_candidates}) - if(EXISTS "${_tc}/usr/lib/swift/embedded") - set(SWIFTC "${_tc}/usr/bin/swiftc") - set(SWIFT_RESOURCE_DIR "${_tc}/usr/lib/swift") - break() - endif() - endforeach() -else() - # Linux: find swiftc in PATH - find_program(_SWIFTC_EXE swiftc) - if(_SWIFTC_EXE) - get_filename_component(_SWIFTC_BIN "${_SWIFTC_EXE}" DIRECTORY) - get_filename_component(_SWIFTC_USR "${_SWIFTC_BIN}" DIRECTORY) - - if(EXISTS "${_SWIFTC_USR}/lib/swift/embedded") - set(SWIFTC "${_SWIFTC_EXE}") - set(SWIFT_RESOURCE_DIR "${_SWIFTC_USR}/lib/swift") - elseif(EXISTS "${_SWIFTC_USR}/lib/swift/lib/swift/embedded") - set(SWIFTC "${_SWIFTC_EXE}") - set(SWIFT_RESOURCE_DIR "${_SWIFTC_USR}/lib/swift/lib/swift") - endif() - endif() -endif() +target_compile_options(Kernel PRIVATE + $<$: + -ffreestanding + -fno-stack-protector + -fno-builtin + -Wall -Wextra + -g + -mgeneral-regs-only + > +) -if(NOT SWIFTC OR NOT EXISTS "${SWIFT_RESOURCE_DIR}/embedded") - message(FATAL_ERROR - "Swift toolchain with Embedded Swift not found.\n" - "Install a swift.org toolchain and pass -DSWIFT_TOOLCHAIN= " - "or set the SWIFT_TOOLCHAIN env var.") -endif() - -message(STATUS "Swift: ${SWIFTC}") -message(STATUS "Swift resource dir: ${SWIFT_RESOURCE_DIR}") - -# Hint for SourceKit: VSCode must use this toolchain (same as compile_commands), -# not Xcode's default; otherwise: "Loading the standard library failed" with Embedded. -get_filename_component(_SWIFT_IDE_PATH "${SWIFTC}" DIRECTORY) -set(_ide_hint -"# If SourceKit reports \"Loading the standard library failed\", set the Swift -# extension's swift.path to the directory on the line below and restart -# \"Swift: Restart SourceKit LSP\". (Embedded Swift — must match this toolchain, not Xcode.) -# Regenerated on each CMake configure. -") -string(APPEND _ide_hint "${_SWIFT_IDE_PATH}\n") -file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/../ide-swift-toolchain.txt" "${_ide_hint}") - -# --- Build --- -add_compile_options(-ffreestanding -nostdlib -O0 -g) - -set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) -add_link_options( - -fuse-ld=lld +target_link_options(Kernel PRIVATE -nostdlib -static - -Wl,-T,${LINKER_SCRIPT} + -no-pie + -T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld" + -z max-page-size=0x1000 ) -set(SWIFT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/Source/Kernel.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/DTB.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/UART.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/ExceptionContext.swift - ${CMAKE_CURRENT_SOURCE_DIR}/Source/OS/panic.swift # idfk why but sourcekit-lsp dont see Panic.swift but see panic.swift perfectly -) -set(SWIFT_OBJ ${CMAKE_CURRENT_BINARY_DIR}/kernel_swift.o) - -add_custom_command( - OUTPUT ${SWIFT_OBJ} - COMMAND ${SWIFTC} - -target aarch64-none-none-elf - -enable-experimental-feature Embedded - -parse-as-library - -wmo - -O - -Xcc -fno-stack-protector - -Xcc -I${CMAKE_CURRENT_SOURCE_DIR}/../Common - -import-bridging-header ${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h - -resource-dir ${SWIFT_RESOURCE_DIR} - -c ${SWIFT_SOURCES} - -o ${SWIFT_OBJ} - COMMAND ${LLVM_OBJCOPY} --remove-section=.swift_modhash ${SWIFT_OBJ} - DEPENDS ${SWIFT_SOURCES} - COMMENT "Compiling Swift kernel" +set_target_properties(Kernel PROPERTIES + OUTPUT_NAME "Kernel.elf" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) -set_source_files_properties(${SWIFT_OBJ} PROPERTIES - EXTERNAL_OBJECT TRUE - GENERATED TRUE -) - -add_executable(kernel.elf Source/Arch/entry.S Source/Support/stubs.c Source/Arch/vectors.S ${SWIFT_OBJ}) - -add_custom_command(TARGET kernel.elf POST_BUILD - COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin -) - -# --- SourceKit-LSP: generate compile_commands.json for Swift (Dynamic) --- -set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h") - -set(SWIFT_ARGS - "\"${SWIFTC}\"" - "\"-target\"" "\"aarch64-none-none-elf\"" - "\"-enable-experimental-feature\"" "\"Embedded\"" - "\"-module-name\"" "\"${KERNEL_MODULE_NAME}\"" - "\"-parse-as-library\"" - "\"-wmo\"" - "\"-import-bridging-header\"" "\"${_BRIDGING_HEADER}\"" - "\"-Xcc\"" "\"-I${CMAKE_CURRENT_SOURCE_DIR}/../Common\"" - "\"-Xcc\"" "\"-fno-stack-protector\"" - "\"-resource-dir\"" "\"${SWIFT_RESOURCE_DIR}\"" -) -foreach(_src IN LISTS SWIFT_SOURCES) - list(APPEND SWIFT_ARGS "\"${_src}\"") -endforeach() - -string(JOIN ", " SWIFT_ARGS_JSON ${SWIFT_ARGS}) - -set(COMPDB_ENTRIES "") -list(LENGTH SWIFT_SOURCES _src_count) -math(EXPR _last_idx "${_src_count} - 1") -set(_idx 0) - -foreach(_src IN LISTS SWIFT_SOURCES) - set(_entry " {\n \"file\": \"${_src}\",\n \"directory\": \"${CMAKE_CURRENT_BINARY_DIR}\",\n \"arguments\": [${SWIFT_ARGS_JSON}]\n }") - - if(_idx LESS _last_idx) - string(APPEND _entry ",\n") - else() - string(APPEND _entry "\n") - endif() - - string(APPEND COMPDB_ENTRIES "${_entry}") - math(EXPR _idx "${_idx} + 1") -endforeach() - -# Precedence: CMake -D > env > Kernel/ (ancestor of all SWIFT_SOURCES). -if(NOT KERNEL_COMPILE_COMMANDS_DIR STREQUAL "") - set(COMPDB_OUTPUT_DIR "${KERNEL_COMPILE_COMMANDS_DIR}") -elseif(DEFINED ENV{KERNEL_COMPILE_COMMANDS_DIR} AND NOT "$ENV{KERNEL_COMPILE_COMMANDS_DIR}" STREQUAL "") - set(COMPDB_OUTPUT_DIR "$ENV{KERNEL_COMPILE_COMMANDS_DIR}") -else() - set(COMPDB_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") -endif() - -# Same JSON twice: (1) optional Kernel/ or KERNEL_COMPILE_COMMANDS_DIR, (2) repo -# root. SourceKit/Cursor/VSCode Swift extension resolve compile_commands at the -# workspace root first; a DB only under Kernel/ often yields no language service -# and broken cross-file resolution (WMO) even though the build works. -set(KERNEL_COMPDB_CONTENT "[\n${COMPDB_ENTRIES}]\n") -file(GENERATE OUTPUT "${COMPDB_OUTPUT_DIR}/compile_commands.json" - CONTENT "${KERNEL_COMPDB_CONTENT}" -) -set(_REPO_COMPDB "${CMAKE_CURRENT_SOURCE_DIR}/../compile_commands.json") -file(GENERATE OUTPUT "${_REPO_COMPDB}" - CONTENT "${KERNEL_COMPDB_CONTENT}" +add_custom_command(TARGET Kernel POST_BUILD + COMMAND ${LLVM_OBJCOPY} -O binary ${CMAKE_BINARY_DIR}/Kernel.elf ${CMAKE_BINARY_DIR}/Kernel.bin + COMMENT "Generating ksOSKernel.bin from Kernel.elf" ) \ No newline at end of file diff --git a/Kernel/Source/Arch/ExceptionContext.swift b/Kernel/Source/Arch/ExceptionContext.swift deleted file mode 100644 index 2949d7a..0000000 --- a/Kernel/Source/Arch/ExceptionContext.swift +++ /dev/null @@ -1,74 +0,0 @@ -@frozen -public struct ExceptionContext { - public var x0: UInt64 - public var x1: UInt64 - public var x2: UInt64 - public var x3: UInt64 - public var x4: UInt64 - public var x5: UInt64 - public var x6: UInt64 - public var x7: UInt64 - public var x8: UInt64 - public var x9: UInt64 - public var x10: UInt64 - public var x11: UInt64 - public var x12: UInt64 - public var x13: UInt64 - public var x14: UInt64 - public var x15: UInt64 - public var x16: UInt64 - public var x17: UInt64 - public var x18: UInt64 - public var x19: UInt64 - public var x20: UInt64 - public var x21: UInt64 - public var x22: UInt64 - public var x23: UInt64 - public var x24: UInt64 - public var x25: UInt64 - public var x26: UInt64 - public var x27: UInt64 - public var x28: UInt64 - public var x29: UInt64 // fp - public var x30: UInt64 // lr - public var elr_el1: UInt64 // pc - public var spsr_el1: UInt64 // cpu status - public var esr_el1: UInt64 // error reason -} - -@frozen -public enum ExceptionType: UInt64 { - // curr el with sp0 (EL1t) - // usually dont happen cuz we switch to sp_el1, but just in case - case syncEL1t = 0 - case irqEL1t = 1 - case fiqEL1t = 2 - case seErrorEL1t = 3 - - // curr el with sp1 (EL1h) - // exception in kernel space - case syncEL1h = 4 - case irqEL1h = 5 - case fiqEL1h = 6 - case seErrorEL1h = 7 - - // lower EL 64-bit from userspace - case syncEL0_64 = 8 - case irqEL0_64 = 9 - case fiqEL0_64 = 10 - case seErrorEL0_64 = 11 - - // lower EL 32-bit from userspace - case syncEL0_32 = 12 - case irqEL0_32 = 13 - case fiqEL0_32 = 14 - case seErrorEL0_32 = 15 -} - -@_cdecl("swift_trap_handler") -public func trapHandler(context: UnsafeMutableRawPointer, rawType: UInt64) { - let context = context.assumingMemoryBound(to: ExceptionContext.self) - let type = ExceptionType(rawValue: rawType)! - - panic(context: context.pointee) -} \ No newline at end of file diff --git a/Kernel/Source/Arch/dtb.swift b/Kernel/Source/Arch/dtb.swift deleted file mode 100644 index 15f7dda..0000000 --- a/Kernel/Source/Arch/dtb.swift +++ /dev/null @@ -1,83 +0,0 @@ -struct FDTHeader { - let magic: UInt32 // 0xd00dfeed - let totalsize: UInt32 - let off_dt_struct: UInt32 - let off_dt_strings: UInt32 - let off_mem_rsvmap: UInt32 - let version: UInt32 - let last_comp_version: UInt32 - let boot_cpuid_phys: UInt32 - let size_dt_strings: UInt32 - let size_dt_struct: UInt32 -} - -struct FDTProperty { - let len: UInt32 - let nameoff: UInt32 -} - -enum FDTToken: UInt32 { - case beginNode = 0x1 - case endNode = 0x2 - case prop = 0x3 - case nop = 0x4 - case end = 0x9 -} - -extension UInt32 { - var fromBe: UInt32 { - return self.byteSwapped - } -} - -func alignUp(_ value: Int, to: Int) -> Int { - return (value + to - 1) & ~(to - 1) -} - -let kFDTHeaderMagic = 0xd00dfeed - -func parseDTB(at pointer: UnsafeRawPointer) { - let header = pointer.bindMemory(to: FDTHeader.self, capacity: 1).pointee - guard header.magic.byteSwapped == kFDTHeaderMagic else { - return - } - - let structOffset = Int(header.off_dt_struct.byteSwapped) - let stringOffset = Int(header.off_dt_strings.byteSwapped) - - var structBase = pointer.advanced(by: structOffset) - let stringsBase = pointer.advanced(by: stringOffset) - - var finished = false - while !finished { - let rawToken = structBase.load(as: UInt32.self).byteSwapped - structBase = structBase.advanced(by: 4) - - if let token = FDTToken(rawValue: rawToken) { - switch token { - case .beginNode: - let namePointer = structBase.assumingMemoryBound(to: UInt8.self) - let name = String(cString: namePointer) - let nameLength = name.utf8.count + 1 - structBase = structBase.advanced(by: alignUp(nameLength, to: 4)) - case .prop: - let propertyHeader = structBase.load(as: FDTProperty.self) - let dataLength = Int(propertyHeader.len.byteSwapped) - let nameOffset = Int(propertyHeader.nameoff.byteSwapped) - - let namePointer = stringsBase.advanced(by: nameOffset).assumingMemoryBound(to: UInt8.self) - - structBase = structBase.advanced(by: 8) // skip header - structBase = structBase.advanced(by: alignUp(dataLength, to: 4)) // skip data for now - - // TODO: finish it :D - case .endNode: - continue - case .nop: - continue - case .end: - finished = true - } - } - } -} \ No newline at end of file diff --git a/Kernel/Source/Arch/entry.S b/Kernel/Source/Arch/entry.S index 2638f10..59853a5 100644 --- a/Kernel/Source/Arch/entry.S +++ b/Kernel/Source/Arch/entry.S @@ -1,7 +1,5 @@ .section .text.boot, "ax" .global _start - _start: - bl kmain -.hang: - b .hang \ No newline at end of file + bl KernelMain + b . \ No newline at end of file diff --git a/Kernel/Source/Arch/vectors.S b/Kernel/Source/Arch/vectors.S deleted file mode 100644 index aab9215..0000000 --- a/Kernel/Source/Arch/vectors.S +++ /dev/null @@ -1,83 +0,0 @@ -.macro ventry type - .align 7 - sub sp, sp, #272 // save 272 bytes of stack - stp x0, x1, [sp, #0] // move stack - mov x1, #\type // move type to x1 - b common_trap_entry -.endm - -.section .text.vectors -.align 11 -.global vectors -vector_table: - // EL1t (curr EL with SP0) - ventry 0 // Sync - ventry 1 // IRQ - ventry 2 // FIQ - ventry 3 // SError - - // EL1h (curr EL with SP1) - ventry 4 // Sync - ventry 5 // IRQ - ventry 6 // FIQ - ventry 7 // SError - - // EL0 (lower EL 64-bit from userspace) - ventry 8 // Sync - ventry 9 // IRQ - ventry 10 // FIQ - ventry 11 // SError - - // EL0 (lower EL 32-bit from userspace) - ventry 12; ventry 13; ventry 14; ventry 15 - -common_trap_entry: - stp x2, x3, [sp, #16 * 1] - stp x4, x5, [sp, #16 * 2] - stp x6, x7, [sp, #16 * 3] - stp x8, x9, [sp, #16 * 4] - stp x10, x11, [sp, #16 * 5] - stp x12, x13, [sp, #16 * 6] - stp x14, x15, [sp, #16 * 7] - stp x16, x17, [sp, #16 * 8] - stp x18, x19, [sp, #16 * 9] - stp x20, x21, [sp, #16 * 10] - stp x22, x23, [sp, #16 * 11] - stp x24, x25, [sp, #16 * 12] - stp x26, x27, [sp, #16 * 13] - stp x28, x29, [sp, #16 * 14] - - mrs x21, elr_el1 - mrs x22, spsr_el1 - mrs x23, esr_el1 - - stp x30, x21, [sp, #16 * 15] - stp x22, x23, [sp, #16 * 16] - - mov x0, sp - bl swift_trap_handler - - ldp x22, x23, [sp, #16 * 16] - msr spsr_el1, x22 - - ldp x30, x21, [sp, #16 * 15] - msr elr_el1, x21 - - ldp x28, x29, [sp, #16 * 14] - ldp x26, x27, [sp, #16 * 13] - ldp x24, x25, [sp, #16 * 12] - ldp x22, x23, [sp, #16 * 11] - ldp x20, x21, [sp, #16 * 10] - ldp x18, x19, [sp, #16 * 9] - ldp x16, x17, [sp, #16 * 8] - ldp x14, x15, [sp, #16 * 7] - ldp x12, x13, [sp, #16 * 6] - ldp x10, x11, [sp, #16 * 5] - ldp x8, x9, [sp, #16 * 4] - ldp x6, x7, [sp, #16 * 3] - ldp x4, x5, [sp, #16 * 2] - ldp x2, x3, [sp, #16 * 1] - ldp x0, x1, [sp, #0] - - add sp, sp, #272 - eret \ No newline at end of file diff --git a/Kernel/Source/IO/uart.swift b/Kernel/Source/IO/uart.swift deleted file mode 100644 index 3d9107f..0000000 --- a/Kernel/Source/IO/uart.swift +++ /dev/null @@ -1,20 +0,0 @@ -let kUARTBaseAddress: UInt = 0x09000000 // TODO: Make it dynamic by parsion DTB - -@_cdecl("putchar") -@discardableResult -public func _serialPutchar(_ char: Int32) -> Int32 { - let uartFR: UInt = kUARTBaseAddress + 0x18// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18) - - while (mmio_read32(uartFR) & (1 << 5)) != 0 { - // i love pizza btw - } - - mmio_write32(UInt(kUARTBaseAddress), UInt32(char)) - return char -} - -public func kprint(_ message: StaticString) { - for i in 0.. - -static inline void mmio_write32(uintptr_t addr, uint32_t val) { - *(volatile uint32_t *)addr = val; -} - -static inline uint32_t mmio_read32(uintptr_t addr) { - return *(volatile uint32_t *)addr; -} - -static inline void _wfi(void) { - __asm__ volatile("wfi"); -} \ No newline at end of file diff --git a/Kernel/Source/Support/stubs.c b/Kernel/Source/Support/stubs.c deleted file mode 100644 index ca96b13..0000000 --- a/Kernel/Source/Support/stubs.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -void* memmove(void* dest, const void* src, unsigned long n) { - unsigned char* d = (unsigned char*)dest; - const unsigned char* s = (const unsigned char*)src; - if (d < s) { - while (n--) *d++ = *s++; - } else { - d += n; s += n; - while (n--) *--d = *--s; - } - return dest; -} - -void* memcpy(void* dest, const void* src, unsigned long n) { - return memmove(dest, src, n); -} - -void* memset(void* dest, int c, unsigned long n) { - unsigned char* d = (unsigned char*)dest; - while (n--) *d++ = (unsigned char)c; - return dest; -} - -// Stack protection -long __stack_chk_guard = (long)0xDEADBEEFCAFEBABEULL; -void __stack_chk_fail(void) { while (1); } - -// Swift runtime allocator stubs — should never be called in embedded mode -int posix_memalign(void** ptr, unsigned long align, unsigned long size) { - (void)ptr; (void)align; (void)size; - while (1); -} - -void free(void* ptr) { (void)ptr; } - -// Swift stdlib uses arc4random_buf for Hasher seed — stub with zeroes in bare-metal -void arc4random_buf(void* buf, unsigned long nbytes) { - unsigned char* b = (unsigned char*)buf; - while (nbytes--) *b++ = 0; -} diff --git a/Kernel/Source/kernel.swift b/Kernel/Source/kernel.swift deleted file mode 100644 index 0f68ce9..0000000 --- a/Kernel/Source/kernel.swift +++ /dev/null @@ -1,12 +0,0 @@ -@inline(never) -func getDenominator() -> Int { - return 0 -} - -@_cdecl("kmain") -public func kernelMain(_ bootInfo: UnsafeMutablePointer) { - kprint("Test nya") - let a: Int = 10 - let b = getDenominator() - let c = a / b -} diff --git a/Kernel/cmake/aarch64-bare.cmake b/Kernel/cmake/aarch64-bare.cmake index 3b90c1b..4974c8d 100644 --- a/Kernel/cmake/aarch64-bare.cmake +++ b/Kernel/cmake/aarch64-bare.cmake @@ -26,3 +26,13 @@ set(LLVM_OBJCOPY "${LLVM_BIN}/llvm-objcopy") set(TARGET_TRIPLE aarch64-none-elf) set(CMAKE_C_COMPILER_TARGET ${TARGET_TRIPLE}) set(CMAKE_ASM_COMPILER_TARGET ${TARGET_TRIPLE}) + +if(APPLE) + find_program(TERMOS_LD_LLD NAMES ld.lld HINTS /usr/local/bin /opt/homebrew/bin REQUIRED) + find_program(LLVM_OBJCOPY NAMES llvm-objcopy objcopy + HINTS /usr/local/opt/llvm/bin /opt/homebrew/opt/llvm/bin /usr/local/bin /opt/homebrew/bin + REQUIRED) + set(CMAKE_C_LINK_FLAGS "") + set(CMAKE_C_LINK_EXECUTABLE + "${TERMOS_LD_LLD} -o ") +endif() From cf142ba78e17e60e819eff516bf6944ab75e9bf3 Mon Sep 17 00:00:00 2001 From: karina Date: Thu, 23 Apr 2026 06:49:40 +0400 Subject: [PATCH 3/9] fix: clangd --- Kernel/.clangd | 2 ++ Kernel/CMakeLists.txt | 1 + Kernel/Include/types.h | 18 +++++++++++++++ Kernel/Source/KernelMain.c | 4 +++- Kernel/cmake/aarch64-bare.cmake | 39 +++++++++++++++++++++++---------- Kernel/justfile | 2 +- 6 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 Kernel/.clangd create mode 100644 Kernel/Include/types.h diff --git a/Kernel/.clangd b/Kernel/.clangd new file mode 100644 index 0000000..9992ca2 --- /dev/null +++ b/Kernel/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + CompilationDatabase: ../.build/temp/Kernel diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d25b339..6c42a05 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.20) project(ksOSKernel LANGUAGES ASM C) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Source/KernelMain.c diff --git a/Kernel/Include/types.h b/Kernel/Include/types.h new file mode 100644 index 0000000..3c0ad3e --- /dev/null +++ b/Kernel/Include/types.h @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +typedef unsigned char UInt8; +typedef unsigned short UInt16; +typedef unsigned int UInt32; +typedef unsigned long long UInt64; + +typedef signed char Int8; +typedef signed short Int16; +typedef signed int Int32; +typedef signed long long Int64; + +typedef UInt64 Size; + + diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 7e4f917..22c22be 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,3 +1,5 @@ +#include "types.h" + void KernelMain(void) { - + volatile UInt64 meow = 0x12345; } \ No newline at end of file diff --git a/Kernel/cmake/aarch64-bare.cmake b/Kernel/cmake/aarch64-bare.cmake index 4974c8d..461e28a 100644 --- a/Kernel/cmake/aarch64-bare.cmake +++ b/Kernel/cmake/aarch64-bare.cmake @@ -3,25 +3,35 @@ set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) if(NOT LLVM_BIN) - if(APPLE) + find_program(_CLANG + NAMES clang + HINTS + /opt/homebrew/opt/llvm/bin + /usr/local/opt/llvm/bin + ) + + if(NOT _CLANG AND APPLE) execute_process( COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE BREW_PREFIX_RESULT ) - set(LLVM_BIN "${LLVM_PREFIX}/bin") - else() - find_program(_CLANG clang) - if(NOT _CLANG) - message(FATAL_ERROR "clang not found.") + if(BREW_PREFIX_RESULT EQUAL 0 AND EXISTS "${LLVM_PREFIX}/bin/clang") + set(_CLANG "${LLVM_PREFIX}/bin/clang") endif() - get_filename_component(LLVM_BIN "${_CLANG}" DIRECTORY) endif() + + if(NOT _CLANG) + message(FATAL_ERROR "clang not found. Set LLVM_BIN or add clang to PATH.") + endif() + + get_filename_component(LLVM_BIN "${_CLANG}" DIRECTORY) endif() set(CMAKE_C_COMPILER "${LLVM_BIN}/clang") set(CMAKE_ASM_COMPILER "${LLVM_BIN}/clang") -set(LLVM_OBJCOPY "${LLVM_BIN}/llvm-objcopy") set(TARGET_TRIPLE aarch64-none-elf) set(CMAKE_C_COMPILER_TARGET ${TARGET_TRIPLE}) @@ -29,10 +39,17 @@ set(CMAKE_ASM_COMPILER_TARGET ${TARGET_TRIPLE}) if(APPLE) find_program(TERMOS_LD_LLD NAMES ld.lld HINTS /usr/local/bin /opt/homebrew/bin REQUIRED) - find_program(LLVM_OBJCOPY NAMES llvm-objcopy objcopy - HINTS /usr/local/opt/llvm/bin /opt/homebrew/opt/llvm/bin /usr/local/bin /opt/homebrew/bin - REQUIRED) set(CMAKE_C_LINK_FLAGS "") set(CMAKE_C_LINK_EXECUTABLE "${TERMOS_LD_LLD} -o ") endif() + +find_program(LLVM_OBJCOPY NAMES llvm-objcopy objcopy + HINTS + "${LLVM_BIN}" + /usr/local/opt/llvm/bin + /opt/homebrew/opt/llvm/bin + /usr/local/bin + /opt/homebrew/bin + REQUIRED +) diff --git a/Kernel/justfile b/Kernel/justfile index 2d9764b..d621268 100644 --- a/Kernel/justfile +++ b/Kernel/justfile @@ -6,7 +6,7 @@ build: cmake --build {{TEMP_DIR}}/Kernel - cp {{TEMP_DIR}}/Kernel/kernel.bin {{BUILD_DIR}}/Kernel/ksOSKernel.bin + cp {{TEMP_DIR}}/Kernel/Kernel.bin {{BUILD_DIR}}/Kernel/ksOSKernel.bin @echo "✅ Kernel ready at: {{BUILD_DIR}}/Kernel/ksOSKernel.bin" clean: From 502413b9ab0e9c07fd516e8ab1ce661675459a5b Mon Sep 17 00:00:00 2001 From: karina Date: Thu, 23 Apr 2026 21:25:15 +0400 Subject: [PATCH 4/9] feat(kernel): add PL011 UART console and arch I/O helpers - Add IOSerial: PL011 (0x0900_0000) TX with FIFO-full polling, yield while waiting - Add Arch/IO.h (32-bit MMIO with DSB) and Arch/CPU.h (yield, WFI) - Extend types.h (e.g. ASCII, Address, Int/UInt aliases) - Wire KernelMain to IOSerialPutString for early boot output - Drop .sourcekit-lsp config; note IO glob in CMake (commented) --- .sourcekit-lsp/config.json | 8 -------- Kernel/CMakeLists.txt | 1 + Kernel/Include/Arch/CPU.h | 9 +++++++++ Kernel/Include/Arch/IO.h | 14 ++++++++++++++ Kernel/Include/IO/IOSerial.h | 9 +++++++++ Kernel/Include/types.h | 8 +++++++- Kernel/Source/IO/IOSerial.c | 25 +++++++++++++++++++++++++ Kernel/Source/KernelMain.c | 5 +++-- 8 files changed, 68 insertions(+), 11 deletions(-) delete mode 100644 .sourcekit-lsp/config.json create mode 100644 Kernel/Include/Arch/CPU.h create mode 100644 Kernel/Include/Arch/IO.h create mode 100644 Kernel/Include/IO/IOSerial.h create mode 100644 Kernel/Source/IO/IOSerial.c diff --git a/.sourcekit-lsp/config.json b/.sourcekit-lsp/config.json deleted file mode 100644 index 96d4543..0000000 --- a/.sourcekit-lsp/config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "defaultWorkspaceType": "compilationDatabase", - "compilationDatabase": { - "searchPaths": [".", "Kernel"] - }, - "backgroundIndexing": true, - "backgroundPreparationMode": "enabled" -} diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 6c42a05..91025ab 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Source/KernelMain.c ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/entry.S +# ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/*.c ${CMAKE_CURRENT_SOURCE_DIR}/Source/**/*.c ) diff --git a/Kernel/Include/Arch/CPU.h b/Kernel/Include/Arch/CPU.h new file mode 100644 index 0000000..ce9532a --- /dev/null +++ b/Kernel/Include/Arch/CPU.h @@ -0,0 +1,9 @@ +#pragma once + +static inline void CPUYield() { + __asm__ volatile ("yield" ::: "memory"); +} + +static inline void CPUWaitForInterrupt() { + __asm__ volatile ("wfi" ::: "memory"); +} \ No newline at end of file diff --git a/Kernel/Include/Arch/IO.h b/Kernel/Include/Arch/IO.h new file mode 100644 index 0000000..6b378d1 --- /dev/null +++ b/Kernel/Include/Arch/IO.h @@ -0,0 +1,14 @@ +#pragma once +#include + +static inline void IOAddressWrite32(UInt64 address, UInt32 value) { + __asm__ volatile ("dsb sy" ::: "memory"); // wait till all previous writes are finished physically + *(volatile UInt32*)address = value; + __asm__ volatile ("dsb sy" ::: "memory"); // wait till my write is finished physically +} + +static inline UInt32 IOAddressRead32(UInt64 address) { + UInt32 value = *(volatile UInt32*)address; + __asm__ volatile ("dsb ld" ::: "memory"); // wait till my read is finished physically + return value; +} \ No newline at end of file diff --git a/Kernel/Include/IO/IOSerial.h b/Kernel/Include/IO/IOSerial.h new file mode 100644 index 0000000..f2d7787 --- /dev/null +++ b/Kernel/Include/IO/IOSerial.h @@ -0,0 +1,9 @@ +#pragma once +#include + +enum { + kUARTBaseAddress = 0x09000000, // TODO: make it dynamic by parsing DTB +}; + +Int32 IOSerialPutCharacter(ASCII character); +Int32 IOSerialPutString(const ASCII* string); \ No newline at end of file diff --git a/Kernel/Include/types.h b/Kernel/Include/types.h index 3c0ad3e..442cefc 100644 --- a/Kernel/Include/types.h +++ b/Kernel/Include/types.h @@ -7,12 +7,18 @@ typedef unsigned char UInt8; typedef unsigned short UInt16; typedef unsigned int UInt32; typedef unsigned long long UInt64; +typedef unsigned long long UInt; + +typedef UInt Address; +typedef UInt8* BytePointer; +typedef UInt8* MemoryPointer; typedef signed char Int8; typedef signed short Int16; typedef signed int Int32; typedef signed long long Int64; +typedef int Int; typedef UInt64 Size; - +typedef char ASCII; diff --git a/Kernel/Source/IO/IOSerial.c b/Kernel/Source/IO/IOSerial.c new file mode 100644 index 0000000..e2cf1f2 --- /dev/null +++ b/Kernel/Source/IO/IOSerial.c @@ -0,0 +1,25 @@ +#include +#include +#include + +Int32 IOSerialPutCharacter(ASCII character) { + // TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18) + UInt64 uartFR = kUARTBaseAddress + 0x18; + + while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) { + CPUYield(); + } + + IOAddressWrite32(kUARTBaseAddress, character); + return character; +} + +Int32 IOSerialPutString(const ASCII* string) { + Int i = 0; + while (string[i] != '\0') { + IOSerialPutCharacter(string[i]); + i++; + } + + return i; +} \ No newline at end of file diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 22c22be..10592dd 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,5 +1,6 @@ -#include "types.h" +#include +#include void KernelMain(void) { - volatile UInt64 meow = 0x12345; + IOSerialPutString("Meow nya!!\n"); } \ No newline at end of file From 93bce5a46d33462ff223c31a1f97f38d5d3e5c94 Mon Sep 17 00:00:00 2001 From: karina Date: Thu, 23 Apr 2026 22:03:18 +0400 Subject: [PATCH 5/9] feat(kernel): add vectors.S and Exceptions.h/c as a stub for future exceptions handling --- Kernel/CMakeLists.txt | 2 +- Kernel/Include/Arch/Exceptions.h | 67 ++++++++++++++++++++++++ Kernel/Source/Arch/Exceptions.c | 10 ++++ Kernel/Source/Arch/entry.S | 1 + Kernel/Source/Arch/vectors.S | 90 ++++++++++++++++++++++++++++++++ Kernel/Source/KernelMain.c | 2 + 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 Kernel/Include/Arch/Exceptions.h create mode 100644 Kernel/Source/Arch/Exceptions.c create mode 100644 Kernel/Source/Arch/vectors.S diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 91025ab..be84ad4 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Source/KernelMain.c ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/entry.S -# ${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/vectors.S ${CMAKE_CURRENT_SOURCE_DIR}/Source/**/*.c ) diff --git a/Kernel/Include/Arch/Exceptions.h b/Kernel/Include/Arch/Exceptions.h new file mode 100644 index 0000000..df48045 --- /dev/null +++ b/Kernel/Include/Arch/Exceptions.h @@ -0,0 +1,67 @@ +#pragma once +#include + +typedef struct ExceptionsContext { + UInt64 x0; + UInt64 x1; + UInt64 x2; + UInt64 x3; + UInt64 x4; + UInt64 x5; + UInt64 x6; + UInt64 x7; + UInt64 x8; + UInt64 x9; + UInt64 x10; + UInt64 x11; + UInt64 x12; + UInt64 x13; + UInt64 x14; + UInt64 x15; + UInt64 x16; + UInt64 x17; + UInt64 x18; + UInt64 x19; + UInt64 x20; + UInt64 x21; + UInt64 x22; + UInt64 x23; + UInt64 x24; + UInt64 x25; + UInt64 x26; + UInt64 x27; + UInt64 x28; + UInt64 x29; // fp + UInt64 x30; // lr + UInt64 elr_el1; // pc + UInt64 spsr_el1; // cpu status + UInt64 esr_el1; // error reason +} ExceptionsContext; + +typedef enum ExceptionsType { + // curr el with sp0 (EL1t) + // usually dont happen cuz we switch to sp_el1, but just in case + ExceptionsSyncEl1t, + ExceptionsIRQEl1t, + ExceptionsFIQEl1t, + ExceptionsSErrorEl1t, + + // curr el with sp1 (EL1h) + // exception in kernel space + ExceptionsSyncEl1h, + ExceptionsIRQEl1h, + ExceptionsFIQEl1h, + ExceptionsSErrorEl1h, + + // lower EL 64-bit from userspace + ExceptionsSyncEl064, + ExceptionsIRQEl064, + ExceptionsFIQEl064, + ExceptionsSErrorEl064, + + // lower EL 32-bit from userspace + ExceptionsSyncEl032, + ExceptionsIRQEl032, + ExceptionsFIQEl032, + ExceptionsSErrorEl032, +} ExceptionsType; \ No newline at end of file diff --git a/Kernel/Source/Arch/Exceptions.c b/Kernel/Source/Arch/Exceptions.c new file mode 100644 index 0000000..952d356 --- /dev/null +++ b/Kernel/Source/Arch/Exceptions.c @@ -0,0 +1,10 @@ +#include +#include +#include + +void ExceptionsHandler(ExceptionsContext* context, ExceptionsType type) { + IOSerialPutString("Exception occurred"); + while (1) { + CPUWaitForInterrupt(); + } +} \ No newline at end of file diff --git a/Kernel/Source/Arch/entry.S b/Kernel/Source/Arch/entry.S index 59853a5..af21614 100644 --- a/Kernel/Source/Arch/entry.S +++ b/Kernel/Source/Arch/entry.S @@ -1,5 +1,6 @@ .section .text.boot, "ax" .global _start _start: + bl ExceptionsVectorsInit bl KernelMain b . \ No newline at end of file diff --git a/Kernel/Source/Arch/vectors.S b/Kernel/Source/Arch/vectors.S new file mode 100644 index 0000000..05e183e --- /dev/null +++ b/Kernel/Source/Arch/vectors.S @@ -0,0 +1,90 @@ +.macro ventry type + .align 7 + sub sp, sp, #272 // save 272 bytes of stack + stp x0, x1, [sp, #0] // move stack + mov x1, #\type // move type to x1 + b ExceptionsTrapEntry +.endm + +.section .text.vectors +.align 11 +.global vectors +ExceptionsVectorsTable: + // EL1t (curr EL with SP0) + ventry 0 // Sync + ventry 1 // IRQ + ventry 2 // FIQ + ventry 3 // SError + + // EL1h (curr EL with SP1) + ventry 4 // Sync + ventry 5 // IRQ + ventry 6 // FIQ + ventry 7 // SError + + // EL0 (lower EL 64-bit from userspace) + ventry 8 // Sync + ventry 9 // IRQ + ventry 10 // FIQ + ventry 11 // SError + + // EL0 (lower EL 32-bit from userspace) + ventry 12; ventry 13; ventry 14; ventry 15 + +ExceptionsTrapEntry: + stp x2, x3, [sp, #16 * 1] + stp x4, x5, [sp, #16 * 2] + stp x6, x7, [sp, #16 * 3] + stp x8, x9, [sp, #16 * 4] + stp x10, x11, [sp, #16 * 5] + stp x12, x13, [sp, #16 * 6] + stp x14, x15, [sp, #16 * 7] + stp x16, x17, [sp, #16 * 8] + stp x18, x19, [sp, #16 * 9] + stp x20, x21, [sp, #16 * 10] + stp x22, x23, [sp, #16 * 11] + stp x24, x25, [sp, #16 * 12] + stp x26, x27, [sp, #16 * 13] + stp x28, x29, [sp, #16 * 14] + + mrs x21, elr_el1 + mrs x22, spsr_el1 + mrs x23, esr_el1 + + stp x30, x21, [sp, #16 * 15] + stp x22, x23, [sp, #16 * 16] + + mov x0, sp + bl ExceptionsHandler + + ldp x22, x23, [sp, #16 * 16] + msr spsr_el1, x22 + + ldp x30, x21, [sp, #16 * 15] + msr elr_el1, x21 + + ldp x28, x29, [sp, #16 * 14] + ldp x26, x27, [sp, #16 * 13] + ldp x24, x25, [sp, #16 * 12] + ldp x22, x23, [sp, #16 * 11] + ldp x20, x21, [sp, #16 * 10] + ldp x18, x19, [sp, #16 * 9] + ldp x16, x17, [sp, #16 * 8] + ldp x14, x15, [sp, #16 * 7] + ldp x12, x13, [sp, #16 * 6] + ldp x10, x11, [sp, #16 * 5] + ldp x8, x9, [sp, #16 * 4] + ldp x6, x7, [sp, #16 * 3] + ldp x4, x5, [sp, #16 * 2] + ldp x2, x3, [sp, #16 * 1] + ldp x0, x1, [sp, #0] + + add sp, sp, #272 + eret + +.global ExceptionsVectorsInit +ExceptionsVectorsInit: + adr x0, ExceptionsVectorsTable + msr vbar_el1, x0 + isb + ret \ No newline at end of file diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 10592dd..ddd4caf 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -3,4 +3,6 @@ void KernelMain(void) { IOSerialPutString("Meow nya!!\n"); + __asm__ volatile ("brk #0"); + IOSerialPutString("How\r\n"); } \ No newline at end of file From f469da7e0b874dbb121ecf0135e6e92d72a27932 Mon Sep 17 00:00:00 2001 From: karina Date: Thu, 23 Apr 2026 22:17:56 +0400 Subject: [PATCH 6/9] refactor(kernel): minor refactor. Changed naming convention --- Kernel/Include/Arch/IO.h | 4 ++-- Kernel/Include/IO/{IOSerial.h => Serial.h} | 0 Kernel/Source/Arch/Exceptions.c | 2 +- Kernel/Source/IO/{IOSerial.c => Serial.c} | 2 +- Kernel/Source/KernelMain.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename Kernel/Include/IO/{IOSerial.h => Serial.h} (100%) rename Kernel/Source/IO/{IOSerial.c => Serial.c} (95%) diff --git a/Kernel/Include/Arch/IO.h b/Kernel/Include/Arch/IO.h index 6b378d1..91f494b 100644 --- a/Kernel/Include/Arch/IO.h +++ b/Kernel/Include/Arch/IO.h @@ -1,13 +1,13 @@ #pragma once #include -static inline void IOAddressWrite32(UInt64 address, UInt32 value) { +static inline void IOAddressWrite32(Address address, UInt32 value) { __asm__ volatile ("dsb sy" ::: "memory"); // wait till all previous writes are finished physically *(volatile UInt32*)address = value; __asm__ volatile ("dsb sy" ::: "memory"); // wait till my write is finished physically } -static inline UInt32 IOAddressRead32(UInt64 address) { +static inline UInt32 IOAddressRead32(Address address) { UInt32 value = *(volatile UInt32*)address; __asm__ volatile ("dsb ld" ::: "memory"); // wait till my read is finished physically return value; diff --git a/Kernel/Include/IO/IOSerial.h b/Kernel/Include/IO/Serial.h similarity index 100% rename from Kernel/Include/IO/IOSerial.h rename to Kernel/Include/IO/Serial.h diff --git a/Kernel/Source/Arch/Exceptions.c b/Kernel/Source/Arch/Exceptions.c index 952d356..200e529 100644 --- a/Kernel/Source/Arch/Exceptions.c +++ b/Kernel/Source/Arch/Exceptions.c @@ -1,6 +1,6 @@ #include #include -#include +#include void ExceptionsHandler(ExceptionsContext* context, ExceptionsType type) { IOSerialPutString("Exception occurred"); diff --git a/Kernel/Source/IO/IOSerial.c b/Kernel/Source/IO/Serial.c similarity index 95% rename from Kernel/Source/IO/IOSerial.c rename to Kernel/Source/IO/Serial.c index e2cf1f2..2a92d13 100644 --- a/Kernel/Source/IO/IOSerial.c +++ b/Kernel/Source/IO/Serial.c @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index ddd4caf..131de92 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,5 +1,5 @@ #include -#include +#include void KernelMain(void) { IOSerialPutString("Meow nya!!\n"); From 373ee00d045e4c9413f778063c81fc122a00d072 Mon Sep 17 00:00:00 2001 From: karina Date: Thu, 23 Apr 2026 23:14:24 +0400 Subject: [PATCH 7/9] feat: add kernel exception panic --- Kernel/Include/Arch/CPU.h | 11 ++++++++- Kernel/Include/OS/Panic.h | 6 +++++ Kernel/Source/Arch/Exceptions.c | 8 +++--- Kernel/Source/KernelMain.c | 2 -- Kernel/Source/OS/Panic.c | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 Kernel/Include/OS/Panic.h create mode 100644 Kernel/Source/OS/Panic.c diff --git a/Kernel/Include/Arch/CPU.h b/Kernel/Include/Arch/CPU.h index ce9532a..ae6aafa 100644 --- a/Kernel/Include/Arch/CPU.h +++ b/Kernel/Include/Arch/CPU.h @@ -1,4 +1,5 @@ #pragma once +#include static inline void CPUYield() { __asm__ volatile ("yield" ::: "memory"); @@ -6,4 +7,12 @@ static inline void CPUYield() { static inline void CPUWaitForInterrupt() { __asm__ volatile ("wfi" ::: "memory"); -} \ No newline at end of file +} + +static inline void CPUDisableInterrupts() { + __asm__ volatile ("msr daifset, #3" ::: "memory"); +} + +static inline void CPUEnableInterrupts() { + __asm__ volatile ("msr daifclr, #3" ::: "memory"); +} diff --git a/Kernel/Include/OS/Panic.h b/Kernel/Include/OS/Panic.h new file mode 100644 index 0000000..c8d69d5 --- /dev/null +++ b/Kernel/Include/OS/Panic.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +__attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame); \ No newline at end of file diff --git a/Kernel/Source/Arch/Exceptions.c b/Kernel/Source/Arch/Exceptions.c index 200e529..532bbb2 100644 --- a/Kernel/Source/Arch/Exceptions.c +++ b/Kernel/Source/Arch/Exceptions.c @@ -1,10 +1,8 @@ #include #include #include +#include -void ExceptionsHandler(ExceptionsContext* context, ExceptionsType type) { - IOSerialPutString("Exception occurred"); - while (1) { - CPUWaitForInterrupt(); - } +void ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) { + OSPanicException(frame); } \ No newline at end of file diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 131de92..7cc4f2d 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -3,6 +3,4 @@ void KernelMain(void) { IOSerialPutString("Meow nya!!\n"); - __asm__ volatile ("brk #0"); - IOSerialPutString("How\r\n"); } \ No newline at end of file diff --git a/Kernel/Source/OS/Panic.c b/Kernel/Source/OS/Panic.c new file mode 100644 index 0000000..769d159 --- /dev/null +++ b/Kernel/Source/OS/Panic.c @@ -0,0 +1,43 @@ +#include +#include +#include + +static const ASCII* GetExceptionClassString(UInt32 class) { + switch (class) { + case 0x00: return "Unknown reason"; + case 0x01: return "Trapped WFI | WFE instruction"; + case 0x07: return "Trapped SIMD | FP instruction"; + case 0x11: return "SVC from EL1"; + case 0x15: return "SVC from EL0"; + case 0x20: return "Instruction abort (LoEL)"; // User Execute Fault + case 0x21: return "Instruction abort (CurrEL)"; // Kernel Execute Fault + case 0x22: return "PC Alignment Fault"; // Jumped to a misaligned address + case 0x24: return "Data abort (LoEL)"; // User Memory Fault + case 0x25: return "Data abort (CurrEL)"; // Kernel Memory Fault + case 0x26: return "SP Alignment Fault"; // SP must be 16-byte aligned + case 0x3C: return "Breakpoint"; + default: return "Reserved"; + } +} + + +__attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) { + UInt32 esr = frame->esr_el1; + UInt32 class = (esr >> 26) & 0x3F; // Exception class (Bits 31:26) + UInt32 length = (esr >> 25) & 0x1; // Instruction length (Bit 25) + UInt32 syndrome = esr & 0x1FFFFFF; // Syndrome (Bits 24:0) + + // i cant show any info since i have no formatter yet :( + IOSerialPutString("\n-------------------\n"); + IOSerialPutString("Kernel Panic! :(\n"); + IOSerialPutString("-------------------\n"); + IOSerialPutString("CPU Exception: "); + IOSerialPutString(GetExceptionClassString(class)); + IOSerialPutString("\n-------------------\n"); + IOSerialPutString("System halted.\n"); + + while (1) { + CPUDisableInterrupts(); + CPUWaitForInterrupt(); + } +} \ No newline at end of file From 78dcfdd662c83fdca72dd835c23ba9d3d7d7d4b5 Mon Sep 17 00:00:00 2001 From: karina Date: Fri, 24 Apr 2026 16:29:46 +0400 Subject: [PATCH 8/9] feat: formatter and oslog() --- Kernel/Include/Lib/String.h | 18 ++++ Kernel/Include/Lib/VAArgs.h | 8 ++ Kernel/Include/OS/Log.h | 8 ++ Kernel/Source/IO/Serial.c | 4 +- Kernel/Source/KernelMain.c | 4 +- Kernel/Source/Lib/String.c | 179 ++++++++++++++++++++++++++++++++++++ Kernel/Source/OS/Log.c | 15 +++ 7 files changed, 231 insertions(+), 5 deletions(-) create mode 100644 Kernel/Include/Lib/String.h create mode 100644 Kernel/Include/Lib/VAArgs.h create mode 100644 Kernel/Include/OS/Log.h create mode 100644 Kernel/Source/Lib/String.c create mode 100644 Kernel/Source/OS/Log.c diff --git a/Kernel/Include/Lib/String.h b/Kernel/Include/Lib/String.h new file mode 100644 index 0000000..201334f --- /dev/null +++ b/Kernel/Include/Lib/String.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include + +void* StringSet(BytePointer destination, ASCII value, Size count); +void* MemoryCopy(void* destination, const void* source, Size count); + +Int32 StringCompare(const ASCII* firstString, const ASCII* secondString); +Int32 StringCompareWithLimit(const ASCII* firstString, const ASCII* secondString, Size limit); + +ASCII* StringCopy(ASCII* destination, const ASCII* source); +ASCII* StringCopyWithLimit(ASCII* destination, const ASCII* source, Size limit); + +Size StringGetLength(const ASCII* string); +const ASCII* StringFindLastOccurrenceOfCharacter(const ASCII* string, ASCII separator); + +Int32 StringFormatVariadic(ASCII* string, Size size, const ASCII* format, va_list args); +Int32 StringFormat(ASCII* destination, UInt64 size, const ASCII* format, ...); \ No newline at end of file diff --git a/Kernel/Include/Lib/VAArgs.h b/Kernel/Include/Lib/VAArgs.h new file mode 100644 index 0000000..da688ef --- /dev/null +++ b/Kernel/Include/Lib/VAArgs.h @@ -0,0 +1,8 @@ +#pragma once + +typedef __builtin_va_list va_list; + +#define va_start(v, l) __builtin_va_start(v, l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v, l) __builtin_va_arg(v, l) +#define va_copy(d, s) __builtin_va_copy(d, s) \ No newline at end of file diff --git a/Kernel/Include/OS/Log.h b/Kernel/Include/OS/Log.h new file mode 100644 index 0000000..5b9d1d2 --- /dev/null +++ b/Kernel/Include/OS/Log.h @@ -0,0 +1,8 @@ +#pragma once +#include + +enum { + kOSLogBufferSize = 1024, +}; + +void OSLog(const ASCII* format, ...); \ No newline at end of file diff --git a/Kernel/Source/IO/Serial.c b/Kernel/Source/IO/Serial.c index 2a92d13..68f7ef9 100644 --- a/Kernel/Source/IO/Serial.c +++ b/Kernel/Source/IO/Serial.c @@ -4,7 +4,7 @@ Int32 IOSerialPutCharacter(ASCII character) { // TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18) - UInt64 uartFR = kUARTBaseAddress + 0x18; + UInt64 uartFR = kUARTBaseAddress + 0x18; while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) { CPUYield(); @@ -22,4 +22,4 @@ Int32 IOSerialPutString(const ASCII* string) { } return i; -} \ No newline at end of file +} diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 7cc4f2d..d21d0c3 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,6 +1,4 @@ -#include -#include +#include void KernelMain(void) { - IOSerialPutString("Meow nya!!\n"); } \ No newline at end of file diff --git a/Kernel/Source/Lib/String.c b/Kernel/Source/Lib/String.c new file mode 100644 index 0000000..5a23995 --- /dev/null +++ b/Kernel/Source/Lib/String.c @@ -0,0 +1,179 @@ +#include +#include + +static void BufferAdd(ASCII* buffer, Size bufferSize, Size* written, ASCII character) { + if (*written + 1 < bufferSize) { + buffer[*written] = character; + } + (*written)++; +} + +void* StringSet(BytePointer destination, ASCII value, Size count) { + BytePointer savedDestination = destination; + while (count--) { + *destination++ = (UInt8) value; + } + return savedDestination; +} + +void* MemoryCopy(void* destination, const void* source, Size count) { + BytePointer destinationBuffer = (BytePointer) destination; + const UInt8* sourceBuffer = (const UInt8*) source; + + while (count >= 8) { + *(UInt64*) destinationBuffer = *(const UInt64*) sourceBuffer; + destinationBuffer += 8; + sourceBuffer += 8; + count -= 8; + } + + while (count > 0) { + *destinationBuffer++ = *sourceBuffer++; + count--; + } + + return destination; +} + +Int32 StringCompare(const ASCII* firstString, const ASCII* secondString) { + while (*firstString && (*firstString == *secondString)) { + firstString++; + secondString++; + } + return *(const UInt8*) firstString - *(const UInt8*) secondString; +} + +Int32 StringCompareWithLimit(const ASCII* firstString, const ASCII* secondString, Size limit) { + while (limit > 0) { + if (*firstString != *secondString) return *(const UInt8*) firstString - *(const UInt8*) secondString; + if (*firstString == '\0') return 0; + firstString++; + secondString++; + limit--; + } + + return 0; +} + +ASCII* StringCopy(ASCII* destination, const ASCII* source) { + ASCII* saved = destination; + while (*source) *destination++ = *source++; + *destination = 0; + return saved; +} + +ASCII* StringCopyWithLimit(ASCII* destination, const ASCII* source, Size limit) { + ASCII* saved = destination; + while (*source && limit > 0) { + *destination++ = *source++; + limit--; + } + while (limit > 0) { + *destination++ = 0; + limit--; + } + return saved; +} + +Size StringGetLength(const ASCII* string) { + Size result = 0; + for (result = 0; string[result]; result++); + return result; +} + +const ASCII* StringFindLastOccurrenceOfCharacter(const ASCII* string, ASCII separator) { + const ASCII* lastSeparator = 0; + do { + if (*string == separator) lastSeparator = string; + } while (*string++); + + return lastSeparator; +} + +Int32 StringFormatVariadic(ASCII* string, Size size, const ASCII* format, va_list args) { + Size written = 0; + for (Size i = 0; format[i] != '\0'; i++) { + if (format[i] == '%') { + i++; + if (format[i] == '\0') break; + switch (format[i]) { + case 's': { + const ASCII* vaArgString = va_arg(args, const ASCII*); + if (!vaArgString) vaArgString = "(null)"; + while (*vaArgString) BufferAdd(string, size, &written, *vaArgString++); + break; + } + case 'c': { + ASCII character = (ASCII)va_arg(args, Int); + BufferAdd(string, size, &written, character); + break; + } + case 'd': { + Int64 number = va_arg(args, Int); + if (number < 0) { + BufferAdd(string, size, &written, '-'); + number = -number; + } + + UInt64 unsignedNumber = (UInt64)number; + ASCII tempBuffer[32]; + Size position = 0; + + if (unsignedNumber == 0) tempBuffer[position++] = '0'; + while (unsignedNumber > 0) { + tempBuffer[position++] = (ASCII)((unsignedNumber % 10) + '0'); + unsignedNumber /= 10; + } + + while (position > 0) BufferAdd(string, size, &written, tempBuffer[--position]); + break; + } + case 'x': + case 'X': { + UInt64 unsignedNumber = va_arg(args, UInt64); + UInt8 padding = (format[i] == 'X') ? 16 : 0; + + ASCII tempBuffer[32]; + Size position = 0; + static const ASCII kHexDigits[] = "0123456789ABCDEF"; + + if (unsignedNumber == 0 && padding == 0) tempBuffer[position++] = '0'; + while (unsignedNumber > 0) { + tempBuffer[position++] = kHexDigits[unsignedNumber % 16]; + unsignedNumber /= 16; + } + + while (position < (Size)padding) tempBuffer[position++] = '0'; + while (position > 0) BufferAdd(string, size, &written, tempBuffer[--position]); + break; + } + case '%': { + BufferAdd(string, size, &written, '%'); + break; + } + default: { + BufferAdd(string, size, &written, '%'); + BufferAdd(string, size, &written, format[i]); + break; + } + } + } else { + BufferAdd(string, size, &written, format[i]); + } + } + + if (size > 0) { + if (written < size) string[written] = '\0'; + else string[size - 1] = '\0'; + } + + return (Int32)written; +} + +Int32 StringFormat(ASCII* destination, UInt64 size, const ASCII* format, ...) { + va_list args; + va_start(args, format); + Int32 returnValue = StringFormatVariadic(destination, size, format, args); + va_end(args); + return returnValue; +} \ No newline at end of file diff --git a/Kernel/Source/OS/Log.c b/Kernel/Source/OS/Log.c new file mode 100644 index 0000000..d69be46 --- /dev/null +++ b/Kernel/Source/OS/Log.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +void OSLog(const ASCII* format, ...) { + ASCII buffer[kOSLogBufferSize]; + + va_list args; + va_start(args, format); + StringFormatVariadic(buffer, kOSLogBufferSize, format, args); + va_end(args); + + IOSerialPutString(buffer); +} \ No newline at end of file From 560bdc8b1d6f810babad8f875bdf4bdb969f443a Mon Sep 17 00:00:00 2001 From: karina Date: Fri, 24 Apr 2026 18:14:04 +0400 Subject: [PATCH 9/9] feat: error parse in panic --- Kernel/Include/Arch/CPU.h | 6 ++++ Kernel/Include/types.h | 1 + Kernel/Source/KernelMain.c | 1 + Kernel/Source/OS/Panic.c | 70 +++++++++++++++++++++++++++++++++----- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/Kernel/Include/Arch/CPU.h b/Kernel/Include/Arch/CPU.h index ae6aafa..d142bc9 100644 --- a/Kernel/Include/Arch/CPU.h +++ b/Kernel/Include/Arch/CPU.h @@ -16,3 +16,9 @@ static inline void CPUDisableInterrupts() { static inline void CPUEnableInterrupts() { __asm__ volatile ("msr daifclr, #3" ::: "memory"); } + +static inline UInt64 CPUGetFAR() { + UInt64 far; + __asm__ volatile ("mrs %0, far_el1" : "=r" (far)); + return far; +} \ No newline at end of file diff --git a/Kernel/Include/types.h b/Kernel/Include/types.h index 442cefc..3e4261f 100644 --- a/Kernel/Include/types.h +++ b/Kernel/Include/types.h @@ -22,3 +22,4 @@ typedef int Int; typedef UInt64 Size; typedef char ASCII; +typedef _Bool Boolean; diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index d21d0c3..3976a24 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,4 +1,5 @@ #include void KernelMain(void) { + OSLog("Hi meow! ;3\n"); } \ No newline at end of file diff --git a/Kernel/Source/OS/Panic.c b/Kernel/Source/OS/Panic.c index 769d159..13883ac 100644 --- a/Kernel/Source/OS/Panic.c +++ b/Kernel/Source/OS/Panic.c @@ -1,5 +1,5 @@ #include -#include +#include #include static const ASCII* GetExceptionClassString(UInt32 class) { @@ -20,6 +20,10 @@ static const ASCII* GetExceptionClassString(UInt32 class) { } } +static void PrintSeparator() { + OSLog("--------------------------------\n"); +} + __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) { UInt32 esr = frame->esr_el1; @@ -27,14 +31,62 @@ __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) { UInt32 length = (esr >> 25) & 0x1; // Instruction length (Bit 25) UInt32 syndrome = esr & 0x1FFFFFF; // Syndrome (Bits 24:0) - // i cant show any info since i have no formatter yet :( - IOSerialPutString("\n-------------------\n"); - IOSerialPutString("Kernel Panic! :(\n"); - IOSerialPutString("-------------------\n"); - IOSerialPutString("CPU Exception: "); - IOSerialPutString(GetExceptionClassString(class)); - IOSerialPutString("\n-------------------\n"); - IOSerialPutString("System halted.\n"); + PrintSeparator(); + OSLog("Kernel Panic! :(\n"); + PrintSeparator(); + OSLog("CPU Exception: %s (%d)\n", GetExceptionClassString(class), class); + OSLog("ESR_EL1 (Syndrome): 0x%x (%d)\n", esr, syndrome); + OSLog("Instruction pointer: 0x%x (%s)\n", frame->elr_el1, length ? "32-bit" : "64-bit"); + OSLog("CPU status: 0x%x\n", frame->spsr_el1); + + if (class == 0x25 || class == 0x24 || class == 0x20 || class == 0x21 ) { + PrintSeparator(); + OSLog("Memory abort helper:\n"); + PrintSeparator(); + + UInt64 far = CPUGetFAR(); + OSLog("Faulting address: 0x%x\n", far); + + UInt32 wnr = (syndrome >> 6) & 0x1; + if (class == 0x24 || class == 0x25) { + OSLog("[W] Caused by %s\n", wnr ? "WRITE" : "READ"); + } else { + OSLog("[T] Tried to execute code from NX/Invalid memory\n"); + } + + + UInt32 dfsc = syndrome & 0x3F; + switch (dfsc & 0b111100) { + case 0b000000: OSLog("[P] Reason: Address size fault (Bad pointer format)\n"); break; + case 0b000100: OSLog("[P] Reason: Translation fault\n"); break; + case 0b001100: OSLog("[P] Reason: Permission fault (Page protection violation)\n"); break; + case 0b010000: OSLog("[P] Reason: Synchronous external abort\n"); break; + case 0b100000: OSLog("[P] Reason: Alignment fault\n"); break; + default: OSLog("[P] Reason: Unknown fault code (0x%X)\n", dfsc); break; + } + } + PrintSeparator(); + OSLog("Registers:\n"); + PrintSeparator(); + OSLog("x0 = 0x%X; x1 = 0x%X\n", frame->x0, frame->x1); + OSLog("x2 = 0x%X; x3 = 0x%X\n", frame->x2, frame->x3); + OSLog("x4 = 0x%X; x5 = 0x%X\n", frame->x4, frame->x5); + OSLog("x6 = 0x%X; x7 = 0x%X\n", frame->x6, frame->x7); + OSLog("x8 = 0x%X; x9 = 0x%X\n", frame->x8, frame->x9); + OSLog("x10 = 0x%X; x11 = 0x%X\n", frame->x10, frame->x11); + OSLog("x12 = 0x%X; x13 = 0x%X\n", frame->x12, frame->x13); + OSLog("x14 = 0x%X; x15 = 0x%X\n", frame->x14, frame->x15); + OSLog("x16 = 0x%X; x17 = 0x%X\n", frame->x16, frame->x17); + OSLog("x18 = 0x%X; x19 = 0x%X\n", frame->x18, frame->x19); + OSLog("x20 = 0x%X; x21 = 0x%X\n", frame->x20, frame->x21); + OSLog("x22 = 0x%X; x23 = 0x%X\n", frame->x22, frame->x23); + OSLog("x24 = 0x%X; x25 = 0x%X\n", frame->x24, frame->x25); + OSLog("x26 = 0x%X; x27 = 0x%X\n", frame->x26, frame->x27); + OSLog("\t\tx28 = 0x%X\n", frame->x28); + OSLog("FP = 0x%X; LR = 0x%X\n", frame->x29, frame->x30); + PrintSeparator(); + + OSLog("System halted.\n"); while (1) { CPUDisableInterrupts();