Compare commits

..
Author SHA1 Message Date
t3hn3rd f427b7bcc7 refactor(memory): complete PMM/VMM/LMM rewrite - bitmap allocators, bug fixes, hardening
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
PMM Rewrite:
- Replace ~8KB record array with compact bitmaps
  (PhysPresent/PhysAlloc/PhysScanned, 128B each)
- Add PhysOwner[0..1023] for per-block ownership tracking
- new_block: O(1) amortised via NextFreeHint + dword-level BSF scan,
  returns 0 as OOM sentinel
- free_block: O(1) direct bit clear with double-free detection
- alloc_block: validates PhysPresent and PhysAlloc bits before allocation
- Add pmm_free_blocks/pmm_total_blocks stats functions

VMM Correctness Fixes:
- Fix free_page block extraction (Address SHR 10, was using
  raw Address field)
- Fix invlpg operand (use virtual address, was passing PDE index)
- Clear PDE entry on free_page before returning block to PMM
- Remove map_page double-write (delegate to map_page_ex only)
- Add OOM propagation (new_page returns false if PMM returns 0)
- Fix missing pop_trace in new_page error path

LMM Rewrite:
- Replace per-entry record array with bitmap allocator
  (93% vs 43% page efficiency)
- Layout: Header(24B) + Bitmap(64512B) + Padding + Data at 0x10000
- SIZE_PREFIX=16 for 16-byte aligned returns (SSE MOVAPS requirement)
- Next-fit bitmap scan with roving hint (NextFree) and dword-level
  fast skip
- Large alloc sentinel (LARGE_ALLOC_MAGIC=$FFFFFFFE) so kfree detects
  klalloc'd memory
- Implement klfree (was previously a no-op - pages could never
  be returned)
- Implement try_release_page (return fully-free heap pages to VMM/PMM)
- Fix interrupt safety: stack-balanced pushfd/cli/pop +
  restore_if (sti only)
  Fixes Bad TSS caused by popfd restoring dangerous EFLAGS bits (NT, IOPL)
- Zero memory via rep stosd instead of byte-by-byte loop

