diff options
Diffstat (limited to 'Private/HALKit')
| -rw-r--r-- | Private/HALKit/AMD64/HalCoreInterruptHandler.cpp | 33 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp | 2 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalCoreSyscallHandlerAMD64.cpp | 12 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalDebugPort.cxx | 8 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalDescriptorLoader.cpp | 55 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalHardwareAPIC.cpp | 4 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalInterruptRouting.asm | 119 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalKernelMain.cxx | 40 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalPageAlloc.cpp | 6 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/HalRoutines.s | 24 | ||||
| -rw-r--r-- | Private/HALKit/AMD64/Processor.hpp | 46 | ||||
| -rw-r--r-- | Private/HALKit/AXP/HAL.s | 4 | ||||
| -rw-r--r-- | Private/HALKit/PowerPC/HalThread.cxx | 2 |
13 files changed, 226 insertions, 129 deletions
diff --git a/Private/HALKit/AMD64/HalCoreInterruptHandler.cpp b/Private/HALKit/AMD64/HalCoreInterruptHandler.cpp index 0b3af515..2acfc454 100644 --- a/Private/HALKit/AMD64/HalCoreInterruptHandler.cpp +++ b/Private/HALKit/AMD64/HalCoreInterruptHandler.cpp @@ -14,23 +14,23 @@ static const char* kExceptionMessages[32] = { "Division by zero", "Debug Breakpoint", - "Non-maskable interrupt", + "Non-maskable Interrupt", "Breakpoint", - "Detected overflow", - "Out-of-bounds", - "Invalid opcode", - "No coprocessor", - "Double fault", - "Coprocessor segment overrun", + "Detected Overflow", + "Out-Of-Bounds", + "Invalid Opcode", + "No Coprocessor", + "Double Fault", + "Coprocessor Segment Overrun", "Bad TSS", - "Segment not found", - "Stack error.", + "Segment Not Found", + "Stack Error", "General Protection Fault", "Page Fault", - "Invalid interrupt", - "Coprocessor fault", - "Alignment check", - "Machine check", + "Invalid Interrupt", + "Coprocessor Fault", + "Alignment Check", + "Machine Check", "Reserved", "Reserved", "Reserved", @@ -49,13 +49,14 @@ static const char* kExceptionMessages[32] = { /// @brief System call interrupt (like DOS and NT) #define kKernelSyscallInterrupt (0x21) -extern "C" { +EXTERN_C { HCore::UIntPtr rt_handle_interrupts(HCore::HAL::StackFramePtr sf) { - HCore::HAL::rt_cli(); + MUST_PASS(sf); if (sf->IntNum < 32) { } else if (sf->IntNum == 0x21) { + rt_syscall_handle(sf); } if ((sf->IntNum - 32) >= 12) { @@ -64,8 +65,6 @@ HCore::UIntPtr rt_handle_interrupts(HCore::HAL::StackFramePtr sf) { HCore::HAL::Out8(0x20, 0x20); - HCore::HAL::rt_sti(); - return (HCore::UIntPtr)sf; } diff --git a/Private/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp b/Private/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp index f1001410..d1483ef3 100644 --- a/Private/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp +++ b/Private/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp @@ -39,7 +39,7 @@ extern "C" void idt_handle_scheduler(HCore::UIntPtr rsp) { HCore::kcout << "HCoreKrnl: Will be scheduled back later " << HCore::ProcessManager::Shared().Leak().GetCurrent().Leak().GetName() - << HCore::EndLine(); + << HCore::end_line(); /// schedule another process. if (!HCore::ProcessHelper::StartScheduling()) { diff --git a/Private/HALKit/AMD64/HalCoreSyscallHandlerAMD64.cpp b/Private/HALKit/AMD64/HalCoreSyscallHandlerAMD64.cpp index cacb66d8..3a3b49b3 100644 --- a/Private/HALKit/AMD64/HalCoreSyscallHandlerAMD64.cpp +++ b/Private/HALKit/AMD64/HalCoreSyscallHandlerAMD64.cpp @@ -11,13 +11,13 @@ #include <HALKit/AMD64/Processor.hpp> #include <KernelKit/PermissionSelector.hxx> -HCore::Array<void (*)(HCore::Int32 id, HCore::HAL::StackFrame *), - kKernelMaxSystemCalls> - kSyscalls; +typedef HCore::Void (*rt_syscall_proc)(HCore::Int32 id, HCore::HAL::StackFramePtr); + +HCore::Array<rt_syscall_proc, kKernelMaxSystemCalls> kSyscalls; /// @brief Interrupt system call handler. -extern "C" void rt_syscall_handle(HCore::HAL::StackFrame *stack) { - for (HCore::SizeT index = 0UL; index < kKernelMaxSystemCalls; ++index) { - if (kSyscalls[index]) (kSyscalls[index].Leak().Leak())(stack->R15, stack); +extern "C" void rt_syscall_handle(HCore::HAL::StackFramePtr stack) { + if (stack->R15 < kKernelMaxSystemCalls && kSyscalls[stack->R15] != 0) { + (kSyscalls[stack->R15].Leak().Leak())(stack->R15, stack); } } diff --git a/Private/HALKit/AMD64/HalDebugPort.cxx b/Private/HALKit/AMD64/HalDebugPort.cxx index d292f95d..510aa421 100644 --- a/Private/HALKit/AMD64/HalDebugPort.cxx +++ b/Private/HALKit/AMD64/HalDebugPort.cxx @@ -42,16 +42,16 @@ void rt_debug_listen(DebuggerPorts* theHook) noexcept { for (UInt32 i = 0U; i < kDebugMaxPorts; ++i) { HAL::Out16(theHook->fPort[i], kDebugMag0); - HAL::rt_wait_for_io(); + HAL::rt_wait_400ns(); HAL::Out16(theHook->fPort[i], kDebugMag1); - HAL::rt_wait_for_io(); + HAL::rt_wait_400ns(); HAL::Out16(theHook->fPort[i], kDebugMag2); - HAL::rt_wait_for_io(); + HAL::rt_wait_400ns(); HAL::Out16(theHook->fPort[i], kDebugMag3); - HAL::rt_wait_for_io(); + HAL::rt_wait_400ns(); if (HAL::In16(theHook->fPort[i] != kDebugUnboundPort)) theHook->fBoundCnt++; } diff --git a/Private/HALKit/AMD64/HalDescriptorLoader.cpp b/Private/HALKit/AMD64/HalDescriptorLoader.cpp index 59952cd3..53218c17 100644 --- a/Private/HALKit/AMD64/HalDescriptorLoader.cpp +++ b/Private/HALKit/AMD64/HalDescriptorLoader.cpp @@ -9,10 +9,8 @@ #include <ArchKit/ArchKit.hpp> -EXTERN_C HCore::UIntPtr ke_handle_irq; - namespace HCore::HAL { -static Register64 kRegGdt; +STATIC Register64 kRegGdt; void GDTLoader::Load(Register64 &gdt) { kRegGdt.Base = gdt.Base; @@ -21,37 +19,58 @@ void GDTLoader::Load(Register64 &gdt) { rt_load_gdt(kRegGdt); } -static volatile HAL::Register64 kRegIdt; +STATIC HAL::Register64 kRegIdt; void IDTLoader::Load(Register64 &idt) { + UInt8 a1, a2; + + a1 = HAL::In8(0x21); // save masks + a2 = HAL::In8(0xA1); + // Remap PIC. HAL::Out8(0x20, 0x11); + HAL::rt_wait_400ns(); HAL::Out8(0xA0, 0x11); + HAL::rt_wait_400ns(); HAL::Out8(0x21, 0x20); + HAL::rt_wait_400ns(); HAL::Out8(0xA1, 0x28); + HAL::rt_wait_400ns(); HAL::Out8(0x21, 0x04); + HAL::rt_wait_400ns(); HAL::Out8(0xA1, 0x02); + HAL::rt_wait_400ns(); HAL::Out8(0x21, 0x01); + HAL::rt_wait_400ns(); HAL::Out8(0xA1, 0x01); - HAL::Out8(0x21, 0x0); - HAL::Out8(0xA1, 0x0); + HAL::rt_wait_400ns(); + HAL::Out8(0x21, a1); + HAL::rt_wait_400ns(); + HAL::Out8(0xA1, a2); - volatile ::HCore::Detail::AMD64::InterruptDescriptorAMD64 *baseIdt = - (::HCore::Detail::AMD64::InterruptDescriptorAMD64 *)idt.Base; + volatile ::HCore::UIntPtr *baseIdt = (::HCore::UIntPtr *)idt.Base; + + MUST_PASS(baseIdt[0]); + + ::HCore::Detail::AMD64::InterruptDescriptorAMD64 *kInterruptVectorTable = + new ::HCore::Detail::AMD64::InterruptDescriptorAMD64[kKernelIdtSize]; for (auto i = 0; i < kKernelIdtSize; i++) { - baseIdt[i].Selector = kGdtCodeSelector; - baseIdt[i].Ist = 0x0; - baseIdt[i].TypeAttributes = kInterruptGate; - baseIdt[i].OffsetLow = (UInt16)((UInt32)ke_handle_irq & 0x000000000000ffff); - baseIdt[i].OffsetMid = - (UInt16)(((UInt32)ke_handle_irq & 0x00000000ffff0000) >> 16); - baseIdt[i].OffsetHigh = - (UInt32)(((UInt32)ke_handle_irq & 0xffffffff00000000) >> 32); - baseIdt[i].Zero = 0x0; + kInterruptVectorTable[i].Selector = kGdtCodeSelector; + kInterruptVectorTable[i].Ist = 0x0; + kInterruptVectorTable[i].TypeAttributes = kInterruptGate; + kInterruptVectorTable[i].OffsetLow = (baseIdt[i] & 0xFF); + kInterruptVectorTable[i].OffsetMid = ((baseIdt[i] & 0xFFFF) >> 16); + kInterruptVectorTable[i].OffsetHigh = ((baseIdt[i] & 0xFFFFFFFF) >> 32); + kInterruptVectorTable[i].Zero = 0x0; } - rt_load_idt(idt); + kRegIdt.Base = (UIntPtr)&kInterruptVectorTable[0]; + kRegIdt.Limit = sizeof(::HCore::Detail::AMD64::InterruptDescriptorAMD64) * + kKernelIdtSize - + 1; + + rt_load_idt(kRegIdt); } void GDTLoader::Load(Ref<Register64> &gdt) { GDTLoader::Load(gdt.Leak()); } diff --git a/Private/HALKit/AMD64/HalHardwareAPIC.cpp b/Private/HALKit/AMD64/HalHardwareAPIC.cpp index 4e985f8e..cae54658 100644 --- a/Private/HALKit/AMD64/HalHardwareAPIC.cpp +++ b/Private/HALKit/AMD64/HalHardwareAPIC.cpp @@ -15,12 +15,12 @@ namespace HCore { // @brief wakes up thread. // wakes up thread from hang. void rt_wakeup_thread(HAL::StackFrame* stack) { - __asm__ volatile("cli"); + HAL::rt_cli(); stack->Rbp = stack->R15; stack->Rsi = stack->Rbp; - __asm__ volatile("sti"); + HAL::rt_sti(); } static void __rt_hang_proc(void) { diff --git a/Private/HALKit/AMD64/HalInterruptRouting.asm b/Private/HALKit/AMD64/HalInterruptRouting.asm index 7de90da0..1ed802b4 100644 --- a/Private/HALKit/AMD64/HalInterruptRouting.asm +++ b/Private/HALKit/AMD64/HalInterruptRouting.asm @@ -11,18 +11,36 @@ [bits 64] +%macro IntDecl 1 + dq __HCR_INT_%1 +%endmacro + +%macro IntExp 1 +__HCR_INT_%1: + push 0 + push %1 + call ke_handle_irq + iretq +%endmacro + +%macro IntNormal 1 +__HCR_INT_%1: + push %1 + call ke_handle_irq + iretq +%endmacro + ; This file handles the core interrupt table ; Last edited 31/01/24 extern rt_handle_interrupts -global ke_power_on_self_test +global _ke_power_on_self_test global ke_handle_irq +global kInterruptVectorTable section .text ke_handle_irq: - cld - push rax push rbx push rcx @@ -41,7 +59,7 @@ ke_handle_irq: mov rcx, rsp call rt_handle_interrupts - mov rsp, rax + mov rsp, rcx pop r15 pop r14 @@ -59,12 +77,95 @@ ke_handle_irq: pop rbx pop rax - std - iretq + ret + +section .data + +IntNormal 0 +IntNormal 1 +IntNormal 2 +IntNormal 3 +IntNormal 4 +IntNormal 5 +IntNormal 6 +IntNormal 7 +IntExp 8 +IntNormal 9 +IntExp 10 +IntExp 11 +IntExp 12 +IntExp 13 +IntExp 14 +IntNormal 15 +IntNormal 16 +IntExp 17 +IntNormal 18 +IntNormal 19 +IntNormal 20 +IntNormal 21 +IntNormal 22 +IntNormal 23 +IntNormal 24 +IntNormal 25 +IntNormal 26 +IntNormal 27 +IntNormal 28 +IntNormal 29 +IntExp 30 +IntNormal 31 + +%assign i 32 +%rep 255 + IntNormal i +%assign i i+1 +%endrep + +section .text ;; this one is doing a POST for us. ;; testing interrupts. -ke_power_on_self_test: +_ke_power_on_self_test: + int 0x21 + int 0x21 + int 0x21 int 0x21 - int 0xe - ret
\ No newline at end of file + int 0x21 + int 0x21 + int 0x21 + int 0x21 + + ret + +[global rt_load_gdt] + +rt_load_gdt: + lgdt [rcx] + push 0x08 + lea rax, [rel rt_reload_segments] + push rax + retfq +rt_reload_segments: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + ret + +global rt_load_idt + +section .text + +rt_load_idt: + lidt [rcx] + ret + +section .data + +kInterruptVectorTable: + %assign i 0 + %rep 255 + IntDecl i + %assign i i+1 + %endrep diff --git a/Private/HALKit/AMD64/HalKernelMain.cxx b/Private/HALKit/AMD64/HalKernelMain.cxx index c4f4ed94..d799e5ae 100644 --- a/Private/HALKit/AMD64/HalKernelMain.cxx +++ b/Private/HALKit/AMD64/HalKernelMain.cxx @@ -20,10 +20,15 @@ #include <NewKit/KernelHeap.hpp> #include <NewKit/UserHeap.hpp> +///! @brief Disk contains HCore files. +#define kInstalledMedia 0xDD + +EXTERN_C VoidStar kInterruptVectorTable[]; + namespace Detail { using namespace HCore; -EXTERN_C void ke_power_on_self_test(void); +EXTERN_C void _ke_power_on_self_test(void); /** @brief Global descriptor table entry, either null, code or data. @@ -55,16 +60,16 @@ EXTERN_C void RuntimeMain( kKernelVirtualSize = HandoverHeader->f_VirtualSize; kKernelVirtualStart = HandoverHeader->f_VirtualStart; - kKernelPhysicalSize = HandoverHeader->f_VirtualSize; - kKernelPhysicalStart = HandoverHeader->f_VirtualStart; + kKernelPhysicalSize = HandoverHeader->f_PhysicalSize; + kKernelPhysicalStart = HandoverHeader->f_PhysicalStart; static Detail::HC_GDT GDT = { {0, 0, 0, 0x00, 0x00, 0}, // null entry - {0, 0, 0, 0x9a, 0xa0, 0}, // kernel code - {0, 0, 0, 0x92, 0xa0, 0}, // kernel data + {0, 0, 0, 0x9a, 0xaf, 0}, // kernel code + {0, 0, 0, 0x92, 0xaf, 0}, // kernel data {0, 0, 0, 0x00, 0x00, 0}, // null entry - {0, 0, 0, 0x9a, 0xa0, 0}, // user code - {0, 0, 0, 0x92, 0xa0, 0}, // user data + {0, 0, 0, 0x9a, 0xaf, 0}, // user code + {0, 0, 0, 0x92, 0xaf, 0}, // user data }; HCore::HAL::Register64 gdtBase; @@ -79,19 +84,15 @@ EXTERN_C void RuntimeMain( /// load idt buffer - constexpr HCore::Int IDT_SIZE = 4095; - - HCore::UIntPtr* kInterruptVectorTable = new HCore::UIntPtr[IDT_SIZE]; - HCore::HAL::Register64 idtBase; idtBase.Base = (HCore::UIntPtr)kInterruptVectorTable; - idtBase.Limit = IDT_SIZE; + idtBase.Limit = 0; HCore::HAL::IDTLoader idt; idt.Load(idtBase); - if (HandoverHeader->f_Bootloader == 0xDD) { - /// Mounts a NewFS partition. + if (HandoverHeader->f_Bootloader == kInstalledMedia) { + /// Mounts a NewFS block. HCore::IFilesystemManager::Mount(new HCore::NewFilesystemManager()); // Open file from first hard-drive. @@ -106,15 +107,8 @@ EXTERN_C void RuntimeMain( ** This does the POST. */ - HCore::kcout << "FOOBAR." << HCore::EndLine(); - - Detail::ke_power_on_self_test(); - - HCore::kcout << "FOOBAR." << HCore::EndLine(); - /** - ** This draws the HCore resource icon.. - */ - + Detail::_ke_power_on_self_test(); + /** This mounts the NewFS drive. */ diff --git a/Private/HALKit/AMD64/HalPageAlloc.cpp b/Private/HALKit/AMD64/HalPageAlloc.cpp index 4654ab7b..84ddc665 100644 --- a/Private/HALKit/AMD64/HalPageAlloc.cpp +++ b/Private/HALKit/AMD64/HalPageAlloc.cpp @@ -22,6 +22,8 @@ namespace HCore { namespace HAL { static auto hal_try_alloc_new_page(SizeT sz, Boolean rw, Boolean user) -> PageTable64 * { + MUST_PASS(sz != 0); + PageTable64 *pte = reinterpret_cast<PageTable64 *>((UIntPtr)kKernelVirtualStart); @@ -29,8 +31,8 @@ static auto hal_try_alloc_new_page(SizeT sz, Boolean rw, Boolean user) pte->User = user; pte->Present = true; - kKernelVirtualStart = - (VoidPtr)((UIntPtr)kKernelVirtualStart + kPageCnt + sz + kKernelPagingPadding); + kKernelVirtualStart = (VoidPtr)((UIntPtr)kKernelVirtualStart + kPageCnt + sz + + kKernelPagingPadding); return pte; } diff --git a/Private/HALKit/AMD64/HalRoutines.s b/Private/HALKit/AMD64/HalRoutines.s index bbef4bbd..a25b25c7 100644 --- a/Private/HALKit/AMD64/HalRoutines.s +++ b/Private/HALKit/AMD64/HalRoutines.s @@ -1,30 +1,10 @@ .globl rt_load_idt .globl rt_load_gdt -.globl rt_wait_for_io +.globl rt_wait_400ns .globl rt_get_current_context .section .text -rt_load_gdt: - lgdt (%rcx) - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - pop %rdi - mov $0x08, %rax - push %rax - push %rdi - retfq - -rt_load_idt: - lidt (%rcx) - sti - ret - -.section .text -rt_wait_for_io: +rt_wait_400ns: jmp .loop .loop: jmp .loop2 diff --git a/Private/HALKit/AMD64/Processor.hpp b/Private/HALKit/AMD64/Processor.hpp index e5e66f09..035b095f 100644 --- a/Private/HALKit/AMD64/Processor.hpp +++ b/Private/HALKit/AMD64/Processor.hpp @@ -36,29 +36,30 @@ namespace Detail::AMD64 { struct PACKED InterruptDescriptorAMD64 final { UInt16 OffsetLow; // offset bits 0..15 UInt16 Selector; // a code segment selector in GDT or LDT - UInt8 Ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero. + UInt8 + Ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero. UInt8 TypeAttributes; // gate type, dpl, and p fields UInt16 OffsetMid; // offset bits 16..31 UInt32 OffsetHigh; // offset bits 32..63 UInt32 Zero; // reserved }; } // namespace Detail::AMD64 -} // namespace HCore +} // namespace HCore namespace HCore::HAL { -extern "C" UChar In8(UInt16 port); -extern "C" UShort In16(UInt16 port); -extern "C" UInt In32(UInt16 port); +EXTERN_C UChar In8(UInt16 port); +EXTERN_C UShort In16(UInt16 port); +EXTERN_C UInt In32(UInt16 port); -extern "C" void Out16(UShort port, UShort byte); -extern "C" void Out8(UShort port, UChar byte); -extern "C" void Out32(UShort port, UInt byte); +EXTERN_C void Out16(UShort port, UShort byte); +EXTERN_C void Out8(UShort port, UChar byte); +EXTERN_C void Out32(UShort port, UInt byte); -extern "C" void rt_wait_for_io(); -extern "C" void rt_halt(); -extern "C" void rt_cli(); -extern "C" void rt_sti(); -extern "C" void rt_cld(); +EXTERN_C void rt_wait_400ns(); +EXTERN_C void rt_halt(); +EXTERN_C void rt_cli(); +EXTERN_C void rt_sti(); +EXTERN_C void rt_cld(); class PACKED Register64 { public: @@ -74,7 +75,6 @@ using interruptTrap = UIntPtr(UIntPtr sp); typedef UIntPtr Reg; struct PACKED StackFrame { - Reg ExceptionZ; Reg IntNum; Reg Rax; Reg Rbx; @@ -151,13 +151,15 @@ class IDTLoader final { void system_get_cores(voidPtr rsdPtr); } // namespace HCore::HAL -extern "C" void idt_handle_system_call(HCore::UIntPtr rsp); -extern "C" void idt_handle_generic(HCore::UIntPtr rsp); -extern "C" void idt_handle_gpf(HCore::UIntPtr rsp); -extern "C" void idt_handle_math(HCore::UIntPtr rsp); -extern "C" void idt_handle_pf(HCore::UIntPtr rsp); +EXTERN_C void idt_handle_system_call(HCore::UIntPtr rsp); +EXTERN_C void idt_handle_generic(HCore::UIntPtr rsp); +EXTERN_C void idt_handle_gpf(HCore::UIntPtr rsp); +EXTERN_C void idt_handle_math(HCore::UIntPtr rsp); +EXTERN_C void idt_handle_pf(HCore::UIntPtr rsp); -extern "C" void rt_load_idt(HCore::HAL::Register64 ptr); -extern "C" void rt_load_gdt(HCore::HAL::Register64 ptr); +EXTERN_C void rt_load_idt(HCore::HAL::Register64 ptr); +EXTERN_C void rt_load_gdt(HCore::HAL::Register64 ptr); + +/// @brief Maximum size of the IDT. +#define kKernelIdtSize 256 -#define kKernelIdtSize 256
\ No newline at end of file diff --git a/Private/HALKit/AXP/HAL.s b/Private/HALKit/AXP/HAL.s index 46127130..0178527f 100644 --- a/Private/HALKit/AXP/HAL.s +++ b/Private/HALKit/AXP/HAL.s @@ -1,7 +1,7 @@ -.globl rt_wait_for_io +.globl rt_wait_400ns .section .text -rt_wait_for_io: +rt_wait_400ns: jmp .L .L: jmp .L2 diff --git a/Private/HALKit/PowerPC/HalThread.cxx b/Private/HALKit/PowerPC/HalThread.cxx index b280ba90..0c6cfa4b 100644 --- a/Private/HALKit/PowerPC/HalThread.cxx +++ b/Private/HALKit/PowerPC/HalThread.cxx @@ -11,6 +11,6 @@ #include <KernelKit/DebugOutput.hpp> extern "C" void flush_tlb() {} -extern "C" void rt_wait_for_io() {} +extern "C" void rt_wait_400ns() {} extern "C" HCore::HAL::StackFramePtr rt_get_current_context() { return nullptr; } |
