Compare commits

..
2 Commits
Author SHA1 Message Date
t3hn3rd d3c164e8af Merge branch 'feature/vtop-fix' into feature/tcp
continuous-integration/drone/push Build is passing
2026-03-03 19:10:38 +00:00
t3hn3rd 5e9d0004d7 feature: implement TCP (RFC 793) protocol driver
continuous-integration/drone/push Build is passing
Add full TCP/IP stack implementation at L4 alongside UDP and ICMP.

Core Protocol Engine:
- TCP types in nettypes.pas (header, TCB, state enum, error codes,
  callbacks, OOO entry, socket structures)
- 3-way handshake (active & passive OPEN)
- Reliable data transfer with ACK and sequence number tracking
- Graceful close (FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT)
- RST send/receive handling
- Retransmission with exponential backoff (max 5 attempts)
- Pseudo-header based checksum (RFC 793)

Server Support:
- LISTEN → SYN_RECEIVED → ESTABLISHED passive open path
- Listen backlog enforcement (configurable per-socket)
- accept() to retrieve established child connections

Robustness & Hardening:
- Delayed ACK timer (~200ms)
- Nagle's algorithm (buffer small sends while unACKed data pending)
- Jacobson/Karels RTT estimation with adaptive RTO
- Congestion control (slow start / congestion avoidance)
- Zero-window probing with exponential backoff
- MSS option negotiation in SYN/SYN-ACK (Kind=2, Len=4)
- Keep-alive (30s idle, 10s interval, 5 probes)
- Out-of-order segment reassembly (4-slot buffer)

Terminal & Testing:
- tcpconnect: active open + send "Hello, World!"
- tcplisten: passive open with syslog output
- tcphttp: HTTP/1.0 GET client

Also add push_trace() instrumentation to net, eth2, arp, ipv4,
icmp, udp, and dhcp entry points for call tracing, and register
tcp in net.init.
2026-03-03 10:55:50 +00:00
15 changed files with 2379 additions and 896 deletions

No files matched your search