Hardening:
- kalloc OOM now triggers BSOD instead of returning nil
  (90% of callers don't check)
- Double-free detection in kfree (verify bitmap bits set before clearing)
- Guard bytes ({$IFDEF DEBUG_LMM}): $DEADBEEF sentinel for buffer overrun detection
- kpalloc: bounds check (block >= 1024 -> GPF) + syslog MMIO mapping audit log

Observability:
- Add MEMINFO command as src/prog/meminfo.pas (moved from inline kernel.pas)
- Displays multiboot memory, PMM block stats, LMM heap stats
- Register via progmanager.pas following standard prog pattern

Files changed:
- src/pmemorymanager.pas
- src/vmemorymanager.pas
- src/lmemorymanager.pas
- src/kernel.pas
- src/progmanager.pas
- src/prog/meminfo.pas
2026-03-04 19:23:46 +00:00
Aaron 4ba3c5b524 Merge pull request 'feature/Queues' (#37) from feature/Queues into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #37
2026-03-04 00:06:10 +00:00
t3hn3rd 7180ad39d8 Merge pull request 'feature: Pipeline - LVGL Build Caching' (#38) from feature/lvgl-build-caching into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #38
Reviewed-by: Aaron Hance <[email protected]>
2026-03-04 00:05:01 +00:00
Aaron 6c7bcc1911 better testing
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2026-03-04 00:00:56 +00:00
Aaron e09c9b5595 refactor 2026-03-04 00:00:56 +00:00
Aaron 9476bb0c8a compile 2026-03-04 00:00:56 +00:00
Aaron 8f7db8507b Queues 2026-03-04 00:00:56 +00:00
t3hn3rd 188b1aebb0 feature: Pipeline - LVGL Build Caching
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Add LVGL build caching: store liblvgl.a on host mount to skip
  full recompilation on subsequent builds
2026-03-03 23:22:09 +00:00
t3hn3rd 452203b7b4 Merge pull request 'bug: vtop incorrect bitmask' (#36) from feature/vtop-fix into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #36
Reviewed-by: Aaron Hance <[email protected]>
2026-03-03 20:03:47 +00:00
27 changed files with 3526 additions and 2385 deletions
+22 -8
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# compile_lvgl.sh — Download LVGL v9.2 source and compile into lib/liblvgl.a
# Clone & compile in /tmp (fast container-local fs).
# Copy source + objects to /lvgl (host mount) for debugging.
# Cache liblvgl.a on host mount (/code/lvgl/) to skip rebuild.
set -e
LVGL_VERSION="v9.2.2"
@@ -10,6 +10,7 @@ LVGL_DIR="/tmp/lvgl"
OBJ_DIR="/tmp/lvgl_obj"
CONF_DIR="$(pwd)/lvglh"
OUT_DIR="$(pwd)/lib"
CACHE_DIR="/code/lvgl"
CC="gcc"
CFLAGS="-m32 -march=i686 -ffreestanding \
@@ -26,6 +27,17 @@ echo " "
echo "Compiling LVGL..."
echo " "
# If cached liblvgl.a exists on host mount, just copy it and skip everything
if [ -f "${CACHE_DIR}/liblvgl.a" ]; then
echo "Found cached liblvgl.a in ${CACHE_DIR}, copying to ${OUT_DIR}..."
cp "${CACHE_DIR}/liblvgl.a" "${OUT_DIR}/liblvgl.a"
echo "(Delete lvgl/liblvgl.a to force a full rebuild.)"
echo " "
echo "LVGL compilation complete (cached)."
echo " "
exit 0
fi
# Clone LVGL into /tmp (container-local)
rm -rf "$LVGL_DIR"
echo "Downloading LVGL ${LVGL_VERSION}..."
@@ -105,14 +117,16 @@ else
echo "No custom LVGL files in lvglh/."
fi
# Copy source + objects to /lvgl host mount for debugging
echo "Copying LVGL source and objects to host mount..."
mkdir /code/lvgl 2>/dev/null || true
rm -rf /code/lvgl/* /code/lvgl/.[!.]* /code/lvgl/..?* 2>/dev/null || true
cp -a "$LVGL_DIR/src" /code/lvgl/src
cp -a "$OBJ_DIR" /code/lvgl/obj
# Cache liblvgl.a and source to host mount for next build
echo "Caching LVGL to host mount..."
mkdir -p "$CACHE_DIR"
rm -rf ${CACHE_DIR}/* ${CACHE_DIR}/.[!.]* ${CACHE_DIR}/..?* 2>/dev/null || true
cp "${OUT_DIR}/liblvgl.a" "${CACHE_DIR}/liblvgl.a"
cp -a "$LVGL_DIR/src" "${CACHE_DIR}/src"
cp -a "$LVGL_DIR"/*.h "${CACHE_DIR}/" 2>/dev/null || true
cp -a "$OBJ_DIR" "${CACHE_DIR}/obj"
echo "Done."
echo " "
echo "LVGL compilation complete."
echo " "
echo " "
+1 -1
View File
@@ -4,4 +4,4 @@ echo "======================="
echo " "
echo "Compiling FPC Sources..."
echo " "
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/include/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -100,8 +100,8 @@ end;
procedure send(p_data : void; p_len : uint16);
begin
push_trace('net.send');
writeToLogLn('L1/NET: send');
//push_trace('net.send');
//writeToLogLn('L1: net.send');
if CBSend <> nil then CBSend(p_data, p_len);
pop_trace;
end;
@@ -111,7 +111,8 @@ var
context : PPacketContext;
begin
push_trace('net.recv');
//push_trace('net.recv');
//writeToLogLn('L1: net.recv');
context:= newPacketContext;
if CBNext <> nil then CBNext(p_data, p_len, context);
freePacketContext(context);
@@ -128,7 +129,6 @@ end;
procedure init;
begin
push_trace('net.init');
writeToLogLn('L1/NET: init');
//l2
eth2.register;
//l3
@@ -136,7 +136,6 @@ begin
ipv4.register;
//l4
icmp.register;
tcp.register;
udp.register;
//l5
dhcp.register;
+1 -4
View File
@@ -46,7 +46,6 @@ var
procedure registerTypePromisc(eType : uint16; RecvCB : TRecvCallback);
begin
push_trace('eth2.registerTypePromisc');
register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
Promisc[eType]:= true;
@@ -54,7 +53,6 @@ end;
procedure registerType(eType : uint16; RecvCB : TRecvCallback);
begin
push_trace('eth2.registerType');
register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
end;
@@ -95,7 +93,7 @@ var
buf : puint8;
begin
push_trace('eth2.recv');
//writeToLogLn(' L2: eth2.recv');
buf:= puint8(p_data);
Header:= PEthernetHeader(buf);
@@ -122,7 +120,6 @@ var
begin
push_trace('eth2.register');
if not Registered then begin
writeToLogLn(' L2/ETH: register');
for i:=0 to 65535 do begin
EthTypes[i]:= nil;
Promisc[i]:= false;
-9
View File
@@ -96,7 +96,6 @@ var
hSize, pSize : uint8;
begin
push_trace('arp.send');
if p_context <> nil then begin
buf:= kalloc(sizeof(TARPHeader));
hdr:= PARPHeader(buf);
@@ -136,8 +135,6 @@ var
context : PPacketContext;
begin
push_trace('arp.sendGratuitous');
writeToLogLn(' L3/ARP: sendGratuitous');
context:= newPacketContext;
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -153,7 +150,6 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.sendRequestGateway');
context:= newPacketContext;
CacheRecord:= findCacheRecordByIP(@getIPv4Config^.Gateway[0]);
if CacheRecord <> nil then begin
@@ -172,8 +168,6 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.sendRequest');
writeToLogLn(' L3/ARP: sendRequest');
context:= newPacketContext;
CopyIPv4(ip, @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -190,7 +184,6 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.resolveIP');
CacheRecord:= findCacheRecordByIP(ip);
resolveIP:= nil;
if CacheRecord = nil then begin
@@ -210,7 +203,6 @@ var
context : PPacketContext;
begin
push_trace('arp.recv');
{ Get our converted Header }
Header:= PARPHeader(p_data);
AHeader.Hardware_Type:= (Header^.Hardware_Type_Hi SHL 8) + Header^.Hardware_Type_Lo;
@@ -306,7 +298,6 @@ procedure register;
begin
push_trace('arp.register');
if not Registered then begin
writeToLogLn(' L3/ARP: register');
Cache:= LL_New(sizeof(TARPCacheRecord));
eth2.registerTypePromisc($0806, @recv);
stdio.registerCommand('ARP', @terminal_command_arp, 'Get ARP Table.');
-7
View File
@@ -46,9 +46,7 @@ var
function getIPv4Config : PIPv4Configuration;
begin
push_trace('ipv4.getIPv4Config');
getIPv4Config:= @Config;
pop_trace;
end;
procedure send(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -59,7 +57,6 @@ var
buffer : void;
begin
push_trace('ipv4.send');
inc(CurrentID);
Header.version:= 4;
Header.header_len:= 5;
@@ -87,7 +84,6 @@ begin
memcpy(uint32(p_data), uint32(Buffer) + (Header.header_len * 4), p_len);
eth2.send(Buffer, (Header.header_len * 4) + p_len, $0800, p_context);
kfree(Buffer);
pop_trace;
end;
procedure recv(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -99,7 +95,6 @@ var
len : uint16;
begin
push_trace('ipv4.recv');
Header:= PIPV4Header(p_data);
AHeader.version:= Header^.version;
AHeader.header_len:= Header^.header_len;
@@ -200,7 +195,6 @@ var
begin
push_trace('ipv4.register');
if not Registered then begin
writeToLogLn(' L3/IPv4: register');
for i:=0 to 255 do begin
Protocols[i]:= nil;
end;
@@ -219,7 +213,6 @@ end;
procedure registerProtocol(Protocol_ID : uint8; recv_callback : TRecvCallback);
begin
push_trace('ipv4.registerProtocol');
register;
if Protocols[Protocol_ID] = nil then Protocols[Protocol_ID]:= recv_callback;
pop_trace;
+1 -8
View File
@@ -23,7 +23,7 @@ interface
uses
bios_data_area,
lmemorymanager, tracer,
lmemorymanager,
net, nettypes, netutils, ipv4, arp, util;
type
@@ -55,7 +55,6 @@ var
i : uint8;
begin
push_trace('icmp.nextInactiveHandler');
nextInactiveHandler:= 0;
for i:=1 to 255 do begin
if not Handlers[i].Active then begin
@@ -81,8 +80,6 @@ var
Size : uint32;
begin
push_trace('icmp.sendICMPRequest');
writeToLogLn(' L4/ICMP: sendICMPRequest');
handle:= nextInactiveHandler;
Handlers[handle].Active:= true;
Handlers[handle].OnReply:= OnRep;
@@ -138,8 +135,6 @@ var
Handle : uint8;
begin
push_trace('icmp.recv');
writeToLogLn(' L4/ICMP: recv');
Header:= PICMPHeader(p_data);
//writehexlnWND(Header^.ICMP_Type, getTerminalHWND);
case Header^.ICMP_Type of
@@ -248,8 +243,6 @@ var
i : uint32;
begin
push_trace('icmp.register');
writeToLogLn(' L4/ICMP: register');
for i:=0 to 255 do begin
Handlers[i].Active:= false;
Handlers[i].OnError:= nil;
File diff suppressed because it is too large Load Diff
+1 -8
View File
@@ -25,7 +25,7 @@ uses
lmemorymanager,
nettypes, netutils,
ipv4, net,
tracer, util;
util;
procedure register();
function bind(bindContext : PUDPBindContext) : TUDPError;
@@ -71,7 +71,6 @@ begin
nullend:= true;
end;
pseudoBuffer:= kalloc(sizeof(TUDPPseudoHeader) + pseudoSize);
push_trace('udp.CalculateChecksum');
pseudoBuffer8:= puint8(pseudoBuffer);
pseudoBuffer16:= puint16(pseudoBuffer);
pseudoBuffer32:= puint32(pseudoBuffer);
@@ -119,7 +118,6 @@ var
begin
push_trace('udp.send');
if udpContext <> nil then begin
size:= p_len + sizeof(TUDPHeader);
buffer:= kalloc(size);
@@ -154,7 +152,6 @@ var
context : PUDPBindContext;
begin
push_trace('udp.bind');
result:= tueGenericError;
if bindContext <> nil then begin
if Ports[bindContext^.port] = nil then begin
@@ -177,7 +174,6 @@ var
context : PUDPBindContext;
begin
push_trace('udp.unbind');
result:= tueGenericError;
if bindContext <> nil then begin
context:= Ports[bindContext^.port];
@@ -207,7 +203,6 @@ var
size : uint16;
begin
push_trace('udp.ProcessPacket');
header:= PUDPHeader(p_data);
if Ports[switchendian16(header^.DstPort)] <> nil then begin
context:= PUDPPacketContext(kalloc(sizeof(TUDPPacketContext)));
@@ -250,8 +245,6 @@ var
Checksum : uint32;
begin
push_trace('udp.register');
writeToLogLn(' L4/UDP: register');
for i:=0 to 65535 do begin
Ports[i]:= nil;
end;
+3 -6
View File
@@ -415,7 +415,7 @@ end;
procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions);
begin
writeToLogLn(' L5/DHCP: Process NAK.');
syslog.logln('DHCP', 'Process NAK.');
{ Server provided a NAK, NULL configuration ready for next DISCOVER/Request }
nullConfiguration();
end;
@@ -429,7 +429,7 @@ var
cfgopt : void;
begin
writeToLogLn(' L5/DHCP: Process ACK.');
syslog.logln('DHCP', 'Process ACK.');
getIPv4Config^.UP:= false;
//Copy new address
@@ -484,7 +484,7 @@ Var
begin
syslog.logln('DHCP', 'Process OFFER.');
writeToLogLn(' L5/DHCP: Process OFFER.');
{ Check the Transaction ID matches our stored ID, discard if not. }
if Header^.Transaction_ID = Configuration^.Transaction then begin
syslog.logln('DHCP', 'XID Match');
@@ -566,7 +566,6 @@ var
begin
tracer.push_trace('dhcp.processPacket.enter');
writeToLogLn(' L5/DHCP: processPacket');
syslog.logln('DHCP','processPacket');
{ Give access to header values & process to correct endianness. }
@@ -637,7 +636,6 @@ var
begin
tracer.push_trace('dhcp.DHCPDiscover.begin');
writeToLogLn(' L5/DHCP: DHCPDiscover');
{ Ensure we have a socket bound. }
if Socket <> nil then begin
{ Clear any current configuration }
@@ -713,7 +711,6 @@ var
begin
tracer.push_trace('dhcp.register');
writeToLogLn(' L5/DHCP: register');
syslog.logln('DHCP', 'Register begin.');
{ Kalloc our Configuration Data }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More