From 02dc35f0dfd0ac6a7debaa1d4d0842717ec52c85 Mon Sep 17 00:00:00 2001 From: Karina Date: Sat, 31 Jan 2026 20:50:27 +0400 Subject: [PATCH] feat(core): implement spinlocks, GC and keyboard safety * Implemented Spinlocks and applied to VM/Scheduler * Added Garbage Collector for tasks * Moved Getchar to IOKeyboard with locking * Cleanup panic messages --- kernel/inc/IO/IOConsole.h | 1 - kernel/inc/IO/IOKeyboard.h | 11 +++-- kernel/inc/OS/OSScheduler.h | 1 + kernel/inc/OS/OSSpinlock.h | 19 ++++++++ kernel/src/IO/IOConsole.c | 11 +---- kernel/src/IO/IOKeyboard.c | 36 +++++++++++++-- kernel/src/OS/OSPanic.c | 2 - kernel/src/OS/OSScheduler.c | 69 +++++++++++++++++++++++++--- kernel/src/OS/OSSpinlock.c | 29 ++++++++++++ kernel/src/OS/Services/OSServiceIO.c | 3 +- kernel/src/VM/Heap.c | 50 +++++++++++++++----- kernel/src/VM/PMM.c | 18 +++++++- kernel/src/VM/VMM.c | 36 +++++++++++++-- kernel/src/kmain.c | 15 +++--- userspace/debug/src/main.c | 1 + 15 files changed, 251 insertions(+), 51 deletions(-) create mode 100644 kernel/inc/OS/OSSpinlock.h create mode 100644 kernel/src/OS/OSSpinlock.c diff --git a/kernel/inc/IO/IOConsole.h b/kernel/inc/IO/IOConsole.h index 1ea6262..15ab159 100644 --- a/kernel/inc/IO/IOConsole.h +++ b/kernel/inc/IO/IOConsole.h @@ -29,7 +29,6 @@ IOGraphicsSize IOConsoleGetDimensions(); void IOConsoleSetForegroundColor(IOGraphicsColor color); void IOConsoleSetDefaultForegroundColor(UInt32 color); void IOConsoleSetCursorPosition(IOGraphicsPoint* point); -char IOConsoleGetCharacter(); void IOConsoleReadLine(char* buffer, UInt32 limit); void IOConsolePutcharacter(char character); void IOConsolePrint(const char *string); diff --git a/kernel/inc/IO/IOKeyboard.h b/kernel/inc/IO/IOKeyboard.h index dea4ca6..603af06 100644 --- a/kernel/inc/IO/IOKeyboard.h +++ b/kernel/inc/IO/IOKeyboard.h @@ -3,17 +3,20 @@ #pragma once #include +#include enum { kIOKeyboardBufferSize = 256, }; typedef struct { + OSSpinlock lock; char buffer[kIOKeyboardBufferSize]; - UInt16 head; - UInt16 tail; -} IOKeyboardBuffer; + volatile UInt16 head; + volatile UInt16 tail; +} IOKeyboardController; -extern IOKeyboardBuffer gIOKeyboardInputBuffer; +extern IOKeyboardController gIOKeyboardController; void IOKeyboardInterruptsHandler(); +char IOKeyboardGetCharacter(); \ No newline at end of file diff --git a/kernel/inc/OS/OSScheduler.h b/kernel/inc/OS/OSScheduler.h index fedfdd5..9f75d6e 100644 --- a/kernel/inc/OS/OSScheduler.h +++ b/kernel/inc/OS/OSScheduler.h @@ -29,6 +29,7 @@ typedef struct OSTask { UInt32 sleepTicks; OSProcessState taskState; // reusing process_state cuz wn UInt64 kernelStackTop; + void* kernelStackBase; OSProcess* process; Int32 waitingForProcess; } OSTask; diff --git a/kernel/inc/OS/OSSpinlock.h b/kernel/inc/OS/OSSpinlock.h new file mode 100644 index 0000000..4a043d2 --- /dev/null +++ b/kernel/inc/OS/OSSpinlock.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +#include + +typedef struct OSSpinlock { + volatile UInt32 lockValue; +} OSSpinlock; + +typedef struct OSSpinlockState { + Boolean interruptsEnabled; +} OSSpinlockState; + +void OSSpinlockLock(OSSpinlock* lock); +void OSSpinlockUnlock(OSSpinlock* lock); +void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state); +void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state); diff --git a/kernel/src/IO/IOConsole.c b/kernel/src/IO/IOConsole.c index 28da518..09a6769 100644 --- a/kernel/src/IO/IOConsole.c +++ b/kernel/src/IO/IOConsole.c @@ -238,19 +238,10 @@ void IOConsoleSetDefaultForegroundColor(UInt32 color) { sIOConsoleDefaultForegroundColor = color; } -char IOConsoleGetCharacter() { - while (gIOKeyboardInputBuffer.head == gIOKeyboardInputBuffer.tail) { __asm__ volatile ("sti"); OSSchedulerYield(1); } - __asm__ volatile ("cli"); - char temp = gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.tail]; - gIOKeyboardInputBuffer.tail = (gIOKeyboardInputBuffer.tail + 1) % kIOKeyboardBufferSize; - __asm__ volatile ("sti"); - return temp; -} - void IOConsoleReadLine(char* buffer, UInt32 limit) { UInt32 i = 0; while (true) { - char character = IOConsoleGetCharacter(); + char character = IOKeyboardGetCharacter(); switch (character) { case '\n': { buffer[i] = '\0'; diff --git a/kernel/src/IO/IOKeyboard.c b/kernel/src/IO/IOKeyboard.c index 32e3116..3a8c9ee 100644 --- a/kernel/src/IO/IOKeyboard.c +++ b/kernel/src/IO/IOKeyboard.c @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -87,19 +89,20 @@ static unsigned char sIOKeyboardMapShifted[128] = { static Boolean sIOKeyboardIsShiftPressed = false; -IOKeyboardBuffer gIOKeyboardInputBuffer = {0}; +IOKeyboardController gIOKeyboardController = {0}; void IOKeyboardInterruptsHandler() { - UInt16 nextHead = (gIOKeyboardInputBuffer.head + 1) % kIOKeyboardBufferSize; + OSSpinlockLock(&gIOKeyboardController.lock); + UInt16 nextHead = (gIOKeyboardController.head + 1) % kIOKeyboardBufferSize; UInt8 scancode = IOPortRead8(0x60); // make code 0x00 - 0x7F; break code = make code + 0x80 if (scancode < 0x80) { unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap; char ascii = keyMap[scancode]; - if (ascii && nextHead != gIOKeyboardInputBuffer.tail) { - gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.head] = ascii; - gIOKeyboardInputBuffer.head = nextHead; + if (ascii && nextHead != gIOKeyboardController.tail) { + gIOKeyboardController.buffer[gIOKeyboardController.head] = ascii; + gIOKeyboardController.head = nextHead; } else { switch (scancode) { case 0x2A: sIOKeyboardIsShiftPressed = true; break; @@ -112,4 +115,27 @@ void IOKeyboardInterruptsHandler() { default: break; } } + + OSSpinlockUnlock(&gIOKeyboardController.lock); +} + +char IOKeyboardGetCharacter() { + char ascii = 0; + OSSpinlockState state; + + while (true) { + OSSpinlockLockIRQ(&gIOKeyboardController.lock, &state); + + if (gIOKeyboardController.head != gIOKeyboardController.tail) { + ascii = gIOKeyboardController.buffer[gIOKeyboardController.tail]; + gIOKeyboardController.tail = (gIOKeyboardController.tail + 1) % kIOKeyboardBufferSize; + + OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state); + return ascii; + } + + OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state); + __asm__ volatile ("sti"); + OSSchedulerYield(1); + } } diff --git a/kernel/src/OS/OSPanic.c b/kernel/src/OS/OSPanic.c index cd20efe..fc08da5 100644 --- a/kernel/src/OS/OSPanic.c +++ b/kernel/src/OS/OSPanic.c @@ -35,8 +35,6 @@ static const char* sOSPanicFunMessages[] = { "I'll be back", "Hastla la vista, baby", "Ti chego mne tut nagovoril...", - "Your access has been denied because of your region.\n\t\t\t\tPlease, use Chultem VPN and try again later.", - "Fatal error has been occurred. \n\t\t\t\tYour device will be transformed into Niva in a few seconds.", "Have you tried turning it off and on again?", "Put it in rice maybe?", "Just hit the monitor, it usually helps", diff --git a/kernel/src/OS/OSScheduler.c b/kernel/src/OS/OSScheduler.c index 804c5d9..b278258 100644 --- a/kernel/src/OS/OSScheduler.c +++ b/kernel/src/OS/OSScheduler.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 0xKarinyash -#include #include +#include +#include #include #include #include @@ -16,6 +17,7 @@ extern void irq0_handler(); extern UInt64 gVMKernelPML4Physical; static OSProcess sOSSchedulerKernelProcess; +static OSSpinlock sOSSchedulerLock; void idle_task() { while (1) { @@ -23,6 +25,39 @@ void idle_task() { } } + +void OSSchedulerGarbadgeCollector() { + OSTask* self = gOSSchedulerCurrentTask; + + while (true) { + OSTask* previousTask = self; + OSTask* nextTask = previousTask->next; + + while (nextTask != self) { + if (nextTask->taskState == kOSProcessStateDead) { + OSSpinlockState lockState; + OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState); + + previousTask->next = nextTask->next; + + OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState); + + if (nextTask->kernelStackBase) { + VMHeapFree(nextTask->kernelStackBase); + } + VMHeapFree(nextTask); + + nextTask = previousTask->next; + } else { + previousTask = nextTask; + nextTask = nextTask->next; + } + } + + OSSchedulerYield(200); + } +} + void OSSchedulerInitialize() { sOSSchedulerKernelProcess.processId = 0; sOSSchedulerKernelProcess.state = kOSProcessStateRunning; @@ -30,7 +65,10 @@ void OSSchedulerInitialize() { strcpy(sOSSchedulerKernelProcess.name, "kernel"); OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask)); + if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm"); + memset(kernelTask, 0, sizeof(OSTask)); + kernelTask->id = 0; kernelTask->process = &sOSSchedulerKernelProcess; kernelTask->sleepTicks = 0; @@ -40,6 +78,8 @@ void OSSchedulerInitialize() { gOSSchedulerCurrentTask = kernelTask; OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0); + OSSchedulerSpawn(OSSchedulerGarbadgeCollector, &sOSSchedulerKernelProcess, false, 0); + return; } OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) { @@ -74,17 +114,27 @@ OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt6 task->process = owner; task->id = owner->processId; task->sleepTicks = 0; - task->next = gOSSchedulerCurrentTask->next; task->kernelStackTop = (UInt64)stackBaseAddress + stackSize; + task->kernelStackBase = stackBaseAddress; task->taskState = kOSProcessStateRunning; task->waitingForProcess = -1; + + OSSpinlockState state; + OSSpinlockLockIRQ(&sOSSchedulerLock, &state); + + task->next = gOSSchedulerCurrentTask->next; gOSSchedulerCurrentTask->next = task; + + OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state); + return task; } UInt64 OSSchedulerNext(UInt64 currentStackPointer) { if (!gOSSchedulerCurrentTask) return currentStackPointer; + OSSpinlockLock(&sOSSchedulerLock); + gOSSchedulerCurrentTask->stackPointer = currentStackPointer; OSTask* taskIterator = gOSSchedulerCurrentTask->next; @@ -95,12 +145,12 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) { if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--; - OSTask* nextTask = gOSSchedulerCurrentTask; + OSTask* nextTask = gOSSchedulerCurrentTask->next; while (1) { - // TODO: add gc here; - nextTask = nextTask->next; if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning; if (nextTask->taskState == kOSProcessStateRunning) break; + nextTask = nextTask->next; + if (nextTask == gOSSchedulerCurrentTask) { if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break; OSPanic("no running tasks"); @@ -111,6 +161,8 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) { gOSSchedulerCurrentTask = nextTask; gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop; gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop; + + OSSpinlockUnlock(&sOSSchedulerLock); return gOSSchedulerCurrentTask->stackPointer; } @@ -121,6 +173,9 @@ void OSSchedulerBlock(UInt32 processID) { } void OSSchedulerWakeup(UInt32 processID) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sOSSchedulerLock, &state); + OSTask* iteratorTask = gOSSchedulerCurrentTask; do { if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) { @@ -129,6 +184,8 @@ void OSSchedulerWakeup(UInt32 processID) { } iteratorTask = iteratorTask->next; } while (iteratorTask != gOSSchedulerCurrentTask); + + OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state); } void OSSchedulerTerminate() { @@ -143,4 +200,4 @@ void OSSchedulerYield(UInt64 ticks) { gOSSchedulerCurrentTask->sleepTicks = ticks; gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping; __asm__ volatile("hlt"); -} \ No newline at end of file +} diff --git a/kernel/src/OS/OSSpinlock.c b/kernel/src/OS/OSSpinlock.c new file mode 100644 index 0000000..38a7665 --- /dev/null +++ b/kernel/src/OS/OSSpinlock.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#include + +void OSSpinlockLock(OSSpinlock* lock) { + while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) { + while (lock->lockValue) { + __builtin_ia32_pause(); + } + } +} + +void OSSpinlockUnlock(OSSpinlock *lock) { + __atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE); +} + +void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) { + UInt64 rflags; + __asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli + state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit + + OSSpinlockLock(lock); +} + +void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) { + OSSpinlockUnlock(lock); + if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory"); +} \ No newline at end of file diff --git a/kernel/src/OS/Services/OSServiceIO.c b/kernel/src/OS/Services/OSServiceIO.c index 18411d5..e3b60fc 100644 --- a/kernel/src/OS/Services/OSServiceIO.c +++ b/kernel/src/OS/Services/OSServiceIO.c @@ -3,6 +3,7 @@ #include #include +#include UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) { if (fileDescriptor == 1 || fileDescriptor == 2) { @@ -19,7 +20,7 @@ UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) { char* readBuffer = (char*)buffer; if (fileDescriptor == 0) { for (UInt64 i = 0; i < count; i++) { - readBuffer[i] = IOConsoleGetCharacter(); + readBuffer[i] = IOKeyboardGetCharacter(); } return count; } diff --git a/kernel/src/VM/Heap.c b/kernel/src/VM/Heap.c index 2f907c0..2d05a35 100644 --- a/kernel/src/VM/Heap.c +++ b/kernel/src/VM/Heap.c @@ -6,10 +6,12 @@ #include #include #include +#include #include extern UInt64* gVMKernelPML4; static VMHeapBlockHeader* sVMHeapListHead = nullptr; +static OSSpinlock sVMHeapLock = {0}; static void sVMHeapCombineForward(VMHeapBlockHeader* current) { if (!current->next || !current->next->isFree) return; @@ -37,7 +39,7 @@ void VMHeapInitialize() { sVMHeapListHead->previous = nullptr; } -void* VMHeapAllocate(UInt64 size) { +static void* sVMHeapAllocateInternal(UInt64 size) { if (size == 0) return nullptr; UInt64 alignedSize = (size + 15) & ~15; @@ -65,7 +67,7 @@ void* VMHeapAllocate(UInt64 size) { return nullptr; } -void VMHeapFree(void* pointer) { +static void sVMHeapFreeInternal(void* pointer) { if (!pointer) return; VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader)); @@ -76,6 +78,25 @@ void VMHeapFree(void* pointer) { if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous); } +void* VMHeapAllocate(UInt64 size) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMHeapLock, &state); + + void* result = sVMHeapAllocateInternal(size); + + OSSpinlockUnlockIRQ(&sVMHeapLock, &state); + return result; +} + +void VMHeapFree(void* pointer) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMHeapLock, &state); + + sVMHeapFreeInternal(pointer); + + OSSpinlockUnlockIRQ(&sVMHeapLock, &state); +} + void* VMHeapResize(void* pointer, UInt64 newSize) { if (!pointer) return VMHeapAllocate(newSize); if (newSize == 0) { @@ -83,21 +104,28 @@ void* VMHeapResize(void* pointer, UInt64 newSize) { return nullptr; } - VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader)); - if (current->size >= newSize) return pointer; + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMHeapLock, &state); - if (current->next && - current->next->isFree && + VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader)); + if (current->size >= newSize) { + OSSpinlockUnlockIRQ(&sVMHeapLock, &state); + return pointer; + } + + if (current->next && current->next->isFree && (current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable sVMHeapCombineForward(current); + OSSpinlockUnlockIRQ(&sVMHeapLock, &state); return pointer; } - void* newPointer = VMHeapAllocate(newSize); - if (!newPointer) return nullptr; - - memcpy(newPointer, pointer, current->size); - VMHeapFree(pointer); + void* newPointer = sVMHeapAllocateInternal(newSize); + if (newPointer) { + memcpy(newPointer, pointer, current->size); + sVMHeapFreeInternal(pointer); + } + OSSpinlockUnlockIRQ(&sVMHeapLock, &state); return newPointer; } \ No newline at end of file diff --git a/kernel/src/VM/PMM.c b/kernel/src/VM/PMM.c index 179f691..f82daad 100644 --- a/kernel/src/VM/PMM.c +++ b/kernel/src/VM/PMM.c @@ -6,7 +6,9 @@ #include #include -#include +#include +#include + #include #include "bootinfo.h" @@ -16,6 +18,8 @@ UInt8* gVMPhycalMemoryBitmap = nullptr; UInt64 gVMPhycalMemoryBitmapSize = 0; UInt64 gVMPhycalMemoryTotalMemorySize = 0; +static OSSpinlock sVMPMMLock = {0}; + extern UInt64 _kernel_start; extern UInt64 _kernel_end; @@ -96,6 +100,9 @@ void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) { } void* VMPhysicalMemoryAllocatePage() { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMPMMLock, &state); + for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) { if (gVMPhycalMemoryBitmap[i] == 0xFF) continue; @@ -103,13 +110,22 @@ void* VMPhysicalMemoryAllocatePage() { if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) { UInt64 address = (i * 8 + bit) * kVMPageSize; BITMAP_SET(gVMPhycalMemoryBitmap, address); + + OSSpinlockUnlockIRQ(&sVMPMMLock, &state); return (void*)address; } } } + + OSSpinlockUnlockIRQ(&sVMPMMLock, &state); return nullptr; // Out of memory } void VMPhysicalMemoryFreePage(void* address) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMPMMLock, &state); + BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address); + + OSSpinlockUnlockIRQ(&sVMPMMLock, &state); } \ No newline at end of file diff --git a/kernel/src/VM/VMM.c b/kernel/src/VM/VMM.c index f7be376..210dc52 100644 --- a/kernel/src/VM/VMM.c +++ b/kernel/src/VM/VMM.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -20,6 +21,7 @@ enum { UInt64* gVMKernelPML4 = nullptr; UInt64 gVMKernelPML4Physical = 0; +static OSSpinlock sVMVMMlock = {0}; static bool isInitialized = false; extern UInt64 _kernel_start; @@ -36,7 +38,7 @@ static UInt64* sVMGetVirtualTable(UInt64 phys) { return (UInt64*)phys; } -UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) { +static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) { UInt64 pt_idx = VMM_PT_INDEX(virt); UInt64 pd_idx = VMM_PD_INDEX(virt); UInt64 pdpt_idx = VMM_PDPT_INDEX(virt); @@ -92,7 +94,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl return (UInt64*)virt; } -void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) { +static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) { UInt64 pt_idx = VMM_PT_INDEX(virt); UInt64 pd_idx = VMM_PD_INDEX(virt); UInt64 pdpt_idx = VMM_PDPT_INDEX(virt); @@ -115,6 +117,27 @@ void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) { __asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory"); } + +UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMVMMlock, &state); + + UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags); + + OSSpinlockUnlockIRQ(&sVMVMMlock, &state); + return result; +} + +void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMVMMlock, &state); + + sVMVirtualMemoryUnmapPageInternal(pml4, virt); + + OSSpinlockUnlockIRQ(&sVMVMMlock, &state); +} + + void VMLoadCR3(UInt64 pml4_addr) { __asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory"); } @@ -144,8 +167,14 @@ void VMVirtualMemoryInitialize(Bootinfo* info) { } UInt64 VMVirtualMemoryCreateAddressSpace() { + OSSpinlockState state; + OSSpinlockLockIRQ(&sVMVMMlock, &state); + UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage(); - if (!phys) return 0; + if (!phys) { + OSSpinlockUnlockIRQ(&sVMVMMlock, &state); + return 0; + }; UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys); memset(virt, 0, kVMPageSize); @@ -156,6 +185,7 @@ UInt64 VMVirtualMemoryCreateAddressSpace() { virt[i] = kernel_pml4_virt[i]; } + OSSpinlockUnlockIRQ(&sVMVMMlock, &state); return phys; } diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 930e826..6ab7e2d 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -93,20 +94,20 @@ void kmain(Bootinfo* info) { SplashShow(&sIOGraphicsContext); - bool staying_in_ksh = false; + bool rescueMode = false; if (!info->initramfs.address) { - IOConsoleLog("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n"); - staying_in_ksh = true; + IOConsoleLog("^rWARNING^!: Failed to load ^yStartupVolume^!! Staying in kernel rescue shell!\n\n"); + rescueMode = true; } - if (!staying_in_ksh) { + if (!rescueMode) { IOConsoleLog("Press any key to continue booting. \nPress ^yq^! to stay in ^gksh^!\n"); char c = '\n'; - c = IOConsoleGetCharacter(); - if (c == 'q') staying_in_ksh = true; + c = IOKeyboardGetCharacter(); + if (c == 'q') rescueMode = true; } - if (staying_in_ksh) OSSchedulerSpawn(ksh, nullptr, false, 0); + if (rescueMode) OSSchedulerSpawn(ksh, nullptr, false, 0); else OSSchedulerSpawn(init_task_entry, nullptr, false, 0); __asm__ volatile("sti"); diff --git a/userspace/debug/src/main.c b/userspace/debug/src/main.c index bc3e366..65383bb 100644 --- a/userspace/debug/src/main.c +++ b/userspace/debug/src/main.c @@ -69,6 +69,7 @@ void render_list(Vector* numbers) { } int main() { + UInt64* bad_ptr = (UInt64*)0xDEADBEEF; *bad_ptr = 666; Vector nums; vector_init(&nums); printf("Heap test\n");