completely redesign how user mode memory is allocated, fix a few smp and scheduler bugs, terminating a process now terminates the process, telemetry, optimize text editor, new font, new color scheme

This commit is contained in:
maksw committed 2026-06-09 18:02:28 +02:00
1 parent 27b31f62b6
commit 325149006c
45 files changed
+2091 -760

No files matched your search

+1 -1
View File
@@ -93,7 +93,7 @@ static int gS5Found = 0;
int debugEnabled = 0;
int _fltused; // MSVC floating-point helper anchor
static void hal_putchar(char c) {
gApi.Screen.PrintChar(c, 0x00FF00, 0x000000);
gApi.Screen.PrintChar(c, 0xCCCCCC, 0x012456);
}
void HalDbgPrint(const char* fmt, ...) {
if (!debugEnabled) return;
+20 -9
View File
@@ -19,6 +19,9 @@ static int gCursorX = 0, gCursorY = 0;
#define FONT_W 8
#define FONT_H 16
#define SCREEN_DEFAULT_FG 0xCCCCCCu
#define SCREEN_DEFAULT_BG 0x012456u
// ---------------------------------------------------------------------------
// 8x16 VGA font - printable ASCII only (glyph 0 = space = 0x20)
// ---------------------------------------------------------------------------
@@ -113,28 +116,36 @@ static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) {
static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; }
static void ScreenScroll(int lines) {
if (lines <= 0 || lines >= gHeight) { ScreenClear(0); return; }
if (lines <= 0)
return;
if (lines >= gHeight) {
ScreenClear(SCREEN_DEFAULT_BG);
return;
}
size_t rowBytes = (size_t)gStride * sizeof(uint32_t);
uint32_t* shadow = gBackbuffer ? gBackbuffer : gFb;
memmove(shadow, shadow + lines * gStride,
(size_t)(gHeight - lines) * rowBytes);
// Clear the revealed rows at the bottom.
memset(shadow + (gHeight - lines) * gStride, 0,
(size_t)lines * rowBytes);
// Fill the revealed rows with the console background. Do not memset here:
// the background color is not zero.
uint32_t* fill = shadow + (gHeight - lines) * gStride;
for (int y = 0; y < lines; y++) {
for (int x = 0; x < gWidth; x++)
fill[y * gStride + x] = SCREEN_DEFAULT_BG;
}
ScreenFlushRows(0, gHeight);
}
static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) {
if ((unsigned char)c < 0x20 || (unsigned char)c > 0x7E) c = '?';
const uint8_t* glyph = Font8x16 + ((unsigned char)c - 0x20) * 16;
const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16);
for (int row = 0; row < 16; row++) {
uint8_t bits = glyph[row];
for (int col = 0; col < 8; col++) {
uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why
// i shouldn't have to wonder why but the font is backwards unless we do this terriblness
uint32_t color = (bits & (0x80u >> col)) ? fg : bg;
PutPixelRaw(x + col, y + row, color);
}
}
@@ -321,5 +332,5 @@ void HalScreenInitialize(void* (*AllocatePool)(size_t size), uintptr_t fb, int w
out->PrintChar = ScreenPrintChar;
out->DrawCursor = HalScreenDrawCursor;
out->EraseCursor = HalScreenEraseCursor;
ScreenClear(0x000000);
ScreenClear(SCREEN_DEFAULT_BG);
}
+10 -4
View File
@@ -175,6 +175,13 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) {
return elapsed / 10; // APIC ticks per ms
}
__declspec(dllexport) void HalTimerConfigureCurrentCpu(void) {
if (!gLapic || !gApicTicksPerQuantum) return;
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR;
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
}
KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *out) {
gLapic = (volatile uint32_t *)gApi.PhysToVirt(lapicPhys);
HalDbgPrint("HAL: lapicPhys=0x%016llX, lapicVirt=0x%016llX, hpetPhys=0x%016llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys);
@@ -205,10 +212,9 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
HalDbgPrint("HAL: APIC timer: %u ticks/ms\n", ticksPerMs);
// Configure LAPIC timer in periodic mode
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR;
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
// Configure this CPU's LAPIC timer; APs call HalTimerConfigureCurrentCpu()
// after enabling their local APIC.
HalTimerConfigureCurrentCpu();
out->QueryTicks = QueryTicks;
out->Stall = Stall;
+515 -193
View File
@@ -1,199 +1,521 @@
#pragma once
// font8x16.h - embedded 8x16 VGA bitmap font, printable ASCII (0x20-0x7E)
// 95 glyphs × 16 bytes = 1520 bytes total.
// Each byte is one scanline; bit 7 = leftmost pixel.
// font8x16.h - embedded 8x16 CP437 bitmap font.
// Source: PC Face oldschool-vga-8x16 fontlist.js.
// Converted from: oldschool-vga-8x16-fontlist.js
// Layout: 256 glyphs * 16 scanlines. Bit 7 is the leftmost pixel.
#include <stdint.h>
static const uint8_t Font8x16[95 * 16] = {
// 0x20 ' '
static const uint8_t Font8x16[256 * 16] = {
// 0x00
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x21 '!'
0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
// 0x22 '"'
0x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x23 '#'
0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x24 '$'
0x18,0x18,0x3E,0x63,0x03,0x03,0x1E,0x30,0x30,0x63,0x3E,0x18,0x18,0x00,0x00,0x00,
// 0x25 '%'
0x00,0x00,0x63,0x33,0x18,0x0C,0x06,0x31,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x26 '&'
0x00,0x1C,0x36,0x1C,0x0E,0x3B,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x27 '\''
0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x28 '('
0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x29 ')'
0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2A '*'
0x00,0x00,0x00,0x33,0x1E,0xFF,0x1E,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2B '+'
0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2C ','
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2D '-'
0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2E '.'
// 0x01
0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,
// 0x02
0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,
// 0x03
0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
// 0x04
0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
// 0x05
0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x06
0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x07
0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x08
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
// 0x09
0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
// 0x0A
0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,
// 0x0B
0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
// 0x0C
0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x0D
0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,
// 0x0E
0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,
// 0x0F
0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x10
0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
// 0x11
0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
// 0x12
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
// 0x13
0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
// 0x14
0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
// 0x15
0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,
// 0x16
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,
// 0x17
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
// 0x18
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x19
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,
// 0x1A
0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x1B
0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x1C
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x1D
0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x1E
0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,
// 0x1F
0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
// 0x20
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x21
0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x22
0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x23
0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
// 0x24
0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,
// 0x25
0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,
// 0x26
0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x27
0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x28
0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,
// 0x29
0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,
// 0x2A
0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2B
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2C
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
// 0x2D
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2E
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x2F
0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,
// 0x30
0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
// 0x31
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
// 0x32
0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
// 0x33
0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x34
0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
// 0x35
0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x36
0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x37
0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
// 0x38
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x39
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
// 0x3A
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
// 0x3B
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
// 0x3C
0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
// 0x3D
0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3E
0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
// 0x3F
0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x40
0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,
// 0x41
0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x42
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
// 0x43
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
// 0x44
0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
// 0x45
0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
// 0x46
0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
// 0x47
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,
// 0x48
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x49
0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x4A
0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
// 0x4B
0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
// 0x4C
0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
// 0x4D
0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x4E
0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x4F
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x50
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
// 0x51
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,
// 0x52
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
// 0x53
0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x54
0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x55
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x56
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
// 0x57
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
// 0x58
0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x59
0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x5A
0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
// 0x5B
0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
// 0x5C
0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
// 0x5D
0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,
// 0x5E
0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5F
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,
// 0x60
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x61
0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x62
0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
// 0x63
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x64
0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x65
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x66
0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
// 0x67
0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00,
// 0x68
0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
// 0x69
0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x6A
0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,
// 0x6B
0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
// 0x6C
0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x6D
0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00,
// 0x6E
0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
// 0x6F
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x70
0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
// 0x71
0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
// 0x72
0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
// 0x73
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x74
0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
// 0x75
0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x76
0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
// 0x77
0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,
// 0x78
0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,
// 0x79
0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
// 0x7A
0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
// 0x7B
0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
// 0x7C
0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x7D
0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
// 0x7E
0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7F
0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,
// 0x80
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,
// 0x81
0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x82
0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x83
0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x84
0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x85
0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x86
0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x87
0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,
// 0x88
0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x89
0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x8A
0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x8B
0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x8C
0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x8D
0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0x8E
0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x8F
0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0x90
0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,
// 0x91
0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
// 0x92
0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
// 0x93
0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x94
0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x95
0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x96
0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x97
0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0x98
0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
// 0x99
0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x9A
0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0x9B
0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x9C
0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
// 0x9D
0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
// 0x9E
0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,
// 0x9F
0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,
// 0xA0
0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0xA1
0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
// 0xA2
0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0xA3
0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
// 0xA4
0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
// 0xA5
0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0xA6
0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xA7
0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xA8
0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
// 0xA9
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,
// 0xAA
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
// 0xAB
0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,
// 0xAC
0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,
// 0xAD
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
// 0xAE
0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xAF
0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xB0
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
// 0xB1
0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
// 0xB2
0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
// 0xB3
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xB4
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xB5
0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xB6
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xB7
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xB8
0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xB9
0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xBA
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xBB
0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xBC
0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xBD
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xBE
0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xBF
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xC0
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xC1
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xC2
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xC3
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xC4
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xC5
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xC6
0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xC7
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xC8
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xC9
0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xCA
0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xCB
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xCC
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xCD
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xCE
0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xCF
0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xD0
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xD1
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xD2
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xD3
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xD4
0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xD5
0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xD6
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xD7
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
// 0xD8
0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xD9
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xDA
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xDB
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
// 0xDC
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
// 0xDD
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
// 0xDE
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
// 0xDF
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xE0
0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,
// 0xE1
0x00,0x00,0x78,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00,
// 0xE2
0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
// 0xE3
0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
// 0xE4
0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
// 0xE5
0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
// 0xE6
0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00,
// 0xE7
0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
// 0xE8
0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
// 0xE9
0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
// 0xEA
0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,
// 0xEB
0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
// 0xEC
0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xED
0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,
// 0xEE
0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,
// 0xEF
0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
// 0xF0
0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
// 0xF1
0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
// 0xF2
0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,
// 0xF3
0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,
// 0xF4
0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
// 0xF5
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
// 0xF6
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
// 0xF7
0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xF8
0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xF9
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x2F '/'
0x00,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x30 '0'
0x00,0x3C,0x66,0x66,0x76,0x6E,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x31 '1'
0x00,0x18,0x1C,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x32 '2'
0x00,0x3C,0x66,0x60,0x30,0x18,0x0C,0x66,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x33 '3'
0x00,0x3C,0x66,0x60,0x38,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x34 '4'
0x00,0x30,0x38,0x3C,0x36,0x33,0x7F,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x35 '5'
0x00,0x7E,0x06,0x06,0x3E,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x36 '6'
0x00,0x38,0x0C,0x06,0x3E,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x37 '7'
0x00,0x7E,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x38 '8'
0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x39 '9'
0x00,0x3C,0x66,0x66,0x7C,0x60,0x30,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3A ':'
0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3B ';'
0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3C '<'
0x00,0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3D '='
0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3E '>'
0x00,0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x3F '?'
0x00,0x3C,0x66,0x60,0x30,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x40 '@'
0x00,0x3E,0x63,0x7B,0x7B,0x7B,0x3B,0x03,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x41 'A'
0x00,0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x42 'B'
0x00,0x3E,0x66,0x66,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x43 'C'
0x00,0x3C,0x66,0x06,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x44 'D'
0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x36,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x45 'E'
0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x46 'F'
0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x47 'G'
0x00,0x3C,0x66,0x06,0x06,0x76,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x48 'H'
0x00,0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x49 'I'
0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4A 'J'
0x00,0x78,0x30,0x30,0x30,0x30,0x36,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4B 'K'
0x00,0x66,0x36,0x1E,0x0E,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4C 'L'
0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4D 'M'
0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4E 'N'
0x00,0x63,0x67,0x6F,0x7B,0x73,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x4F 'O'
0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x50 'P'
0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x51 'Q'
0x00,0x3C,0x66,0x66,0x66,0x66,0x6E,0x3C,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x52 'R'
0x00,0x3E,0x66,0x66,0x3E,0x36,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x53 'S'
0x00,0x3C,0x66,0x06,0x1C,0x30,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x54 'T'
0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x55 'U'
0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x56 'V'
0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x57 'W'
0x00,0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x58 'X'
0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x59 'Y'
0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5A 'Z'
0x00,0x7E,0x60,0x30,0x18,0x0C,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5B '['
0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5C '\'
0x00,0x03,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5D ']'
0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5E '^'
0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x5F '_'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x60 '`'
0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x61-0x7A lowercase - condensed to save space, using same shapes as upper offset by 32
// 0x61 'a'
0x00,0x00,0x00,0x1C,0x30,0x3C,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x62 'b'
0x00,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x63 'c'
0x00,0x00,0x00,0x3C,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x64 'd'
0x00,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x65 'e'
0x00,0x00,0x00,0x3C,0x66,0x7E,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x66 'f'
0x00,0x38,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x67 'g'
0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x68 'h'
0x00,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x69 'i'
0x00,0x18,0x00,0x1C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6A 'j'
0x00,0x30,0x00,0x38,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6B 'k'
0x00,0x06,0x06,0x66,0x36,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6C 'l'
0x00,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6D 'm'
0x00,0x00,0x00,0x37,0x7F,0x6B,0x6B,0x6B,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6E 'n'
0x00,0x00,0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6F 'o'
0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x70 'p'
0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x71 'q'
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x72 'r'
0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x73 's'
0x00,0x00,0x00,0x3C,0x06,0x1C,0x30,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x74 't'
0x00,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x75 'u'
0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x76 'v'
0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x77 'w'
0x00,0x00,0x00,0x63,0x6B,0x6B,0x7F,0x77,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x78 'x'
0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x79 'y'
0x00,0x00,0x66,0x66,0x66,0x7C,0x60,0x30,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7A 'z'
0x00,0x00,0x00,0x7E,0x30,0x18,0x0C,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7B '{'
0x00,0x30,0x18,0x18,0x0C,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7C '|'
0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7D '}'
0x00,0x0C,0x18,0x18,0x30,0x18,0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x7E '~'
0x00,0x6E,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xFA
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xFB
0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,
// 0xFC
0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xFD
0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0xFE
0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,
// 0xFF
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
@@ -34,4 +34,5 @@ __declspec(dllexport) void HalApicEnableCurrentCpu(void);
__declspec(dllexport) void HalApicSendPanicIpi(void);
__declspec(dllexport) void HalApicSendRescheduleIpi(uint32_t lapicId);
__declspec(dllexport) void HalApicSendTlbShootdownIpi(uint32_t lapicId);
__declspec(dllexport) void HalTimerConfigureCurrentCpu(void);
__declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uint8_t startupVector);
-1
View File
@@ -31,7 +31,6 @@ KSTATUS LdrResolveImports(uintptr_t imageBase);
KSTATUS LdrResolveImportsForProcess(struct PROCESS* process, uintptr_t imageBase);
// Apply final page permissions for a loaded image after relocations/imports.
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user);
KSTATUS LdrProtectImageForProcess(struct PROCESS* process, uintptr_t imageBase, bool user);
// Load a DLL for a specific process, resolve it against that process's
+11 -1
View File
@@ -1,6 +1,6 @@
#pragma once
// mm_phys.h - physical memory manager (PMM)
// Stack allocator over 4 KB frames, seeded from MEMORY_MAP.
// Bitmap allocator over 4 KB frames, seeded from MEMORY_MAP.
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
@@ -11,6 +11,15 @@
typedef uint64_t PHYSICAL_ADDRESS;
typedef struct MM_PHYSICAL_STATS {
uint64_t TotalFrames;
uint64_t FreeFrames;
uint64_t UsedFrames;
uint64_t LargestFreeRun;
uint64_t FreeRunCount;
uint64_t FreeRunHistogram[8];
} MM_PHYSICAL_STATS;
// Called once by KernelMain with the MEMORY_MAP from BOOT_INFO.
bool MmInitializePhysical(const MEMORY_MAP* map,
uint64_t physicalWindowBase);
@@ -29,3 +38,4 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count);
size_t MmFreeFrameCount(void);
size_t MmTotalFrameCount(void);
void MmQueryPhysicalStats(MM_PHYSICAL_STATS* out);
+8 -2
View File
@@ -1,6 +1,6 @@
#pragma once
// mm_virt.h - virtual memory manager (VMM)
// Manages the single shared PML4, kernel pool, and user heap.
// Manages the single shared PML4, kernel pool, and page-granular user VM regions.
#include <stdint.h>
#include <stddef.h>
#include <kernel/mm_phys.h>
@@ -9,6 +9,11 @@
struct PROCESS;
typedef struct PROCESS PROCESS;
typedef enum MM_MAP_MODE {
MmMapFailIfPresent = 0,
MmMapReplaceExisting = 1,
} MM_MAP_MODE;
typedef enum USER_REGION_TYPE {
UserRegionGeneric = 0,
UserRegionHeap,
@@ -59,7 +64,7 @@ void MmActivate(void);
// ---------------------------------------------------------------------------
// Page mapping
// ---------------------------------------------------------------------------
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags);
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode);
__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt);
// Modify protection flags on an already-mapped virtual range.
@@ -120,6 +125,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t pageFlags);
KSTATUS MmDestroyUserRegion(PROCESS* process, void* base);
void MmDestroyAllUserRegions(PROCESS* process);
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut, uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut);
size_t MmGetUserRegionSize(PROCESS* process, const void* base);
size_t MmGetUserRegionSizeByBase(const void* base);
+93 -91
View File
@@ -6,95 +6,97 @@
// R10, R11 = args 4-5 (loaded by SYSCALL_STUB6)
// RAX = return value
#define SYS_EXIT_PROCESS 0
#define SYS_EXIT_THREAD 1
#define SYS_CREATE_PROCESS 2
#define SYS_WAIT_FOR_PROCESS 3
#define SYS_GET_PROCESS_EXIT_CODE 4
#define SYS_KILL_PROCESS 5
#define SYS_GET_PROCESS_LIST 6
#define SYS_GET_PROCESS_PID 7
#define SYS_CREATE_THREAD 8
#define SYS_WAIT_THREAD 9
#define SYS_GET_CURRENT_TID 10
#define SYS_GET_CURRENT_PID 11
#define SYS_SET_THREAD_PRIORITY 12
#define SYS_YIELD 13
#define SYS_SLEEP 14
#define SYS_SET_USER_APC_DISPATCHER 15
#define SYS_APC_RETURN 16
#define SYS_ALLOC 17
#define SYS_FREE 18
#define SYS_REALLOC 19
#define SYS_CLOSE_HANDLE 20
#define SYS_MUTEX_CREATE 21
#define SYS_MUTEX_ACQUIRE 22
#define SYS_MUTEX_TRY_ACQUIRE 23
#define SYS_MUTEX_RELEASE 24
#define SYS_SEM_CREATE 25
#define SYS_SEM_WAIT 26
#define SYS_SEM_TRY_WAIT 27
#define SYS_SEM_SIGNAL 28
#define SYS_EVENT_CREATE 29
#define SYS_EVENT_SIGNAL 30
#define SYS_EVENT_CLEAR 31
#define SYS_EVENT_WAIT 32
#define SYS_QUEUE_CREATE 33
#define SYS_QUEUE_SEND 34
#define SYS_QUEUE_RECV 35
#define SYS_PUBLISH_QUEUE 36
#define SYS_OPEN_NAMED_QUEUE 37
#define SYS_QUEUE_DUPLICATE 38
#define SYS_NAMED_QUEUE_OWNER_PID 39
#define SYS_OPEN_FILE 40
#define SYS_CREATE_FILE 41
#define SYS_READ_FILE 42
#define SYS_WRITE_FILE 43
#define SYS_READ_FILE_ASYNC 44
#define SYS_WRITE_FILE_ASYNC 45
#define SYS_CANCEL_IO 46
#define SYS_SEEK_FILE 47
#define SYS_GET_FILE_POS 48
#define SYS_GET_FILE_SIZE 49
#define SYS_TRUNCATE_FILE 50
#define SYS_DELETE_FILE 51
#define SYS_RENAME_FILE 52
#define SYS_OPEN_DIR 53
#define SYS_READ_DIR 54
#define SYS_CREATE_DIR 55
#define SYS_REMOVE_DIR 56
#define SYS_SET_CWD 57
#define SYS_GET_CWD 58
#define SYS_WRITE_CONSOLE 59
#define SYS_SCREEN_BLIT 60
#define SYS_SCREEN_CLEAR 61
#define SYS_SCREEN_GET_SIZE 62
#define SYS_SCREEN_PUT_CHAR 63
#define SYS_KB_POLL 64
#define SYS_KB_IS_KEY_DOWN 65
#define SYS_KB_READ_CHAR 66
#define SYS_KB_READ_KEY 67
#define SYS_KB_GET_MODIFIERS 68
#define SYS_MOUSE_POLL 69
#define SYS_MOUSE_READ 70
#define SYS_MOUSE_GET_POS 71
#define SYS_GET_TICK 72
#define SYS_DEBUG_PRINT 73
#define SYS_QUERY_TRAP_FRAME 74
#define SYS_SOCKET 75
#define SYS_BIND 76
#define SYS_LISTEN 77
#define SYS_ACCEPT 78
#define SYS_CONNECT 79
#define SYS_SEND 80
#define SYS_RECV 81
#define SYS_SHUTDOWN 82
#define SYS_SEND_TO 83
#define SYS_RECV_FROM 84
#define SYS_RESOLVE_HOST 85
#define SYS_SET_SOCKET_OPTION 86
#define SYS_GET_SOCKET_OPTION 87
#define SYS_POLL 88
#define SYS_GET_MEMORY_STATUS 89
#define SYS_EXIT_PROCESS 0
#define SYS_EXIT_THREAD 1
#define SYS_CREATE_PROCESS 2
#define SYS_WAIT_FOR_PROCESS 3
#define SYS_GET_PROCESS_EXIT_CODE 4
#define SYS_KILL_PROCESS 5
#define SYS_GET_PROCESS_LIST 6
#define SYS_GET_PROCESS_PID 7
#define SYS_CREATE_THREAD 8
#define SYS_WAIT_THREAD 9
#define SYS_GET_CURRENT_TID 10
#define SYS_GET_CURRENT_PID 11
#define SYS_SET_THREAD_PRIORITY 12
#define SYS_YIELD 13
#define SYS_SLEEP 14
#define SYS_SET_USER_APC_DISPATCHER 15
#define SYS_APC_RETURN 16
#define SYS_VM_ALLOC 17
#define SYS_VM_FREE 18
#define SYS_VM_PROTECT 19
#define SYS_VM_QUERY 20
#define SYS_CLOSE_HANDLE 21
#define SYS_MUTEX_CREATE 22
#define SYS_MUTEX_ACQUIRE 23
#define SYS_MUTEX_TRY_ACQUIRE 24
#define SYS_MUTEX_RELEASE 25
#define SYS_SEM_CREATE 26
#define SYS_SEM_WAIT 27
#define SYS_SEM_TRY_WAIT 28
#define SYS_SEM_SIGNAL 29
#define SYS_EVENT_CREATE 30
#define SYS_EVENT_SIGNAL 31
#define SYS_EVENT_CLEAR 32
#define SYS_EVENT_WAIT 33
#define SYS_QUEUE_CREATE 34
#define SYS_QUEUE_SEND 35
#define SYS_QUEUE_RECV 36
#define SYS_PUBLISH_QUEUE 37
#define SYS_OPEN_NAMED_QUEUE 38
#define SYS_QUEUE_DUPLICATE 39
#define SYS_NAMED_QUEUE_OWNER_PID 40
#define SYS_OPEN_FILE 41
#define SYS_CREATE_FILE 42
#define SYS_READ_FILE 43
#define SYS_WRITE_FILE 44
#define SYS_READ_FILE_ASYNC 45
#define SYS_WRITE_FILE_ASYNC 46
#define SYS_CANCEL_IO 47
#define SYS_SEEK_FILE 48
#define SYS_GET_FILE_POS 49
#define SYS_GET_FILE_SIZE 50
#define SYS_TRUNCATE_FILE 51
#define SYS_DELETE_FILE 52
#define SYS_RENAME_FILE 53
#define SYS_OPEN_DIR 54
#define SYS_READ_DIR 55
#define SYS_CREATE_DIR 56
#define SYS_REMOVE_DIR 57
#define SYS_SET_CWD 58
#define SYS_GET_CWD 59
#define SYS_WRITE_CONSOLE 60
#define SYS_SCREEN_BLIT 61
#define SYS_SCREEN_CLEAR 62
#define SYS_SCREEN_GET_SIZE 63
#define SYS_SCREEN_PUT_CHAR 64
#define SYS_KB_POLL 65
#define SYS_KB_IS_KEY_DOWN 66
#define SYS_KB_READ_CHAR 67
#define SYS_KB_READ_KEY 68
#define SYS_KB_GET_MODIFIERS 69
#define SYS_MOUSE_POLL 70
#define SYS_MOUSE_READ 71
#define SYS_MOUSE_GET_POS 72
#define SYS_GET_TICK 73
#define SYS_DEBUG_PRINT 74
#define SYS_QUERY_TRAP_FRAME 75
#define SYS_SOCKET 76
#define SYS_BIND 77
#define SYS_LISTEN 78
#define SYS_ACCEPT 79
#define SYS_CONNECT 80
#define SYS_SEND 81
#define SYS_RECV 82
#define SYS_SHUTDOWN 83
#define SYS_SEND_TO 84
#define SYS_RECV_FROM 85
#define SYS_RESOLVE_HOST 86
#define SYS_SET_SOCKET_OPTION 87
#define SYS_GET_SOCKET_OPTION 88
#define SYS_POLL 89
#define SYS_GET_MEMORY_STATUS 90
#define SYS_QUERY_KERNEL_STATS 91
#define SYS_MAX 90
#define SYS_MAX 92
+5 -6
View File
@@ -57,7 +57,7 @@ static void KiDebugConsoleWrite(const char* text, size_t len) {
if (!PrintChar || !text)
return;
for (size_t i = 0; i < len; i++)
PrintChar(text[i], 0x00FF00, 0x000000);
PrintChar(text[i], 0xCCCCCC, 0x012456);
}
static volatile long gPanicInProgress = 0;
@@ -88,7 +88,7 @@ __declspec(dllexport) int KeHandleNmiIpi(void) {
}
void KiKernelPutChar(char c) {
PrintChar(c, 0x00FF00, 0x000000);
PrintChar(c, 0xCCCCCC, 0x012456);
}
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), uint32_t flags) {
@@ -231,13 +231,12 @@ __declspec(dllexport) _Noreturn void KePanic(int code, const char* fmt, ...) {
for (;;) __halt();
}
// KePrintConsole - write user-visible console text in white-on-black.
// Used by SYS_WRITE_CONSOLE so user programs get a distinct color from
// kernel debug output (green) and panic output (red).
// KePrintConsole - write user-visible console text using the default console palette.
// Panic output keeps a distinct color so fatal paths remain visually obvious.
__declspec(dllexport) void KePrintConsole(const char* buf, size_t len) {
if (!buf || !PrintChar) return;
for (size_t i = 0; i < len; i++)
PrintChar(buf[i], 0xFFFFFF, 0x000000);
PrintChar(buf[i], 0xCCCCCC, 0x012456);
}
// ---------------------------------------------------------------------------
+8
View File
@@ -5,6 +5,8 @@
#include <kernel/ke_idt.h>
#include <kernel/ke_irql.h>
#include <kernel/ke_dpc.h>
#include <kernel/ke_thread.h>
#include <kernel/ke_process.h>
#include <ntlite/ddi/hal_api.h>
#include <kernel/ke_debug.h>
@@ -115,6 +117,12 @@ void KiExitInterrupt(void) {
// code, leave the request pending instead of switching out of a spinlock or
// high-IRQL region.
if (cpu->InterruptDepth == 0 && KeGetCurrentIrql() == PASSIVE_LEVEL) {
THREAD* current = cpu->CurrentThread;
if (current && !current->IsIdleThread && current->Owner && KeIsProcessTerminating(current->Owner)) {
KeExitThread(current, current->Owner->ExitCode);
while (true) ;
}
KiDrainDpcQueue();
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
KiScheduleFromInterrupt();
+18 -6
View File
@@ -8,6 +8,8 @@
#include <kernel/ke_userenv.h>
#include <kernel/mm_virt.h>
#include <kernel/ob_object.h>
#include <kernel/ke_cpu.h>
#include <kernel/hal/hal_apic.h>
// ---------------------------------------------------------------------------
// Global process list
@@ -382,16 +384,26 @@ KSTATUS KeTerminateProcess(PROCESS* process, int exitCode) {
process->ExitCode = exitCode;
_InterlockedExchange(&process->Terminating, 1);
// Wake alertable waiters so they can notice Terminating at the syscall/
// wait boundary. This is intentionally conservative: fully asynchronous
// forced thread teardown needs object-specific wait-list locking and is a
// larger process-lifecycle project.
uintptr_t flags = KeAcquireSpinlock(&process->HandleLock);
LIST_ENTRY* head = &process->ThreadList;
THREAD* self = KeGetCurrentThread();
KCPU* selfCpu = KeGetCurrentCpu();
uint32_t selfIndex = selfCpu ? selfCpu->CpuIndex : KE_INVALID_CPU;
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
THREAD* t = CONTAINING_RECORD(node, THREAD, ProcessLink);
if (t != KeGetCurrentThread())
(void)KeAlertThread(t);
if (t == self)
continue;
(void)KeAlertThread(t);
if (t->RunningCpu != KE_INVALID_CPU && t->RunningCpu != selfIndex && t->RunningCpu < gCpuCount) {
KCPU* cpu = &gCpus[t->RunningCpu];
if (cpu->Present && cpu->Started && cpu->Online) {
_InterlockedExchange(&cpu->ReschedulePending, 1);
HalApicSendRescheduleIpi(cpu->LapicId);
}
}
}
KeReleaseSpinlock(&process->HandleLock, flags);
+10
View File
@@ -29,6 +29,10 @@ static uint64_t KiDefaultThreadAffinityMask(void) {
return 1ULL;
}
static int KiThreadIsKilledLocked(const THREAD* thread) {
return thread && !thread->IsIdleThread && thread->Owner && KeIsProcessTerminating(thread->Owner);
}
static int KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) {
if (!thread || !cpu) return 0;
if (thread->IsIdleThread) return thread == cpu->IdleThread;
@@ -494,6 +498,10 @@ static void KiSchedule(void) {
// still runnable and nobody else is ready, keep executing it. Otherwise a
// lone CPU-bound thread gets alternated with the idle thread on every timer
// tick, effectively turning a periodic preemption check into a 50% throttle.
if (cur != idle && KiThreadIsKilledLocked(cur)) {
cur->State = ThreadDead;
}
if (cur != idle && cur->State == ThreadRunning && !KiAnyRunnableForCpuLocked(cpu)) {
if (cur->QuantumRemaining == 0)
KiRefillQuantumLocked(cur);
@@ -635,6 +643,8 @@ void KeSchedulerTick(void) {
if (cur == idle) {
if (KiAnyRunnableForCpuLocked(cpu))
requestReschedule = 1;
} else if (KiThreadIsKilledLocked(cur)) {
requestReschedule = 1;
} else {
cur->CpuBurstTicks++;
cur->QuantaConsumed = cur->CpuBurstTicks;
+24 -1
View File
@@ -298,13 +298,29 @@ _Noreturn void KiApKernelEntry(KCPU* cpu) {
idle->RunningCpu = cpu->CpuIndex;
idle->Queued = 0;
cpu->Parked = 0;
// Do not arm the AP's periodic LAPIC timer while it is still in
// the raw park loop. Timer IRQs are scheduler-owned events;
// the AP may take them only after it has a current idle thread.
HalTimerConfigureCurrentCpu();
_InterlockedExchange(&cpu->SchedulerActive, 1);
_enable();
KeStartInitialThread(idle);
}
}
_mm_pause();
// The BSP admits parked APs by storing SchedulerCommand and sending a
// wake IPI. Avoid the classic lost wakeup where the command appears
// between the poll and HLT: check once with interrupts disabled, then
// STI;HLT as a single sleep transition.
_disable();
if (_InterlockedCompareExchange(&cpu->SchedulerCommand, 0, 0) != 0) {
_enable();
continue;
}
_enable();
__halt();
}
}
@@ -766,6 +782,13 @@ KSTATUS KeAdmitApplicationProcessorsToScheduler(void) {
_ReadWriteBarrier();
_InterlockedExchange(&cpu->SchedulerCommand, 1);
// Parked APs sleep with HLT and have no LAPIC timer armed yet. The
// command store alone is not sufficient; send a fixed-vector IPI only
// to wake the parked loop. ReschedulePending is intentionally left
// clear, so the interrupt exit path will not try to schedule before
// the AP has installed its idle thread.
HalApicSendRescheduleIpi(cpu->LapicId);
int active = 0;
for (uint32_t spin = 0; spin < AP_SCHED_TIMEOUT_SPINS; spin++) {
if (_InterlockedCompareExchange(&cpu->SchedulerActive, 0, 0) != 0) {
+335 -111
View File
@@ -34,6 +34,7 @@
#include <stdbool.h>
#include <string.h>
#include <kernel/ke_thread.h>
#include <kernel/ke_cpu.h>
#include <kernel/ke_sched.h>
#include <kernel/ke_process.h>
#include <kernel/ke_mutex.h>
@@ -354,33 +355,147 @@ static uint64_t SyscallSetThreadPriority(uint64_t a0, uint64_t a1, uint64_t a2,
}
// ---------------------------------------------------------------------------
// SYS_ALLOC (8) a0 = size -> void*
// SYS_VM_* page-granular user virtual memory
// ---------------------------------------------------------------------------
static uint64_t SyscallAlloc(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!a0) return 0;
return (uint64_t)(uintptr_t)MmAllocateUserMemory((size_t)a0);
static KSTATUS KiVmProtectToPageFlags(uint32_t protect, uint64_t* flagsOut) {
if (!flagsOut) return STATUS_INVALID_PARAMETER;
switch (protect) {
case SYS_VM_NOACCESS:
*flagsOut = 0;
return STATUS_SUCCESS;
case SYS_VM_READ:
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_NX;
return STATUS_SUCCESS;
case SYS_VM_READWRITE:
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_WRITE | PAGE_NX;
return STATUS_SUCCESS;
case SYS_VM_EXECUTE:
case SYS_VM_EXECUTE_READ:
*flagsOut = PAGE_PRESENT | PAGE_USER;
return STATUS_SUCCESS;
case SYS_VM_EXECUTE_READWRITE:
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_WRITE;
return STATUS_SUCCESS;
default:
return STATUS_INVALID_PARAMETER;
}
}
// ---------------------------------------------------------------------------
// SYS_FREE a0 = ptr
// ---------------------------------------------------------------------------
static uint64_t SyscallFree(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (a0) MmFreeUserMemory((void*)(uintptr_t)a0);
static uint32_t KiPageFlagsToVmProtect(uint64_t flags) {
if (!(flags & PAGE_PRESENT)) return SYS_VM_NOACCESS;
bool writable = (flags & PAGE_WRITE) != 0;
bool executable = (flags & PAGE_NX) == 0;
if (executable && writable) return SYS_VM_EXECUTE_READWRITE;
if (executable) return SYS_VM_EXECUTE_READ;
if (writable) return SYS_VM_READWRITE;
return SYS_VM_READ;
}
static uint64_t SyscallVmAlloc(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a5;
void* preferredBase = (void*)(uintptr_t)a0;
size_t pageCount = (size_t)a1;
uint32_t protect = (uint32_t)a2;
uint32_t flags = (uint32_t)a3;
void** baseOut = (void**)(uintptr_t)a4;
if (!pageCount || !baseOut) return STATUS_INVALID_PARAMETER;
if (pageCount > ((size_t)-1) / PAGE_SIZE) return STATUS_NO_MEMORY;
if (preferredBase || (flags & SYS_VM_FLAG_FIXED)) return STATUS_NOT_SUPPORTED;
uint64_t pageFlags = 0;
KSTATUS s = KiVmProtectToPageFlags(protect, &pageFlags);
if (!KSUCCESS(s)) return s;
PROCESS* process = KeGetCurrentProcess();
if (!process) return STATUS_FAILURE;
void* base = (void*)0;
s = MmCreateUserRegion(process, pageCount * PAGE_SIZE, PAGE_SIZE,
pageFlags ? pageFlags : (PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX),
USER_REGION_ZERO,
UserRegionGeneric,
&base);
if (!KSUCCESS(s)) return s;
if (protect == SYS_VM_NOACCESS) {
s = MmProtectUserRegion(process, base, pageCount * PAGE_SIZE, 0);
if (!KSUCCESS(s)) {
MmDestroyUserRegion(process, base);
return s;
}
}
s = CopyToUser(baseOut, &base, sizeof(base));
if (!KSUCCESS(s)) {
MmDestroyUserRegion(process, base);
return s;
}
return STATUS_SUCCESS;
}
// ---------------------------------------------------------------------------
// SYS_REALLOC (10) a0 = ptr, a1 = newSize -> void*
// ---------------------------------------------------------------------------
static uint64_t SyscallRealloc(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
static uint64_t SyscallVmFree(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
PROCESS* process = KeGetCurrentProcess();
if (!process || !a0) return STATUS_INVALID_PARAMETER;
return MmDestroyUserRegion(process, (void*)(uintptr_t)a0);
}
static uint64_t SyscallVmProtect(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a4; (void)a5;
if (!a0 || !a1) return STATUS_INVALID_PARAMETER;
if ((size_t)a1 > ((size_t)-1) / PAGE_SIZE) return STATUS_NO_MEMORY;
uint64_t pageFlags = 0;
KSTATUS s = KiVmProtectToPageFlags((uint32_t)a2, &pageFlags);
if (!KSUCCESS(s)) return s;
PROCESS* process = KeGetCurrentProcess();
if (!process) return STATUS_FAILURE;
if (a3) {
void* regionBase = (void*)0;
size_t regionSize = 0;
uint64_t oldFlags = 0;
USER_REGION_TYPE type = UserRegionGeneric;
uint32_t regionFlags = 0;
s = MmQueryUserRegion(process, (void*)(uintptr_t)a0, &regionBase, &regionSize, &oldFlags, &type, &regionFlags);
if (!KSUCCESS(s)) return s;
uint32_t oldProtect = KiPageFlagsToVmProtect(oldFlags);
s = CopyToUser((void*)(uintptr_t)a3, &oldProtect, sizeof(oldProtect));
if (!KSUCCESS(s)) return s;
}
return MmProtectUserRegion(process, (void*)(uintptr_t)a0, (size_t)a1 * PAGE_SIZE, pageFlags);
}
static uint64_t SyscallVmQuery(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a2; (void)a3; (void)a4; (void)a5;
return (uint64_t)(uintptr_t)MmReallocateUserMemory(
(void*)(uintptr_t)a0, (size_t)a1);
if (!a0 || !a1) return STATUS_INVALID_PARAMETER;
PROCESS* process = KeGetCurrentProcess();
if (!process) return STATUS_FAILURE;
void* base = (void*)0;
size_t size = 0;
uint64_t pageFlags = 0;
USER_REGION_TYPE type = UserRegionGeneric;
uint32_t regionFlags = 0;
KSTATUS s = MmQueryUserRegion(process, (void*)(uintptr_t)a0, &base, &size, &pageFlags, &type, &regionFlags);
if (!KSUCCESS(s)) return s;
SYS_VM_REGION_INFO info;
info.Base = base;
info.PageCount = size / PAGE_SIZE;
info.Protect = KiPageFlagsToVmProtect(pageFlags);
info.Flags = regionFlags;
info.Type = (uint32_t)type;
info.OwnerPid = process->ProcessId;
return CopyToUser((void*)(uintptr_t)a1, &info, sizeof(info));
}
// ---------------------------------------------------------------------------
@@ -2565,6 +2680,99 @@ static uint64_t SyscallGetMemoryStatus(uint64_t a0, uint64_t a1, uint64_t a2,
return CopyToUser((void*)(uintptr_t)a0, &status, sizeof(status));
}
// ---------------------------------------------------------------------------
// SYS_QUERY_KERNEL_STATS a0=classId a1=buffer a2=bufferSize a3=*requiredSizeOut
// ---------------------------------------------------------------------------
static KSTATUS KiReturnKernelStats(uint64_t bufferArg, size_t bufferSize,
uint64_t requiredArg,
const void* src, size_t size) {
if (requiredArg) {
KSTATUS s = KiCopySizeToUser(requiredArg, size);
if (!KSUCCESS(s)) return s;
}
if (!bufferArg)
return STATUS_SUCCESS;
if (bufferSize < size)
return STATUS_BUFFER_TOO_SMALL;
return CopyToUser((void*)(uintptr_t)bufferArg, src, size);
}
static uint64_t SyscallQueryKernelStats(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a4; (void)a5;
switch ((uint32_t)a0) {
case SYS_KERNEL_STATS_SCHEDULER: {
KE_SCHED_STATS ks;
SYS_SCHEDULER_STATS us;
KeGetSchedulerStats(&ks);
memset(&us, 0, sizeof(us));
us.Ticks = ks.Ticks;
us.ContextSwitches = ks.ContextSwitches;
us.KeepCurrentDecisions = ks.KeepCurrentDecisions;
us.IdleSelections = ks.IdleSelections;
us.Demotions = ks.Demotions;
us.AgingPromotions = ks.AgingPromotions;
us.QuantumExpirations = ks.QuantumExpirations;
us.PriorityPreemptions = ks.PriorityPreemptions;
us.VoluntaryBlocks = ks.VoluntaryBlocks;
us.CpuBurstDemotions = ks.CpuBurstDemotions;
us.SmtSiblingDeferrals = ks.SmtSiblingDeferrals;
us.SmtPrimaryPokes = ks.SmtPrimaryPokes;
return KiReturnKernelStats(a1, (size_t)a2, a3, &us, sizeof(us));
}
case SYS_KERNEL_STATS_PMM: {
MM_PHYSICAL_STATS km;
SYS_PMM_STATS um;
MmQueryPhysicalStats(&km);
memset(&um, 0, sizeof(um));
um.TotalFrames = km.TotalFrames;
um.FreeFrames = km.FreeFrames;
um.UsedFrames = km.UsedFrames;
um.LargestFreeRun = km.LargestFreeRun;
um.FreeRunCount = km.FreeRunCount;
for (size_t i = 0; i < 8; i++)
um.FreeRunHistogram[i] = km.FreeRunHistogram[i];
return KiReturnKernelStats(a1, (size_t)a2, a3, &um, sizeof(um));
}
case SYS_KERNEL_STATS_CPU: {
SYS_CPU_STATS stats;
memset(&stats, 0, sizeof(stats));
stats.CpuCount = gCpuCount;
uint32_t n = gCpuCount;
if (n > SYS_KERNEL_STATS_MAX_CPUS)
n = SYS_KERNEL_STATS_MAX_CPUS;
for (uint32_t i = 0; i < n; i++) {
KCPU* cpu = &gCpus[i];
SYS_CPU_STAT* out = &stats.Cpu[i];
out->CpuIndex = cpu->CpuIndex;
out->LapicId = cpu->LapicId;
if (cpu->Present) out->Flags |= SYS_CPU_FLAG_PRESENT;
if (cpu->Started) out->Flags |= SYS_CPU_FLAG_STARTED;
if (cpu->Parked) out->Flags |= SYS_CPU_FLAG_PARKED;
if (cpu->Online) out->Flags |= SYS_CPU_FLAG_ONLINE;
if (cpu->IsBsp) out->Flags |= SYS_CPU_FLAG_BSP;
if (cpu->IsPrimaryThread) out->Flags |= SYS_CPU_FLAG_PRIMARY;
out->CurrentTid = cpu->CurrentThread ? cpu->CurrentThread->ThreadId : 0;
out->SchedulerTicks = cpu->SchedulerTicks;
out->ContextSwitches = cpu->ContextSwitches;
}
return KiReturnKernelStats(a1, (size_t)a2, a3, &stats, sizeof(stats));
}
default:
return STATUS_INVALID_PARAMETER;
}
}
// ===========================================================================
// Dispatch table - index must match SYS_* in syscall_nr.h exactly.
// ===========================================================================
@@ -2572,96 +2780,98 @@ typedef uint64_t (*SYSCALL_HANDLER)(uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t);
static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
/* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess,
/* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
/* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
/* 05 SYS_KILL_PROCESS */ SyscallKillProcess,
/* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
/* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
/* 08 SYS_CREATE_THREAD */ SyscallCreateThread,
/* 09 SYS_WAIT_THREAD */ SyscallWaitThread,
/* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
/* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
/* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
/* 13 SYS_YIELD */ SyscallYield,
/* 14 SYS_SLEEP */ SyscallSleep,
/* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher,
/* 16 SYS_APC_RETURN */ SyscallApcReturn,
/* 17 SYS_ALLOC */ SyscallAlloc,
/* 18 SYS_FREE */ SyscallFree,
/* 19 SYS_REALLOC */ SyscallRealloc,
/* 20 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
/* 21 SYS_MUTEX_CREATE */ SyscallMutexCreate,
/* 22 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
/* 23 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
/* 24 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
/* 25 SYS_SEM_CREATE */ SyscallSemCreate,
/* 26 SYS_SEM_WAIT */ SyscallSemWait,
/* 27 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
/* 28 SYS_SEM_SIGNAL */ SyscallSemSignal,
/* 29 SYS_EVENT_CREATE */ SyscallEventCreate,
/* 30 SYS_EVENT_SIGNAL */ SyscallEventSignal,
/* 31 SYS_EVENT_CLEAR */ SyscallEventClear,
/* 32 SYS_EVENT_WAIT */ SyscallEventWait,
/* 33 SYS_QUEUE_CREATE */ SyscallQueueCreate,
/* 34 SYS_QUEUE_SEND */ SyscallQueueSend,
/* 35 SYS_QUEUE_RECV */ SyscallQueueRecv,
/* 36 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
/* 37 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
/* 38 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
/* 39 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
/* 40 SYS_OPEN_FILE */ SyscallOpenFile,
/* 41 SYS_CREATE_FILE */ SyscallCreateFile,
/* 42 SYS_READ_FILE */ SyscallReadFile,
/* 43 SYS_WRITE_FILE */ SyscallWriteFile,
/* 44 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync,
/* 45 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync,
/* 46 SYS_CANCEL_IO */ SyscallCancelIo,
/* 47 SYS_SEEK_FILE */ SyscallSeekFile,
/* 48 SYS_GET_FILE_POS */ SyscallGetFilePos,
/* 49 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
/* 50 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
/* 51 SYS_DELETE_FILE */ SyscallDeleteFile,
/* 52 SYS_RENAME_FILE */ SyscallRenameFile,
/* 53 SYS_OPEN_DIR */ SyscallOpenDir,
/* 54 SYS_READ_DIR */ SyscallReadDir,
/* 55 SYS_CREATE_DIR */ SyscallCreateDir,
/* 56 SYS_REMOVE_DIR */ SyscallRemoveDir,
/* 57 SYS_SET_CWD */ SyscallSetCwd,
/* 58 SYS_GET_CWD */ SyscallGetCwd,
/* 59 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
/* 60 SYS_SCREEN_BLIT */ SyscallScreenBlit,
/* 61 SYS_SCREEN_CLEAR */ SyscallScreenClear,
/* 62 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
/* 63 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
/* 64 SYS_KB_POLL */ SyscallKbPoll,
/* 65 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
/* 66 SYS_KB_READ_CHAR */ SyscallKbReadChar,
/* 67 SYS_KB_READ_KEY */ SyscallKbReadKey,
/* 68 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
/* 69 SYS_MOUSE_POLL */ SyscallMousePoll,
/* 70 SYS_MOUSE_READ */ SyscallMouseRead,
/* 71 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
/* 72 SYS_GET_TICK */ SyscallGetTick,
/* 73 SYS_DEBUG_PRINT */ SyscallDebugPrint,
/* 74 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame,
/* 75 SYS_SOCKET */ SyscallSocket,
/* 76 SYS_BIND */ SyscallBind,
/* 77 SYS_LISTEN */ SyscallListen,
/* 78 SYS_ACCEPT */ SyscallAccept,
/* 79 SYS_CONNECT */ SyscallConnect,
/* 80 SYS_SEND */ SyscallSend,
/* 81 SYS_RECV */ SyscallRecv,
/* 82 SYS_SHUTDOWN */ SyscallShutdown,
/* 83 SYS_SEND_TO */ SyscallSendTo,
/* 84 SYS_RECV_FROM */ SyscallRecvFrom,
/* 85 SYS_RESOLVE_HOST */ SyscallResolveHost,
/* 86 SYS_SET_SOCKET_OPTION */ SyscallSetSocketOption,
/* 87 SYS_GET_SOCKET_OPTION */ SyscallGetSocketOption,
/* 88 SYS_POLL */ SyscallPoll,
/* 89 SYS_GET_MEMORY_STATUS */ SyscallGetMemoryStatus
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
/* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess,
/* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
/* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
/* 05 SYS_KILL_PROCESS */ SyscallKillProcess,
/* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
/* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
/* 08 SYS_CREATE_THREAD */ SyscallCreateThread,
/* 09 SYS_WAIT_THREAD */ SyscallWaitThread,
/* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
/* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
/* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
/* 13 SYS_YIELD */ SyscallYield,
/* 14 SYS_SLEEP */ SyscallSleep,
/* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher,
/* 16 SYS_APC_RETURN */ SyscallApcReturn,
/* 17 SYS_VM_ALLOC */ SyscallVmAlloc,
/* 18 SYS_VM_FREE */ SyscallVmFree,
/* 19 SYS_VM_PROTECT */ SyscallVmProtect,
/* 20 SYS_VM_QUERY */ SyscallVmQuery,
/* 21 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
/* 22 SYS_MUTEX_CREATE */ SyscallMutexCreate,
/* 23 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
/* 24 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
/* 25 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
/* 26 SYS_SEM_CREATE */ SyscallSemCreate,
/* 27 SYS_SEM_WAIT */ SyscallSemWait,
/* 28 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
/* 29 SYS_SEM_SIGNAL */ SyscallSemSignal,
/* 30 SYS_EVENT_CREATE */ SyscallEventCreate,
/* 31 SYS_EVENT_SIGNAL */ SyscallEventSignal,
/* 32 SYS_EVENT_CLEAR */ SyscallEventClear,
/* 33 SYS_EVENT_WAIT */ SyscallEventWait,
/* 34 SYS_QUEUE_CREATE */ SyscallQueueCreate,
/* 35 SYS_QUEUE_SEND */ SyscallQueueSend,
/* 36 SYS_QUEUE_RECV */ SyscallQueueRecv,
/* 37 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
/* 38 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
/* 39 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
/* 40 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
/* 41 SYS_OPEN_FILE */ SyscallOpenFile,
/* 42 SYS_CREATE_FILE */ SyscallCreateFile,
/* 43 SYS_READ_FILE */ SyscallReadFile,
/* 44 SYS_WRITE_FILE */ SyscallWriteFile,
/* 45 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync,
/* 46 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync,
/* 47 SYS_CANCEL_IO */ SyscallCancelIo,
/* 48 SYS_SEEK_FILE */ SyscallSeekFile,
/* 49 SYS_GET_FILE_POS */ SyscallGetFilePos,
/* 50 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
/* 51 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
/* 52 SYS_DELETE_FILE */ SyscallDeleteFile,
/* 53 SYS_RENAME_FILE */ SyscallRenameFile,
/* 54 SYS_OPEN_DIR */ SyscallOpenDir,
/* 55 SYS_READ_DIR */ SyscallReadDir,
/* 56 SYS_CREATE_DIR */ SyscallCreateDir,
/* 57 SYS_REMOVE_DIR */ SyscallRemoveDir,
/* 58 SYS_SET_CWD */ SyscallSetCwd,
/* 59 SYS_GET_CWD */ SyscallGetCwd,
/* 60 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
/* 61 SYS_SCREEN_BLIT */ SyscallScreenBlit,
/* 62 SYS_SCREEN_CLEAR */ SyscallScreenClear,
/* 63 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
/* 64 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
/* 65 SYS_KB_POLL */ SyscallKbPoll,
/* 66 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
/* 67 SYS_KB_READ_CHAR */ SyscallKbReadChar,
/* 68 SYS_KB_READ_KEY */ SyscallKbReadKey,
/* 69 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
/* 70 SYS_MOUSE_POLL */ SyscallMousePoll,
/* 71 SYS_MOUSE_READ */ SyscallMouseRead,
/* 72 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
/* 73 SYS_GET_TICK */ SyscallGetTick,
/* 74 SYS_DEBUG_PRINT */ SyscallDebugPrint,
/* 75 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame,
/* 76 SYS_SOCKET */ SyscallSocket,
/* 77 SYS_BIND */ SyscallBind,
/* 78 SYS_LISTEN */ SyscallListen,
/* 79 SYS_ACCEPT */ SyscallAccept,
/* 80 SYS_CONNECT */ SyscallConnect,
/* 81 SYS_SEND */ SyscallSend,
/* 82 SYS_RECV */ SyscallRecv,
/* 83 SYS_SHUTDOWN */ SyscallShutdown,
/* 84 SYS_SEND_TO */ SyscallSendTo,
/* 85 SYS_RECV_FROM */ SyscallRecvFrom,
/* 86 SYS_RESOLVE_HOST */ SyscallResolveHost,
/* 87 SYS_SET_SOCKET_OPTION */ SyscallSetSocketOption,
/* 88 SYS_GET_SOCKET_OPTION */ SyscallGetSocketOption,
/* 89 SYS_POLL */ SyscallPoll,
/* 90 SYS_GET_MEMORY_STATUS */ SyscallGetMemoryStatus,
/* 91 SYS_QUERY_KERNEL_STATS */ SyscallQueryKernelStats
};
// ---------------------------------------------------------------------------
@@ -2681,5 +2891,19 @@ uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1,
}
if (nr >= SYS_MAX || !gSyscallTable[nr]) return STATUS_NOT_SUPPORTED;
return gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
uint64_t result = gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
// A process may be terminated while one of its threads is already inside a
// syscall. Do not allow that thread to return to userspace after the owner
// has been marked terminating.
owner = self ? self->Owner : (PROCESS*)0;
if (owner && KeIsProcessTerminating(owner) &&
nr != SYS_EXIT_PROCESS && nr != SYS_EXIT_THREAD) {
int exitCode = owner->ExitCode;
KeExitThread(self, exitCode);
while (true) ;
}
return result;
}
+1 -1
View File
@@ -409,7 +409,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
.FramebufferHeight = bootInfo->FramebufferHeight,
.FramebufferStride = bootInfo->FramebufferStride,
.RsdpPhysical = bootInfo->RsdpPhysical,
.Debug = bootInfo->Debug,
.Debug = bootInfo->Debug & 1, // bitmask 1 debug prints
.AllocatePool = MmAllocatePool
};
+1 -3
View File
@@ -325,6 +325,7 @@ static void KiFreeLoadedImage(uintptr_t imageBase, bool user) {
KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) {
if (!imageBase) return STATUS_INVALID_PARAMETER;
if (user && !process) return STATUS_INVALID_PARAMETER;
size_t mappedSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase);
if (!mappedSize) return STATUS_FAILURE;
@@ -387,9 +388,6 @@ KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool us
return STATUS_SUCCESS;
}
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user) {
return LdrProtectImageForProcess(user ? (PROCESS*)0 : (PROCESS*)0, imageBase, user);
}
// ---------------------------------------------------------------------------
// Entry point lookup
+247 -137
View File
@@ -1,13 +1,12 @@
// mm_phys.c - physical memory manager
//
// The free-frame stack is a flat array of PHYSICAL_ADDRESS values carved out of
// the first suitable usable region before any allocation is served. All access
// to physical memory goes through the direct physical window established by the
// bootloader at PhysicalWindowBase (always 0xFFFF880000000000).
//
// Lock: a single spinlock guards Push/Pop. O(1) for both operations.
// Bitmap allocator over 4 KB physical frames. One bitmap records which PFNs
// exist in usable RAM, and one bitmap records which usable PFNs are currently
// free. This keeps single-frame allocation simple while making contiguous
// allocation and memory visualization deterministic.
#include <kernel/mm_phys.h>
#include <kernel/ke_spinlock.h>
#include <string.h>
// ---------------------------------------------------------------------------
// Physical-to-virtual translation via the direct map window.
@@ -19,122 +18,198 @@ static inline void* KiPhysToVirt(PHYSICAL_ADDRESS phys) {
}
// ---------------------------------------------------------------------------
// Frame stack
// Frame bitmap
// ---------------------------------------------------------------------------
typedef struct {
PHYSICAL_ADDRESS* Stack; // pointer into physical window
size_t Top; // index of next free slot (stack grows up)
size_t Capacity;
size_t Total; // total frames ever pushed
SPINLOCK Lock;
} FRAME_STACK;
uint8_t* Usable; // bit = 1 when PFN belongs to usable RAM
uint8_t* Free; // bit = 1 when PFN is currently free
size_t BitmapBytes;
size_t MaxPfn;
size_t TotalFrames; // usable frames available to the allocator
size_t FreeFrames;
SPINLOCK Lock;
} FRAME_BITMAP;
static FRAME_STACK gFrameStack;
static FRAME_BITMAP gFrameBitmap;
// Push a physical frame address onto the stack.
static void KiPushFrame(PHYSICAL_ADDRESS frame) {
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
if (gFrameStack.Top < gFrameStack.Capacity) {
gFrameStack.Stack[gFrameStack.Top++] = frame;
gFrameStack.Total++;
static inline PHYSICAL_ADDRESS KiAlignUp(PHYSICAL_ADDRESS value) {
return (value + PAGE_SIZE - 1) & PAGE_MASK;
}
static inline PHYSICAL_ADDRESS KiAlignDown(PHYSICAL_ADDRESS value) {
return value & PAGE_MASK;
}
static inline int KiBitTest(const uint8_t* bits, size_t index) {
return (bits[index >> 3] & (uint8_t)(1u << (index & 7))) != 0;
}
static inline void KiBitSet(uint8_t* bits, size_t index) {
bits[index >> 3] |= (uint8_t)(1u << (index & 7));
}
static inline void KiBitClear(uint8_t* bits, size_t index) {
bits[index >> 3] &= (uint8_t)~(1u << (index & 7));
}
static inline int KiPfnUsableLocked(size_t pfn) {
return pfn < gFrameBitmap.MaxPfn && KiBitTest(gFrameBitmap.Usable, pfn);
}
static inline int KiPfnFreeLocked(size_t pfn) {
return KiPfnUsableLocked(pfn) && KiBitTest(gFrameBitmap.Free, pfn);
}
static void KiMarkUsableFreeRange(size_t firstPfn, size_t count) {
for (size_t i = 0; i < count; i++) {
size_t pfn = firstPfn + i;
if (pfn >= gFrameBitmap.MaxPfn) break;
if (!KiBitTest(gFrameBitmap.Usable, pfn)) {
KiBitSet(gFrameBitmap.Usable, pfn);
gFrameBitmap.TotalFrames++;
}
if (!KiBitTest(gFrameBitmap.Free, pfn)) {
KiBitSet(gFrameBitmap.Free, pfn);
gFrameBitmap.FreeFrames++;
}
}
}
static void KiRemoveUsablePfn(size_t pfn) {
if (pfn >= gFrameBitmap.MaxPfn) return;
if (KiBitTest(gFrameBitmap.Free, pfn)) {
KiBitClear(gFrameBitmap.Free, pfn);
if (gFrameBitmap.FreeFrames) gFrameBitmap.FreeFrames--;
}
if (KiBitTest(gFrameBitmap.Usable, pfn)) {
KiBitClear(gFrameBitmap.Usable, pfn);
if (gFrameBitmap.TotalFrames) gFrameBitmap.TotalFrames--;
}
KeReleaseSpinlock(&gFrameStack.Lock, flags);
}
// ---------------------------------------------------------------------------
// Initialisation
// ---------------------------------------------------------------------------
bool MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) {
if (!map) return false;
gPhysBase = physicalWindowBase;
// --- Phase 0: Count total usable frames so we can size the stack
// dynamically instead of capping at a hardcoded 1 GB. ---
uint64_t totalUsableBytes = 0;
for (uint32_t i = 0; i < map->RegionCount; i++) {
if (map->Regions[i].Type == MemoryUsable)
totalUsableBytes += map->Regions[i].Length;
}
const size_t maxFrames = (size_t)(totalUsableBytes / PAGE_SIZE);
const size_t stackBytes = maxFrames * sizeof(PHYSICAL_ADDRESS);
// --- Phase 1: Find a usable region large enough to hold the stack. ---
PHYSICAL_ADDRESS stackPhys = 0;
for (uint32_t i = 0; i < map->RegionCount; i++) {
const MEMORY_REGION* r = &map->Regions[i];
if (r->Type == MemoryUsable && r->Length >= stackBytes + PAGE_SIZE) {
stackPhys = r->Base;
break;
}
}
if (!stackPhys) {
return false;
}
gFrameStack.Stack = (PHYSICAL_ADDRESS *)KiPhysToVirt(stackPhys);
gFrameStack.Top = 0;
gFrameStack.Capacity = maxFrames;
gFrameStack.Total = 0;
gFrameStack.Lock = (SPINLOCK)SPINLOCK_INIT;
// --- Phase 2: Push all free 4 KB frames, skipping the stack pages. ---
const PHYSICAL_ADDRESS stackEnd =
stackPhys + ((stackBytes + PAGE_SIZE - 1) & PAGE_MASK);
PHYSICAL_ADDRESS maxEnd = 0;
for (uint32_t i = 0; i < map->RegionCount; i++) {
const MEMORY_REGION* r = &map->Regions[i];
if (r->Type != MemoryUsable) continue;
PHYSICAL_ADDRESS base = r->Base;
PHYSICAL_ADDRESS end = r->Base + r->Length;
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
PHYSICAL_ADDRESS end = r->Base + r->Length;
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
end = KiAlignDown(end);
if (end <= base) continue;
if (end > maxEnd) maxEnd = end;
}
for (PHYSICAL_ADDRESS frame = base; frame < end; frame += PAGE_SIZE) {
if (frame >= stackPhys && frame < stackEnd) continue;
KiPushFrame(frame);
size_t maxPfn = (size_t)(maxEnd / PAGE_SIZE);
if (!maxPfn) return false;
size_t bitmapBytes = (maxPfn + 7) / 8;
size_t metadataBytes = bitmapBytes * 2;
size_t metadataPages = (metadataBytes + PAGE_SIZE - 1) / PAGE_SIZE;
PHYSICAL_ADDRESS metadataSize = (PHYSICAL_ADDRESS)metadataPages * PAGE_SIZE;
// Keep allocator metadata out of low memory. The bitmap is much smaller
// than the old free-frame stack, so a first-fit search can otherwise choose
// a conventional-memory hole below 1 MiB. That range is still useful for
// AP startup/legacy scratch, and stealing it makes early boot failures
// unnecessarily silent because PMM initializes before normal debug output.
const PHYSICAL_ADDRESS metadataMin = 0x100000ULL;
PHYSICAL_ADDRESS metadataPhys = 0;
int metadataFound = 0;
for (uint32_t i = 0; i < map->RegionCount; i++) {
const MEMORY_REGION* r = &map->Regions[i];
if (r->Type != MemoryUsable) continue;
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
if (base < metadataMin) base = metadataMin;
PHYSICAL_ADDRESS end = r->Base + r->Length;
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
end = KiAlignDown(end);
if (end <= base) continue;
if (end - base >= metadataSize) {
metadataPhys = base;
metadataFound = 1;
break;
}
}
if (!metadataFound) return false;
gFrameBitmap.BitmapBytes = bitmapBytes;
gFrameBitmap.MaxPfn = maxPfn;
gFrameBitmap.TotalFrames = 0;
gFrameBitmap.FreeFrames = 0;
gFrameBitmap.Lock = (SPINLOCK)SPINLOCK_INIT;
gFrameBitmap.Usable = (uint8_t*)KiPhysToVirt(metadataPhys);
gFrameBitmap.Free = gFrameBitmap.Usable + bitmapBytes;
memset(gFrameBitmap.Usable, 0, metadataBytes);
// Mark page-aligned usable RAM as free. Unaligned tails are ignored rather
// than handing malformed frame addresses to the rest of the kernel.
for (uint32_t i = 0; i < map->RegionCount; i++) {
const MEMORY_REGION* r = &map->Regions[i];
if (r->Type != MemoryUsable) continue;
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
PHYSICAL_ADDRESS end = r->Base + r->Length;
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
end = KiAlignDown(end);
if (end <= base) continue;
size_t firstPfn = (size_t)(base / PAGE_SIZE);
size_t count = (size_t)((end - base) / PAGE_SIZE);
KiMarkUsableFreeRange(firstPfn, count);
}
// PFN 0 is never a valid allocation result because 0 is the failure value.
KiRemoveUsablePfn(0);
// Hide the PMM metadata pages from the allocator entirely. They are not
// merely allocated; they are structural storage that must not become free if
// some caller accidentally passes their PFNs to MmFreeFrame().
size_t metadataFirstPfn = (size_t)(metadataPhys / PAGE_SIZE);
for (size_t i = 0; i < metadataPages; i++)
KiRemoveUsablePfn(metadataFirstPfn + i);
return true;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
static PHYSICAL_ADDRESS KiPopFrameAtIndexLocked(size_t idx) {
PHYSICAL_ADDRESS frame = gFrameStack.Stack[idx];
size_t tail = gFrameStack.Top - idx - 1;
for (size_t j = 0; j < tail; j++)
gFrameStack.Stack[idx + j] = gFrameStack.Stack[idx + 1 + j];
gFrameStack.Top--;
return frame;
}
PHYSICAL_ADDRESS MmAllocateFrameInRange(PHYSICAL_ADDRESS minInclusive,
PHYSICAL_ADDRESS maxExclusive) {
minInclusive = (minInclusive + PAGE_SIZE - 1) & PAGE_MASK;
maxExclusive &= PAGE_MASK;
minInclusive = KiAlignUp(minInclusive);
maxExclusive = KiAlignDown(maxExclusive);
if (maxExclusive <= minInclusive) return (PHYSICAL_ADDRESS)0;
if (maxExclusive <= minInclusive)
return (PHYSICAL_ADDRESS)0;
size_t firstPfn = (size_t)(minInclusive / PAGE_SIZE);
size_t limitPfn = (size_t)(maxExclusive / PAGE_SIZE);
if (limitPfn > gFrameBitmap.MaxPfn) limitPfn = gFrameBitmap.MaxPfn;
if (firstPfn >= limitPfn) return (PHYSICAL_ADDRESS)0;
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
// Search high-to-low within the requested window. For low-memory users
// such as the AP trampoline this naturally prefers the traditional
// 0x70000-0x9f000 area and avoids consuming lower real-mode space first.
for (size_t i = gFrameStack.Top; i > 0; i--) {
size_t idx = i - 1;
PHYSICAL_ADDRESS frame = gFrameStack.Stack[idx];
if (frame >= minInclusive && frame < maxExclusive &&
!(frame & (PAGE_SIZE - 1))) {
frame = KiPopFrameAtIndexLocked(idx);
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return frame;
for (size_t pfn = limitPfn; pfn > firstPfn; pfn--) {
size_t candidate = pfn - 1;
if (KiPfnFreeLocked(candidate)) {
KiBitClear(gFrameBitmap.Free, candidate);
if (gFrameBitmap.FreeFrames) gFrameBitmap.FreeFrames--;
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
return (PHYSICAL_ADDRESS)candidate * PAGE_SIZE;
}
}
KeReleaseSpinlock(&gFrameStack.Lock, flags);
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
return (PHYSICAL_ADDRESS)0;
}
@@ -143,74 +218,109 @@ PHYSICAL_ADDRESS MmAllocateFrameBelow(PHYSICAL_ADDRESS maxExclusive) {
}
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateFrame(void) {
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
if (gFrameStack.Top == 0) {
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return (PHYSICAL_ADDRESS)0;
}
PHYSICAL_ADDRESS frame = gFrameStack.Stack[--gFrameStack.Top];
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return frame;
return MmAllocateFrameInRange(PAGE_SIZE, (PHYSICAL_ADDRESS)gFrameBitmap.MaxPfn * PAGE_SIZE);
}
void MmFreeFrame(PHYSICAL_ADDRESS frame) {
if (!frame || (frame & (PAGE_SIZE - 1))) return;
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
if (gFrameStack.Top < gFrameStack.Capacity)
gFrameStack.Stack[gFrameStack.Top++] = frame;
// else: stack full - leak rather than corrupt
KeReleaseSpinlock(&gFrameStack.Lock, flags);
size_t pfn = (size_t)(frame / PAGE_SIZE);
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
if (KiPfnUsableLocked(pfn) && !KiBitTest(gFrameBitmap.Free, pfn)) {
KiBitSet(gFrameBitmap.Free, pfn);
gFrameBitmap.FreeFrames++;
}
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
}
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) {
if (!count) return (PHYSICAL_ADDRESS)0;
if (!count || count > gFrameBitmap.MaxPfn) return (PHYSICAL_ADDRESS)0;
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
if (gFrameStack.Top < count) {
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return (PHYSICAL_ADDRESS)0;
}
// Frames are pushed in ascending address order by MmInitializePhysical,
// so physically consecutive pages sit at consecutive stack indices.
// Scan from bottom upward for a run of 'count' adjacent frames.
size_t run = (size_t)-1;
for (size_t i = 0; i + count <= gFrameStack.Top; i++) {
int ok = 1;
for (size_t j = 1; j < count; j++) {
if (gFrameStack.Stack[i + j] != gFrameStack.Stack[i] + j * PAGE_SIZE) {
ok = 0;
// Skip past this broken run; the next candidate can't start
// before the frame that broke the sequence.
i += j - 1; // outer loop adds 1 more
break;
size_t runStart = 0;
size_t runLength = 0;
for (size_t pfn = 1; pfn < gFrameBitmap.MaxPfn; pfn++) {
if (KiPfnFreeLocked(pfn)) {
if (!runLength) runStart = pfn;
runLength++;
if (runLength == count) {
for (size_t i = 0; i < count; i++)
KiBitClear(gFrameBitmap.Free, runStart + i);
if (gFrameBitmap.FreeFrames >= count) gFrameBitmap.FreeFrames -= count;
else gFrameBitmap.FreeFrames = 0;
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
return (PHYSICAL_ADDRESS)runStart * PAGE_SIZE;
}
} else {
runLength = 0;
}
if (ok) { run = i; break; }
}
if (run == (size_t)-1) {
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return (PHYSICAL_ADDRESS)0;
}
PHYSICAL_ADDRESS base = gFrameStack.Stack[run];
// Splice out the 'count' entries by sliding the tail down.
size_t tail = gFrameStack.Top - run - count;
for (size_t i = 0; i < tail; i++)
gFrameStack.Stack[run + i] = gFrameStack.Stack[run + count + i];
gFrameStack.Top -= count;
KeReleaseSpinlock(&gFrameStack.Lock, flags);
return base;
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
return (PHYSICAL_ADDRESS)0;
}
size_t MmFreeFrameCount(void) {
return gFrameStack.Top;
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
size_t count = gFrameBitmap.FreeFrames;
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
return count;
}
size_t MmTotalFrameCount(void) {
return gFrameStack.Total;
return gFrameBitmap.TotalFrames;
}
void MmQueryPhysicalStats(MM_PHYSICAL_STATS* out) {
if (!out) return;
MM_PHYSICAL_STATS stats;
memset(&stats, 0, sizeof(stats));
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
stats.TotalFrames = (uint64_t)gFrameBitmap.TotalFrames;
stats.FreeFrames = (uint64_t)gFrameBitmap.FreeFrames;
stats.UsedFrames = stats.TotalFrames - stats.FreeFrames;
uint64_t run = 0;
for (size_t pfn = 1; pfn < gFrameBitmap.MaxPfn; pfn++) {
if (KiPfnFreeLocked(pfn)) {
run++;
continue;
}
if (run) {
stats.FreeRunCount++;
if (run > stats.LargestFreeRun)
stats.LargestFreeRun = run;
if (run == 1) stats.FreeRunHistogram[0]++;
else if (run <= 3) stats.FreeRunHistogram[1]++;
else if (run <= 7) stats.FreeRunHistogram[2]++;
else if (run <= 15) stats.FreeRunHistogram[3]++;
else if (run <= 63) stats.FreeRunHistogram[4]++;
else if (run <= 255) stats.FreeRunHistogram[5]++;
else if (run <= 1023) stats.FreeRunHistogram[6]++;
else stats.FreeRunHistogram[7]++;
run = 0;
}
}
if (run) {
stats.FreeRunCount++;
if (run > stats.LargestFreeRun)
stats.LargestFreeRun = run;
if (run == 1) stats.FreeRunHistogram[0]++;
else if (run <= 3) stats.FreeRunHistogram[1]++;
else if (run <= 7) stats.FreeRunHistogram[2]++;
else if (run <= 15) stats.FreeRunHistogram[3]++;
else if (run <= 63) stats.FreeRunHistogram[4]++;
else if (run <= 255) stats.FreeRunHistogram[5]++;
else if (run <= 1023) stats.FreeRunHistogram[6]++;
else stats.FreeRunHistogram[7]++;
}
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
*out = stats;
}
+50 -7
View File
@@ -11,7 +11,8 @@
//
// User heap:
// A single best-fit free list in the lower half.
// Backed on demand from the PMM. No per-process heaps.
// Page-granular lower-half regions owned by PROCESS metadata. Sub-page
// allocation is a user-mode runtime concern.
#include <stddef.h>
#include <string.h>
#include <intrin.h>
@@ -164,7 +165,7 @@ int MmHandleTlbShootdownNmi(void) {
// ---------------------------------------------------------------------------
// Public mapping
// ---------------------------------------------------------------------------
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode) {
unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0;
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
@@ -186,6 +187,10 @@ __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, u
}
uint64_t* pte = KiPtePtr(pt, PT_IDX(virt));
if ((*pte & PAGE_PRESENT) && mode == MmMapFailIfPresent) {
KeReleaseSpinlock(&gPageTableLock, lockFlags);
return STATUS_ALREADY_EXISTS;
}
*pte = phys | flags;
KeReleaseSpinlock(&gPageTableLock, lockFlags);
@@ -525,7 +530,7 @@ static int KiHeapEnsureMapped(HEAP* h, uintptr_t start, size_t size) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return 0;
KSTATUS ms = MmMapPage(va, frame, h->MapFlags);
KSTATUS ms = MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return 0;
@@ -544,7 +549,7 @@ static int KiHeapGrow(HEAP* h, size_t need) {
for (uintptr_t va = h->Brk; va < h->Brk + grow; va += PAGE_SIZE) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return 0;
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags))) {
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent))) {
MmFreeFrame(frame);
return 0;
}
@@ -965,7 +970,7 @@ KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment,
s = STATUS_NO_MEMORY;
break;
}
s = MmMapPage(va, frame, pageFlags);
s = MmMapPage(va, frame, pageFlags, MmMapFailIfPresent);
if (!KSUCCESS(s)) {
MmFreeFrame(frame);
break;
@@ -1036,7 +1041,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return STATUS_NO_MEMORY;
KSTATUS ms = MmMapPage(va, frame, flags);
KSTATUS ms = MmMapPage(va, frame, flags, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return ms;
@@ -1073,6 +1078,16 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
return STATUS_NOT_FOUND;
}
if (pageFlags == 0) {
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
if (va < regionBase || va >= regionEnd) return STATUS_ACCESS_DENIED;
PHYSICAL_ADDRESS phys = MmGetPhysicalAddress(va);
if (phys && KSUCCESS(MmUnmapPage(va)))
MmFreeFrame(phys);
}
return STATUS_SUCCESS;
}
uint64_t finalFlags = pageFlags | PAGE_PRESENT | PAGE_USER;
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
@@ -1091,7 +1106,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
if (!KSUCCESS(qs) || !(existingFlags & PAGE_PRESENT)) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return STATUS_NO_MEMORY;
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX);
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return ms;
@@ -1161,6 +1176,34 @@ void MmDestroyAllUserRegions(PROCESS* process) {
}
}
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut,
uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut) {
if (!process || !address) return STATUS_INVALID_PARAMETER;
uintptr_t addr = (uintptr_t)address;
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
for (LIST_ENTRY* node = process->UserRegions.Fwd; node != &process->UserRegions; node = node->Fwd) {
USER_VA_REGION* r = CONTAINING_RECORD(node, USER_VA_REGION, ProcessLink);
uintptr_t end = r->Base + r->CommittedSize;
if (addr >= r->Base && addr < end) {
if (baseOut) *baseOut = (void*)r->Base;
if (sizeOut) *sizeOut = r->CommittedSize;
if (pageFlagsOut) {
PHYSICAL_ADDRESS phys = 0;
uint64_t flags = 0;
KSTATUS qs = MmQueryPage(addr & PAGE_MASK, &phys, &flags);
*pageFlagsOut = KSUCCESS(qs) ? flags : 0;
}
if (typeOut) *typeOut = r->Type;
if (regionFlagsOut) *regionFlagsOut = r->Flags;
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
return STATUS_SUCCESS;
}
}
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
return STATUS_NOT_FOUND;
}
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
if (!process || !base) return 0;
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);