From 97538aa09867272cb9bb787911bdfe93a185c26f Mon Sep 17 00:00:00 2001 From: karina Date: Wed, 22 Apr 2026 09:32:01 +0400 Subject: [PATCH] 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