File diff suppressed because it is too large. Load diff
+5 -4
View File
@@ -100,8 +100,8 @@ end;
procedure send(p_data : void; p_len : uint16); procedure send(p_data : void; p_len : uint16);
begin begin
//push_trace('net.send'); push_trace('net.send');
//writeToLogLn('L1: net.send'); writeToLogLn('L1/NET: send');
if CBSend <> nil then CBSend(p_data, p_len); if CBSend <> nil then CBSend(p_data, p_len);
pop_trace; pop_trace;
end; end;
@@ -111,8 +111,7 @@ var
context : PPacketContext; context : PPacketContext;
begin begin
//push_trace('net.recv'); push_trace('net.recv');
//writeToLogLn('L1: net.recv');
context:= newPacketContext; context:= newPacketContext;
if CBNext <> nil then CBNext(p_data, p_len, context); if CBNext <> nil then CBNext(p_data, p_len, context);
freePacketContext(context); freePacketContext(context);
@@ -129,6 +128,7 @@ end;
procedure init; procedure init;
begin begin
push_trace('net.init'); push_trace('net.init');
writeToLogLn('L1/NET: init');
//l2 //l2
eth2.register; eth2.register;
//l3 //l3
@@ -136,6 +136,7 @@ begin
ipv4.register; ipv4.register;
//l4 //l4
icmp.register; icmp.register;
tcp.register;
udp.register; udp.register;
//l5 //l5
dhcp.register; dhcp.register;
+4 -1
View File
@@ -46,6 +46,7 @@ var
procedure registerTypePromisc(eType : uint16; RecvCB : TRecvCallback); procedure registerTypePromisc(eType : uint16; RecvCB : TRecvCallback);
begin begin
push_trace('eth2.registerTypePromisc');
register; register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB; if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
Promisc[eType]:= true; Promisc[eType]:= true;
@@ -53,6 +54,7 @@ end;
procedure registerType(eType : uint16; RecvCB : TRecvCallback); procedure registerType(eType : uint16; RecvCB : TRecvCallback);
begin begin
push_trace('eth2.registerType');
register; register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB; if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
end; end;
@@ -93,7 +95,7 @@ var
buf : puint8; buf : puint8;
begin begin
//writeToLogLn(' L2: eth2.recv'); push_trace('eth2.recv');
buf:= puint8(p_data); buf:= puint8(p_data);
Header:= PEthernetHeader(buf); Header:= PEthernetHeader(buf);
@@ -120,6 +122,7 @@ var
begin begin
push_trace('eth2.register'); push_trace('eth2.register');
if not Registered then begin if not Registered then begin
writeToLogLn(' L2/ETH: register');
for i:=0 to 65535 do begin for i:=0 to 65535 do begin
EthTypes[i]:= nil; EthTypes[i]:= nil;
Promisc[i]:= false; Promisc[i]:= false;
+9
View File
@@ -96,6 +96,7 @@ var
hSize, pSize : uint8; hSize, pSize : uint8;
begin begin
push_trace('arp.send');
if p_context <> nil then begin if p_context <> nil then begin
buf:= kalloc(sizeof(TARPHeader)); buf:= kalloc(sizeof(TARPHeader));
hdr:= PARPHeader(buf); hdr:= PARPHeader(buf);
@@ -135,6 +136,8 @@ var
context : PPacketContext; context : PPacketContext;
begin begin
push_trace('arp.sendGratuitous');
writeToLogLn(' L3/ARP: sendGratuitous');
context:= newPacketContext; context:= newPacketContext;
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Destination[0]); CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]); CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -150,6 +153,7 @@ var
CacheRecord : PARPCacheRecord; CacheRecord : PARPCacheRecord;
begin begin
push_trace('arp.sendRequestGateway');
context:= newPacketContext; context:= newPacketContext;
CacheRecord:= findCacheRecordByIP(@getIPv4Config^.Gateway[0]); CacheRecord:= findCacheRecordByIP(@getIPv4Config^.Gateway[0]);
if CacheRecord <> nil then begin if CacheRecord <> nil then begin
@@ -168,6 +172,8 @@ var
CacheRecord : PARPCacheRecord; CacheRecord : PARPCacheRecord;
begin begin
push_trace('arp.sendRequest');
writeToLogLn(' L3/ARP: sendRequest');
context:= newPacketContext; context:= newPacketContext;
CopyIPv4(ip, @context^.IP.Destination[0]); CopyIPv4(ip, @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]); CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -184,6 +190,7 @@ var
CacheRecord : PARPCacheRecord; CacheRecord : PARPCacheRecord;
begin begin
push_trace('arp.resolveIP');
CacheRecord:= findCacheRecordByIP(ip); CacheRecord:= findCacheRecordByIP(ip);
resolveIP:= nil; resolveIP:= nil;
if CacheRecord = nil then begin if CacheRecord = nil then begin
@@ -203,6 +210,7 @@ var
context : PPacketContext; context : PPacketContext;
begin begin
push_trace('arp.recv');
{ Get our converted Header } { Get our converted Header }
Header:= PARPHeader(p_data); Header:= PARPHeader(p_data);
AHeader.Hardware_Type:= (Header^.Hardware_Type_Hi SHL 8) + Header^.Hardware_Type_Lo; AHeader.Hardware_Type:= (Header^.Hardware_Type_Hi SHL 8) + Header^.Hardware_Type_Lo;
@@ -298,6 +306,7 @@ procedure register;
begin begin
push_trace('arp.register'); push_trace('arp.register');
if not Registered then begin if not Registered then begin
writeToLogLn(' L3/ARP: register');
Cache:= LL_New(sizeof(TARPCacheRecord)); Cache:= LL_New(sizeof(TARPCacheRecord));
eth2.registerTypePromisc($0806, @recv); eth2.registerTypePromisc($0806, @recv);
stdio.registerCommand('ARP', @terminal_command_arp, 'Get ARP Table.'); stdio.registerCommand('ARP', @terminal_command_arp, 'Get ARP Table.');
+7
View File
@@ -46,7 +46,9 @@ var
function getIPv4Config : PIPv4Configuration; function getIPv4Config : PIPv4Configuration;
begin begin
push_trace('ipv4.getIPv4Config');
getIPv4Config:= @Config; getIPv4Config:= @Config;
pop_trace;
end; end;
procedure send(p_data : void; p_len : uint16; p_context : PPacketContext); procedure send(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -57,6 +59,7 @@ var
buffer : void; buffer : void;
begin begin
push_trace('ipv4.send');
inc(CurrentID); inc(CurrentID);
Header.version:= 4; Header.version:= 4;
Header.header_len:= 5; Header.header_len:= 5;
@@ -84,6 +87,7 @@ begin
memcpy(uint32(p_data), uint32(Buffer) + (Header.header_len * 4), p_len); memcpy(uint32(p_data), uint32(Buffer) + (Header.header_len * 4), p_len);
eth2.send(Buffer, (Header.header_len * 4) + p_len, $0800, p_context); eth2.send(Buffer, (Header.header_len * 4) + p_len, $0800, p_context);
kfree(Buffer); kfree(Buffer);
pop_trace;
end; end;
procedure recv(p_data : void; p_len : uint16; p_context : PPacketContext); procedure recv(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -95,6 +99,7 @@ var
len : uint16; len : uint16;
begin begin
push_trace('ipv4.recv');
Header:= PIPV4Header(p_data); Header:= PIPV4Header(p_data);
AHeader.version:= Header^.version; AHeader.version:= Header^.version;
AHeader.header_len:= Header^.header_len; AHeader.header_len:= Header^.header_len;
@@ -195,6 +200,7 @@ var
begin begin
push_trace('ipv4.register'); push_trace('ipv4.register');
if not Registered then begin if not Registered then begin
writeToLogLn(' L3/IPv4: register');
for i:=0 to 255 do begin for i:=0 to 255 do begin
Protocols[i]:= nil; Protocols[i]:= nil;
end; end;
@@ -213,6 +219,7 @@ end;
procedure registerProtocol(Protocol_ID : uint8; recv_callback : TRecvCallback); procedure registerProtocol(Protocol_ID : uint8; recv_callback : TRecvCallback);
begin begin
push_trace('ipv4.registerProtocol');
register; register;
if Protocols[Protocol_ID] = nil then Protocols[Protocol_ID]:= recv_callback; if Protocols[Protocol_ID] = nil then Protocols[Protocol_ID]:= recv_callback;
pop_trace; pop_trace;
+8 -1
View File
@@ -23,7 +23,7 @@ interface
uses uses
bios_data_area, bios_data_area,
lmemorymanager, lmemorymanager, tracer,
net, nettypes, netutils, ipv4, arp, util; net, nettypes, netutils, ipv4, arp, util;
type type
@@ -55,6 +55,7 @@ var
i : uint8; i : uint8;
begin begin
push_trace('icmp.nextInactiveHandler');
nextInactiveHandler:= 0; nextInactiveHandler:= 0;
for i:=1 to 255 do begin for i:=1 to 255 do begin
if not Handlers[i].Active then begin if not Handlers[i].Active then begin
@@ -80,6 +81,8 @@ var
Size : uint32; Size : uint32;
begin begin
push_trace('icmp.sendICMPRequest');
writeToLogLn(' L4/ICMP: sendICMPRequest');
handle:= nextInactiveHandler; handle:= nextInactiveHandler;
Handlers[handle].Active:= true; Handlers[handle].Active:= true;
Handlers[handle].OnReply:= OnRep; Handlers[handle].OnReply:= OnRep;
@@ -135,6 +138,8 @@ var
Handle : uint8; Handle : uint8;
begin begin
push_trace('icmp.recv');
writeToLogLn(' L4/ICMP: recv');
Header:= PICMPHeader(p_data); Header:= PICMPHeader(p_data);
//writehexlnWND(Header^.ICMP_Type, getTerminalHWND); //writehexlnWND(Header^.ICMP_Type, getTerminalHWND);
case Header^.ICMP_Type of case Header^.ICMP_Type of
@@ -243,6 +248,8 @@ var
i : uint32; i : uint32;
begin begin
push_trace('icmp.register');
writeToLogLn(' L4/ICMP: register');
for i:=0 to 255 do begin for i:=0 to 255 do begin
Handlers[i].Active:= false; Handlers[i].Active:= false;
Handlers[i].OnError:= nil; Handlers[i].OnError:= nil;
File diff suppressed because it is too large. Load diff
+8 -1
View File
@@ -25,7 +25,7 @@ uses
lmemorymanager, lmemorymanager,
nettypes, netutils, nettypes, netutils,
ipv4, net, ipv4, net,
util; tracer, util;
procedure register(); procedure register();
function bind(bindContext : PUDPBindContext) : TUDPError; function bind(bindContext : PUDPBindContext) : TUDPError;
@@ -71,6 +71,7 @@ begin
nullend:= true; nullend:= true;
end; end;
pseudoBuffer:= kalloc(sizeof(TUDPPseudoHeader) + pseudoSize); pseudoBuffer:= kalloc(sizeof(TUDPPseudoHeader) + pseudoSize);
push_trace('udp.CalculateChecksum');
pseudoBuffer8:= puint8(pseudoBuffer); pseudoBuffer8:= puint8(pseudoBuffer);
pseudoBuffer16:= puint16(pseudoBuffer); pseudoBuffer16:= puint16(pseudoBuffer);
pseudoBuffer32:= puint32(pseudoBuffer); pseudoBuffer32:= puint32(pseudoBuffer);
@@ -118,6 +119,7 @@ var
begin begin
push_trace('udp.send');
if udpContext <> nil then begin if udpContext <> nil then begin
size:= p_len + sizeof(TUDPHeader); size:= p_len + sizeof(TUDPHeader);
buffer:= kalloc(size); buffer:= kalloc(size);
@@ -152,6 +154,7 @@ var
context : PUDPBindContext; context : PUDPBindContext;
begin begin
push_trace('udp.bind');
result:= tueGenericError; result:= tueGenericError;
if bindContext <> nil then begin if bindContext <> nil then begin
if Ports[bindContext^.port] = nil then begin if Ports[bindContext^.port] = nil then begin
@@ -174,6 +177,7 @@ var
context : PUDPBindContext; context : PUDPBindContext;
begin begin
push_trace('udp.unbind');
result:= tueGenericError; result:= tueGenericError;
if bindContext <> nil then begin if bindContext <> nil then begin
context:= Ports[bindContext^.port]; context:= Ports[bindContext^.port];
@@ -203,6 +207,7 @@ var
size : uint16; size : uint16;
begin begin
push_trace('udp.ProcessPacket');
header:= PUDPHeader(p_data); header:= PUDPHeader(p_data);
if Ports[switchendian16(header^.DstPort)] <> nil then begin if Ports[switchendian16(header^.DstPort)] <> nil then begin
context:= PUDPPacketContext(kalloc(sizeof(TUDPPacketContext))); context:= PUDPPacketContext(kalloc(sizeof(TUDPPacketContext)));
@@ -245,6 +250,8 @@ var
Checksum : uint32; Checksum : uint32;
begin begin
push_trace('udp.register');
writeToLogLn(' L4/UDP: register');
for i:=0 to 65535 do begin for i:=0 to 65535 do begin
Ports[i]:= nil; Ports[i]:= nil;
end; end;
+6 -3
View File
@@ -415,7 +415,7 @@ end;
procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions); procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions);
begin begin
syslog.logln('DHCP', 'Process NAK.'); writeToLogLn(' L5/DHCP: Process NAK.');
{ Server provided a NAK, NULL configuration ready for next DISCOVER/Request } { Server provided a NAK, NULL configuration ready for next DISCOVER/Request }
nullConfiguration(); nullConfiguration();
end; end;
@@ -429,7 +429,7 @@ var
cfgopt : void; cfgopt : void;
begin begin
syslog.logln('DHCP', 'Process ACK.'); writeToLogLn(' L5/DHCP: Process ACK.');
getIPv4Config^.UP:= false; getIPv4Config^.UP:= false;
//Copy new address //Copy new address
@@ -484,7 +484,7 @@ Var
begin begin
syslog.logln('DHCP', 'Process OFFER.'); syslog.logln('DHCP', 'Process OFFER.');
writeToLogLn(' L5/DHCP: Process OFFER.');
{ Check the Transaction ID matches our stored ID, discard if not. } { Check the Transaction ID matches our stored ID, discard if not. }
if Header^.Transaction_ID = Configuration^.Transaction then begin if Header^.Transaction_ID = Configuration^.Transaction then begin
syslog.logln('DHCP', 'XID Match'); syslog.logln('DHCP', 'XID Match');
@@ -566,6 +566,7 @@ var
begin begin
tracer.push_trace('dhcp.processPacket.enter'); tracer.push_trace('dhcp.processPacket.enter');
writeToLogLn(' L5/DHCP: processPacket');
syslog.logln('DHCP','processPacket'); syslog.logln('DHCP','processPacket');
{ Give access to header values & process to correct endianness. } { Give access to header values & process to correct endianness. }
@@ -636,6 +637,7 @@ var
begin begin
tracer.push_trace('dhcp.DHCPDiscover.begin'); tracer.push_trace('dhcp.DHCPDiscover.begin');
writeToLogLn(' L5/DHCP: DHCPDiscover');
{ Ensure we have a socket bound. } { Ensure we have a socket bound. }
if Socket <> nil then begin if Socket <> nil then begin
{ Clear any current configuration } { Clear any current configuration }
@@ -711,6 +713,7 @@ var
begin begin
tracer.push_trace('dhcp.register'); tracer.push_trace('dhcp.register');
writeToLogLn(' L5/DHCP: register');
syslog.logln('DHCP', 'Register begin.'); syslog.logln('DHCP', 'Register begin.');
{ Kalloc our Configuration Data } { Kalloc our Configuration Data }
+18
View File
@@ -73,6 +73,23 @@ procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
implementation implementation
procedure terminal_command_meminfo(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
begin
push_trace('kernel.terminal_command_meminfo');
stdio.bufWriteStr(stdout_buf, 'Lower Memory = ');
stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_lower);
stdio.bufWriteStrLn(stdout_buf, 'KB');
stdio.bufWriteStr(stdout_buf, 'Higher Memory = ');
stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_upper);
stdio.bufWriteStrLn(stdout_buf, 'KB');
stdio.bufWriteStr(stdout_buf, 'Total Memory = ');
stdio.bufWriteInt(stdout_buf, ((multibootinfo^.mem_upper + 1000) div 1024) + 1);
stdio.bufWriteStrLn(stdout_buf, 'MB');
pop_trace;
end;
procedure terminal_command_bsod(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf); procedure terminal_command_bsod(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
begin begin
push_trace('kernel.terminal_command_bsod'); push_trace('kernel.terminal_command_bsod');
@@ -165,6 +182,7 @@ begin
{ Stdio Init } { Stdio Init }
stdio.init(); stdio.init();
stdio.registerCommand('MEMINFO', @terminal_command_meminfo, 'Print Simple Memory Information.');
stdio.registerCommand('BSOD', @terminal_command_bsod, 'Force a Panic Screen.'); stdio.registerCommand('BSOD', @terminal_command_bsod, 'Force a Panic Screen.');
tss.init(); tss.init();
+169 -524
View File
File diff suppressed because it is too large. Load diff
+111 -251
View File
File diff suppressed because it is too large. Load diff
-83
View File
@@ -1,83 +0,0 @@
// Copyright 2021 Kieron Morris
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{
Prog->meminfo - Print memory statistics (PMM / LMM).
@author(Kieron Morris <[email protected]>)
}
unit meminfo;
interface
uses
stdio, multiboot, pmemorymanager, lmemorymanager, tracer;
procedure init();
implementation
procedure run(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
var
pmm_total, pmm_free, pmm_used : uint32;
lmm_pages, lmm_free : uint32;
begin
{ Multiboot memory info }
stdio.bufWriteStrLn(stdout_buf, '--- Multiboot ---');
stdio.bufWriteStr(stdout_buf, 'Lower Memory : ');
stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_lower);
stdio.bufWriteStrLn(stdout_buf, ' KB');
stdio.bufWriteStr(stdout_buf, 'Upper Memory : ');
stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_upper);
stdio.bufWriteStrLn(stdout_buf, ' KB');
stdio.bufWriteStr(stdout_buf, 'Total Memory : ');
stdio.bufWriteInt(stdout_buf, ((multibootinfo^.mem_upper + 1000) div 1024) + 1);
stdio.bufWriteStrLn(stdout_buf, ' MB');
{ PMM stats }
stdio.bufWriteStrLn(stdout_buf, '--- PMM (4 MB blocks) ---');
pmm_total := pmemorymanager.pmm_total_blocks;
pmm_free := pmemorymanager.pmm_free_blocks;
pmm_used := pmm_total - pmm_free;
stdio.bufWriteStr(stdout_buf, 'Total Blocks : ');
stdio.bufWriteIntLn(stdout_buf, pmm_total);
stdio.bufWriteStr(stdout_buf, 'Free Blocks : ');
stdio.bufWriteIntLn(stdout_buf, pmm_free);
stdio.bufWriteStr(stdout_buf, 'Used Blocks : ');
stdio.bufWriteIntLn(stdout_buf, pmm_used);
stdio.bufWriteStr(stdout_buf, 'Free Physical : ');
stdio.bufWriteInt(stdout_buf, pmm_free * 4);
stdio.bufWriteStrLn(stdout_buf, ' MB');
{ LMM heap stats }
stdio.bufWriteStrLn(stdout_buf, '--- LMM (Heap) ---');
lmm_pages := lmemorymanager.lmm_page_count;
lmm_free := lmemorymanager.lmm_total_free;
stdio.bufWriteStr(stdout_buf, 'Heap Pages : ');
stdio.bufWriteIntLn(stdout_buf, lmm_pages);
stdio.bufWriteStr(stdout_buf, 'Heap Size : ');
stdio.bufWriteInt(stdout_buf, lmm_pages * 4);
stdio.bufWriteStrLn(stdout_buf, ' MB');
stdio.bufWriteStr(stdout_buf, 'Heap Free : ');
stdio.bufWriteInt(stdout_buf, lmm_free div 1024);
stdio.bufWriteStrLn(stdout_buf, ' KB');
end;
procedure init();
begin
tracer.push_trace('meminfo.init');
stdio.registerCommand('MEMINFO', @Run, 'Print memory statistics (PMM/LMM).');
end;
end.
+1 -2
View File
@@ -24,7 +24,7 @@ interface
uses uses
tracer, tracer,
//progs //progs
base64_prog, md5sum, dhclient, vbeinfo, meminfo; base64_prog, md5sum, dhclient, vbeinfo;
{ Initialize all baked-in programs } { Initialize all baked-in programs }
procedure init(); procedure init();
@@ -40,7 +40,6 @@ begin
tracer.push_trace('progmanager.dhclient.init'); tracer.push_trace('progmanager.dhclient.init');
dhclient.init(); dhclient.init();
vbeinfo.init(); vbeinfo.init();
meminfo.init();
end; end;
end. end.
+22 -26
View File
@@ -159,14 +159,20 @@ end;
function map_page(page_number : uint16; block : uint16) : boolean; function map_page(page_number : uint16; block : uint16) : boolean;
var var
addr : ubit20;
page : uint16;
rldpd : uint32; rldpd : uint32;
begin begin
push_trace('vmemorymanager.map_page'); push_trace('vmemorymanager.map_page');
{ Delegate to map_page_ex — no redundant direct PDE writes } map_page:= false;
map_page := map_page_ex(page_number, block, PageDirectory); PageDirectory^[page_number].Present:= true;
{ Reload CR3 to flush TLB } addr:= block;
rldpd := uint32(PageDirectory) - KERNEL_VIRTUAL_BASE; PageDirectory^[page_number].Address:= addr SHL 10;
PageDirectory^[page_number].PageSize:= true;
PageDirectory^[page_number].Writable:= true;
map_page:= map_page_ex(page_number, block, PageDirectory);
rldpd:= uint32(PageDirectory) - KERNEL_VIRTUAL_BASE;
asm asm
mov eax, rldpd mov eax, rldpd
mov CR3, eax mov CR3, eax
@@ -195,15 +201,14 @@ var
begin begin
push_trace('vmemorymanager.new_page'); push_trace('vmemorymanager.new_page');
new_page := false; new_page:= false;
if not PageDirectory^[page_number].Present then begin if not PageDirectory^[page_number].Present then begin
if not PageDirectory^[page_number].Reserved then begin if not PageDirectory^[page_number].Reserved then begin
block := pmemorymanager.new_block(uint32(PageDirectory)); block:= pmemorymanager.new_block(uint32(PageDirectory));
if block = 0 then begin if block < 2 then begin
{ OOM — PMM has no free blocks. Return false gracefully. } GPF;
syslog.logln('VMM', 'ERROR: new_page failed — PMM OOM.');
end else begin end else begin
new_page := map_page(page_number, block); new_page:= map_page(page_number, block);
end; end;
end; end;
end; end;
@@ -211,15 +216,17 @@ begin
end; end;
function page_mappable(page_number : uint16) : boolean; function page_mappable(page_number : uint16) : boolean;
var
block : uint16;
begin begin
push_trace('vmemorymanager.page_mappable'); push_trace('vmemorymanager.page_mappable');
page_mappable := false; page_mappable:= false;
if not PageDirectory^[page_number].Present then begin if not PageDirectory^[page_number].Present then begin
if not PageDirectory^[page_number].Reserved then begin if not PageDirectory^[page_number].Reserved then begin
page_mappable := true; page_mappable:= true;
end; end;
end; end;
pop_trace;
end; end;
function new_page_at_address(address : uint32) : boolean; function new_page_at_address(address : uint32) : boolean;
@@ -236,25 +243,14 @@ end;
procedure free_page(page_number : uint16); procedure free_page(page_number : uint16);
var var
block : uint16; block : uint16;
vaddr : uint32;
begin begin
push_trace('vmemorymanager.free_page'); push_trace('vmemorymanager.free_page');
if PageDirectory^[page_number].Present then begin if PageDirectory^[page_number].Present then begin
{ Recover block index: Address stores (block SHL 10), so SHR 10 gives block } block:= PageDirectory^[page_number].Address;
block := PageDirectory^[page_number].Address SHR 10;
{ Clear the PDE before invalidating }
PageDirectory^[page_number].Present := false;
PageDirectory^[page_number].Writable := false;
PageDirectory^[page_number].PageSize := false;
PageDirectory^[page_number].Address := 0;
{ Invalidate TLB for this virtual address (invlpg needs a virtual addr) }
vaddr := uint32(page_number) SHL 22;
asm asm
mov eax, vaddr invlpg [page_number]
invlpg [eax]
end; end;
{ Return physical block to PMM }
pmemorymanager.free_block(block, uint32(PageDirectory)); pmemorymanager.free_block(block, uint32(PageDirectory));
end else begin end else begin
GPF; GPF;