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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -3,17 +3,20 @@
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
|
||||
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();
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
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);
|
||||
@@ -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';
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <IO/IOKeyboard.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
|
||||
#include <IO.h>
|
||||
#include <types.h>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <lib/String.h>
|
||||
#include <VM/Heap.h>
|
||||
#include <VM/VMM.h>
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/OSSpinlock.h>
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <OS/Services/OSServiceIO.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <IO/IOKeyboard.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+39
-11
@@ -6,10 +6,12 @@
|
||||
#include <VM/VMM.h>
|
||||
#include <lib/String.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
#include <types.h>
|
||||
|
||||
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;
|
||||
}
|
||||
+17
-1
@@ -6,7 +6,9 @@
|
||||
#include <lib/String.h>
|
||||
#include <lib/Math.h>
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
+33
-3
@@ -4,6 +4,7 @@
|
||||
#include <VM/PMM.h>
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSSpinlock.h>
|
||||
|
||||
#include <GDT.h>
|
||||
#include <IDT.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -11,6 +11,7 @@
|
||||
#include <IO/IOSerial.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <IO/IOTimer.h>
|
||||
#include <IO/IOKeyboard.h>
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user