x86_64 do not merge #76

Open
Aaron wants to merge 9 commits from 64bit into feature/sotrage-system-overhaul
pull from: 64bit
59 changed files with 1904 additions and 1307 deletions
Showing only changes of commit a27d9cb39d - Show all commits

No files matched your search

+2 -2
View File
@@ -205,7 +205,7 @@ Key constants:
- `DATA_OFFSET = $10000` — data area starts at 64 KB into each page - `DATA_OFFSET = $10000` — data area starts at 64 KB into each page
- `LARGE_ALLOC_MAGIC = $FFFFFFFE` — sentinel for klalloc'd multi-page allocations - `LARGE_ALLOC_MAGIC = $FFFFFFFE` — sentinel for klalloc'd multi-page allocations
Interrupt safety: `pushfd; cli; pop saved_flags` (stack-balanced) + `restore_if(saved_flags)` Interrupt safety: `pushfd; cli; pop saved_flags` (stack-balanced) + `arch.platform.cpu.unlock(saved_flags)`
inline procedure that only restores IF via `sti`, avoiding dangerous EFLAGS restoration inline procedure that only restores IF via `sti`, avoiding dangerous EFLAGS restoration
(IOPL, NT, VM, AC bits that caused Bad-TSS on IRET). (IOPL, NT, VM, AC bits that caused Bad-TSS on IRET).
@@ -256,7 +256,7 @@ list, fixes Search_Page, calls `free_page_at_address`). Skips Root_Page.
| Bug | Root Cause | Fix | | Bug | Root Cause | Fix |
|-----|-----------|-----| |-----|-----------|-----|
| Bad TSS exception during network processing | `pushfd`/`popfd` across separate asm blocks: FPC doesn't track ESP changes in asm, causing EFLAGS corruption (NT=1, IOPL wrong) → Bad TSS on IRET | Stack-balanced `pushfd; cli; pop local_var` + `restore_if()` that only does `sti` if IF was set | | Bad TSS exception during network processing | `pushfd`/`popfd` across separate asm blocks: FPC doesn't track ESP changes in asm, causing EFLAGS corruption (NT=1, IOPL wrong) → Bad TSS on IRET | Stack-balanced `pushfd; cli; pop local_var` + `arch.platform.cpu.unlock()` that only does `sti` if IF was set |
| GPF from SSE MOVAPS in doublebuffer flush | `SIZE_PREFIX=4`→8 gave 8-byte alignment; `MOVAPS` needs 16-byte. `klalloc` returned `page+8` (not 16-aligned) | `SIZE_PREFIX=16` (4B size + 12B pad), klalloc header expanded to 16 bytes | | GPF from SSE MOVAPS in doublebuffer flush | `SIZE_PREFIX=4`→8 gave 8-byte alignment; `MOVAPS` needs 16-byte. `klalloc` returned `page+8` (not 16-aligned) | `SIZE_PREFIX=16` (4B size + 12B pad), klalloc header expanded to 16 bytes |
| Pages never freed (historic) | `free_page` extracted wrong block index from PDE Address field | Fixed extraction to `Address SHR 10` — page freeing works for the first time | | Pages never freed (historic) | `free_page` extracted wrong block index from PDE Address field | Fixed extraction to `Address SHR 10` — page freeing works for the first time |
+2 -2
View File
@@ -19,7 +19,7 @@ Every allocation is preceded by a 16-byte prefix: 4 bytes for the unit count, 12
Allocations larger than a single heap page's capacity are handled by `klalloc`, which maps contiguous virtual pages and stores a magic sentinel (`$FFFFFFFE`) in the header so `kfree` can identify them and call `klfree` instead of the normal bitmap path. Allocations larger than a single heap page's capacity are handled by `klalloc`, which maps contiguous virtual pages and stores a magic sentinel (`$FFFFFFFE`) in the header so `kfree` can identify them and call `klfree` instead of the normal bitmap path.
`kalloc` and `kfree` disable interrupts for the duration of their critical sections using a stack-balanced `pushfd`/`cli`/`pop` sequence and restore the interrupt flag via `restore_if` on all exit paths. `kalloc` and `kfree` disable interrupts for the duration of their critical sections using a stack-balanced `pushfd`/`cli`/`pop` sequence and restore the interrupt flag via `arch.platform.cpu.unlock` on all exit paths.
## Dependencies ## Dependencies
@@ -132,7 +132,7 @@ Returns the number of heap pages currently in the linked list.
## Notes ## Notes
The `restore_if` helper checks bit 9 (IF) of the saved EFLAGS word and issues `STI` only if interrupts were enabled on entry. It uses `STI` rather than `POPFD` to avoid restoring potentially dangerous EFLAGS bits (IOPL, NT, VM, AC) that could trigger a General Protection Fault or Bad-TSS on the next `IRET`. The `arch.platform.cpu.unlock` helper checks bit 9 (IF) of the saved EFLAGS word and issues `STI` only if interrupts were enabled on entry. It uses `STI` rather than `POPFD` to avoid restoring potentially dangerous EFLAGS bits (IOPL, NT, VM, AC) that could trigger a General Protection Fault or Bad-TSS on the next `IRET`.
When `DEBUG_LMM` is defined, `kalloc` allocates one additional unit and writes `GUARD_MAGIC` at the end of the allocation. `kfree` verifies this sentinel before freeing; a mismatch triggers a GPF with a syslog error, catching buffer overruns at free time. When `DEBUG_LMM` is defined, `kalloc` allocates one additional unit and writes `GUARD_MAGIC` at the end of the allocation. `kfree` verifies this sentinel before freeing; a mismatch triggers a GPF with a syslog error, catching buffer overruns at free time.
+34 -5
View File
@@ -12,34 +12,61 @@
{ Shared PC interrupt-controller programming. Call with interrupts disabled. } { Shared PC interrupt-controller programming. Call with interrupts disabled. }
unit arch.common.legacyirq; unit arch.common.legacyirq;
interface interface
const const
PIT_INPUT_HZ = 1193182; PIT_INPUT_HZ = 1193182;
PIT_DIVISOR = 149; PIT_DIVISOR = 149;
procedure remap(masterMask, slaveMask: uint8); procedure remap(masterMask, slaveMask: uint8);
procedure masks(masterMask, slaveMask: uint8); procedure masks(masterMask, slaveMask: uint8);
procedure enableLine(line: uint8);
procedure timerStart; procedure timerStart;
function realIRQ(line: uint8): boolean; function realIRQ(line: uint8): boolean;
procedure acknowledge(line: uint8); procedure acknowledge(line: uint8);
implementation implementation
uses arch.platform.cpu; uses arch.platform.cpu;
procedure writeSlow(port: uint16; value: uint8); procedure writeSlow(port: uint16; value: uint8);
begin begin
outb(port, value); outb(port, value);
outb($80, 0); outb($80, 0);
end; end;
procedure masks(masterMask, slaveMask: uint8); procedure masks(masterMask, slaveMask: uint8);
begin begin
writeSlow($21, masterMask); writeSlow($A1, slaveMask); writeSlow($21, masterMask);
writeSlow($A1, slaveMask);
end; end;
procedure remap(masterMask, slaveMask: uint8); procedure remap(masterMask, slaveMask: uint8);
begin begin
writeSlow($20, $11); writeSlow($A0, $11); writeSlow($20, $11);
writeSlow($21, $20); writeSlow($A1, $28); writeSlow($A0, $11);
writeSlow($21, $04); writeSlow($A1, $02); writeSlow($21, $20);
writeSlow($21, $01); writeSlow($A1, $01); writeSlow($A1, $28);
writeSlow($21, $04);
writeSlow($A1, $02);
writeSlow($21, $01);
writeSlow($A1, $01);
masks(masterMask, slaveMask); masks(masterMask, slaveMask);
end; end;
procedure enableLine(line: uint8);
var
flags: PtrUInt;
begin
if line >= 16 then exit;
flags := arch.platform.cpu.lock;
if line < 8 then
outb($21, inb($21) and not uint8(1 shl line))
else begin
outb($A1, inb($A1) and not uint8(1 shl (line - 8)));
outb($21, inb($21) and not uint8(4));
end;
arch.platform.cpu.unlock(flags);
end;
procedure timerStart; procedure timerStart;
begin begin
{ Channel 0, low/high byte, mode 2, binary. } { Channel 0, low/high byte, mode 2, binary. }
@@ -47,6 +74,7 @@ begin
outb($40, PIT_DIVISOR and $FF); outb($40, PIT_DIVISOR and $FF);
outb($40, PIT_DIVISOR shr 8); outb($40, PIT_DIVISOR shr 8);
end; end;
function realIRQ(line: uint8): boolean; function realIRQ(line: uint8): boolean;
begin begin
realIRQ := line < 16; realIRQ := line < 16;
@@ -60,6 +88,7 @@ begin
if not realIRQ then outb($20, $20); if not realIRQ then outb($20, $20);
end; end;
end; end;
procedure acknowledge(line: uint8); procedure acknowledge(line: uint8);
begin begin
if line >= 16 then exit; if line >= 16 then exit;
+10
View File
@@ -15,6 +15,16 @@ function lock: PtrUInt;
procedure unlock(flags: PtrUInt); procedure unlock(flags: PtrUInt);
procedure outb(port: uint16; value: uint8); procedure outb(port: uint16; value: uint8);
function inb(port: uint16): uint8; function inb(port: uint16): uint8;
procedure outw(port: uint16; value: uint16);
function inw(port: uint16): uint16;
procedure copyBytes(source, dest: PtrUInt; bytes: SizeUInt); procedure copyBytes(source, dest: PtrUInt; bytes: SizeUInt);
procedure zero(dest: pointer; bytes: SizeUInt); procedure zero(dest: pointer; bytes: SizeUInt);
procedure idle; procedure idle;
procedure outl(port: uint16; value: uint32);
function inl(port: uint16): uint32;
type
TCPURegisters = record
eax, ebx, ecx, edx: uint32;
end;
procedure queryCPU(leaf, subleaf: uint32; var registers: TCPURegisters);
@@ -10,14 +10,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
unit arch.common.interrupts; type
interface TIRQHandler = procedure;
function lock: PtrUInt; TTimerHandler = procedure(data: void);
procedure unlock(flags: PtrUInt); procedure registerIRQ(vector: uint8; handler: TIRQHandler);
implementation procedure registerTimer(handler: TTimerHandler);
uses arch.platform.cpu; procedure routePCI(line, vector: uint8);
function lock: PtrUInt; function timerTicks: uint64;
begin lock := arch.platform.cpu.lock; end;
procedure unlock(flags: PtrUInt);
begin arch.platform.cpu.unlock(flags); end;
end.
+4 -1
View File
@@ -15,4 +15,7 @@ function allocateHeapPage: PtrUInt;
function allocateLarge(pages: uint32): PtrUInt; function allocateLarge(pages: uint32): PtrUInt;
procedure release(address: PtrUInt; pages: uint32); procedure release(address: PtrUInt; pages: uint32);
function identityReserve(address: PtrUInt): pointer; function identityReserve(address: PtrUInt): pointer;
function freeBacking: uint64; function freePhysicalBytes: uint64;
function totalPhysicalBytes: uint64;
function physicalAddress(address: PtrUInt): uint64;
function mapDevice(address: uint64; bytes: SizeUInt): pointer;
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2021 Kieron Morris & Aaron Hance
// Copyright 2026 Aaron Hance
//
// 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.
{ Shared dispatch for the table emitted by compile_initcalls.sh.
Initializers only register boot work or set globals; they cannot depend on
heap, hardware setup, or the alphabetical order of this generated table. }
var
unitsInitialized: boolean;
procedure initializeUnits;
var
i: longint;
entry: CodePointer;
begin
if unitsInitialized then exit;
unitsInitialized := true;
for i := 1 to InitFinalTable.TableCount do begin
entry := InitFinalTable.Procs[i].InitProc;
if entry <> nil then
TProcedure(entry)();
end;
end;
+3
View File
@@ -12,10 +12,13 @@
{ Commands extracted from io.stdio (Kieron Morris). } { Commands extracted from io.stdio (Kieron Morris). }
unit arch.x86.console; unit arch.x86.console;
interface interface
procedure init; procedure init;
implementation implementation
uses io.stdio, core.version, driver.timer.rtc, arch.x86.util; uses io.stdio, core.version, driver.timer.rtc, arch.x86.util;
procedure cmd_version(params: PParamList; stdin_buf, stdout_buf, stderr_buf: POutBuf); procedure cmd_version(params: PParamList; stdin_buf, stdout_buf, stderr_buf: POutBuf);
begin begin
bufWriteStr(stdout_buf, ' Asuro Version: '); bufWriteStr(stdout_buf, ' Asuro Version: ');
+1 -1
View File
@@ -38,7 +38,7 @@ type
Pmemory_map_t = boot.multiboot.Pmemory_map_t; Pmemory_map_t = boot.multiboot.Pmemory_map_t;
var var
multibootinfo : Pmultiboot_info_t = nil; multibootinfo : Pmultiboot_info_t absolute boot.multiboot.multibootinfo;
multibootmagic : uint32; multibootmagic : uint32;
implementation implementation
-24
View File
@@ -62,7 +62,6 @@ procedure resetSystem();
function getESP : uint32; function getESP : uint32;
function RolDWord(AValue : uint32; Dist : uint8) : uint32;
function RorDWord(AValue : uint32; Dist : uint8) : uint32; function RorDWord(AValue : uint32; Dist : uint8) : uint32;
function MsSinceSystemBoot : uint64; function MsSinceSystemBoot : uint64;
@@ -380,29 +379,6 @@ begin
getTSC:= (hi SHL 32) OR lo; getTSC:= (hi SHL 32) OR lo;
end; end;
function RolDWord(AValue : uint32; Dist : uint8) : uint32;
var
result : uint32;
i : uint8;
begin
result:= AValue;
asm
PUSH EAX
end;
for i:=0 to Dist-1 do begin
asm
MOV EAX, result
ROL EAX, 1
MOV result, EAX
end;
end;
asm
POP EAX
end;
RolDWord:= result;
end;
function RorDWord(AValue : uint32; Dist : uint8) : uint32; function RorDWord(AValue : uint32; Dist : uint8) : uint32;
var var
result : uint32; result : uint32;
+71 -8
View File
@@ -12,29 +12,67 @@
{ Build-selected x86 adapter. } { Build-selected x86 adapter. }
unit arch.platform.cpu; unit arch.platform.cpu;
interface interface
{$i ../../common/platform.cpu.inc} {$i ../../common/platform.cpu.inc}
implementation implementation
uses arch.x86.util, memory.raw; uses arch.x86.util, memory.raw;
function lock: PtrUInt; assembler; nostackframe; function lock: PtrUInt; assembler; nostackframe;
asm pushfd; cli; pop eax end; asm
pushfd;
cli;
pop eax
end;
procedure unlock(flags: PtrUInt); procedure unlock(flags: PtrUInt);
begin if (flags and $200) <> 0 then asm sti end; end; begin
if (flags and $200) <> 0 then asm
sti
end;
end;
procedure idle; procedure idle;
begin asm hlt end; end; begin
asm
hlt
end;
end;
procedure outb(port: uint16; value: uint8); procedure outb(port: uint16; value: uint8);
begin arch.x86.util.outb(port, value); end; begin
arch.x86.util.outb(port, value);
end;
function inb(port: uint16): uint8; function inb(port: uint16): uint8;
begin inb := arch.x86.util.inb(port); end; begin
inb := arch.x86.util.inb(port);
end;
procedure copyBytes(source, dest: PtrUInt; bytes: SizeUInt); procedure copyBytes(source, dest: PtrUInt; bytes: SizeUInt);
begin begin
if bytes >= 16 then arch.x86.util.__REP_MOVSB_memcpy(source, dest, bytes) if bytes >= 16 then arch.x86.util.__REP_MOVSB_memcpy(source, dest, bytes)
else memory.raw.move(pointer(source), pointer(dest), bytes); else memory.raw.move(pointer(source), pointer(dest), bytes);
end; end;
procedure zero(dest: pointer; bytes: SizeUInt);
var d: pointer; b: SizeUInt; procedure outw(port: uint16; value: uint16);
begin begin
d := dest; b := bytes; arch.x86.util.outw(port, value);
end;
function inw(port: uint16): uint16;
begin
inw := arch.x86.util.inw(port);
end;
procedure zero(dest: pointer; bytes: SizeUInt);
var
d: pointer;
b: SizeUInt;
begin
d := dest;
b := bytes;
if b = 0 then exit; if b = 0 then exit;
asm asm
push edi push edi
@@ -50,4 +88,29 @@ begin
pop edi pop edi
end; end;
end; end;
procedure outl(port: uint16; value: uint32);
begin
arch.x86.util.outl(port, value);
end;
function inl(port: uint16): uint32;
begin
inl := arch.x86.util.inl(port);
end;
procedure queryCPU(leaf, subleaf: uint32; var registers: TCPURegisters); assembler; nostackframe;
asm
push ebx
push edi
mov edi, ecx
mov ecx, edx
cpuid
mov [edi], eax
mov [edi + 4], ebx
mov [edi + 8], ecx
mov [edi + 12], edx
pop edi
pop ebx
end;
end. end.
@@ -12,22 +12,39 @@
{ Build-selected x86 adapter. } { Build-selected x86 adapter. }
unit arch.platform.diagnostics; unit arch.platform.diagnostics;
interface interface
{$i ../../common/platform.diagnostics.inc} {$i ../../common/platform.diagnostics.inc}
implementation implementation
uses io.syslog, debug.tracer, core.panic; uses io.syslog, debug.tracer, core.panic;
procedure log(tag, message: pchar); procedure log(tag, message: pchar);
begin io.syslog.logln(tag, message); end; begin
io.syslog.logln(tag, message);
end;
procedure push_trace(name: pchar); procedure push_trace(name: pchar);
begin debug.tracer.push_trace(name); end; begin
debug.tracer.push_trace(name);
end;
procedure pop_trace; procedure pop_trace;
begin debug.tracer.pop_trace; end; begin
debug.tracer.pop_trace;
end;
procedure fatal(tag, message: pchar); procedure fatal(tag, message: pchar);
begin core.panic.panic(tag, message, nil); end; begin
core.panic.panic(tag, message, nil);
end;
procedure testSummary(tag, passedKey, failedKey: pchar; passed, failed: uint32); procedure testSummary(tag, passedKey, failedKey: pchar; passed, failed: uint32);
begin begin
io.syslog.log(tag, ''); io.syslog.log(tag, '');
io.syslog.writeint(passed); io.syslog.writestring(' passed, '); io.syslog.writeint(passed);
io.syslog.writeint(failed); io.syslog.writestringln(' failed.'); io.syslog.writestring(' passed, ');
io.syslog.writeint(failed);
io.syslog.writestringln(' failed.');
end; end;
end. end.
@@ -0,0 +1,47 @@
// Copyright 2026 Aaron Hance
//
// 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.
unit arch.platform.interrupts;
interface
{$i ../../common/platform.interrupts.inc}
implementation
uses arch.x86.isr.mgr, arch.x86.isr.tmr0, arch.x86.isr.ioapic,
arch.x86.bda, arch.platform.cpu;
function timerTicks: uint64;
var
flags: PtrUInt;
begin
flags := arch.platform.cpu.lock;
timerTicks := Counters.c64;
arch.platform.cpu.unlock(flags);
end;
procedure registerIRQ(vector: uint8; handler: TIRQHandler);
begin
arch.x86.isr.mgr.registerISR(vector, handler);
end;
procedure registerTimer(handler: TTimerHandler);
begin
arch.x86.isr.tmr0.hook(PtrUInt(handler));
end;
procedure routePCI(line, vector: uint8);
begin
arch.x86.isr.ioapic.init;
arch.x86.isr.ioapic.route_pci_irq(line, vector);
end;
end.
+55 -10
View File
@@ -12,25 +12,33 @@
{ Mapping policy extracted from memory.heap (Kieron Morris). } { Mapping policy extracted from memory.heap (Kieron Morris). }
unit arch.platform.memory; unit arch.platform.memory;
interface interface
const MAX_HEAP_REGIONS = 256; const MAX_HEAP_REGIONS = 256;
{$i ../../common/platform.memory.inc} {$i ../../common/platform.memory.inc}
implementation implementation
uses arch.x86.memory.virtual, arch.x86.memory.physical, arch.platform.diagnostics; uses arch.x86.memory.virtual, arch.x86.memory.physical, arch.platform.diagnostics;
function allocateHeapPage: PtrUInt; function allocateHeapPage: PtrUInt;
var i: uint32; var
i: uint32;
begin begin
allocateHeapPage := 0; allocateHeapPage := 0;
i := KERNEL_PAGE_NUMBER + 4; i := KERNEL_PAGE_NUMBER + 4;
while i < 1024 do begin while i < 1024 do begin
if arch.x86.memory.virtual.new_page(i) then begin if arch.x86.memory.virtual.new_page(i) then begin
allocateHeapPage := i shl 22; exit; allocateHeapPage := i shl 22;
exit;
end; end;
inc(i); inc(i);
end; end;
end; end;
function allocateLarge(pages: uint32): PtrUInt; function allocateLarge(pages: uint32): PtrUInt;
var curr_page, i: uint16; miss: boolean; var
curr_page, i: uint16;
miss: boolean;
begin begin
allocateLarge := 0; allocateLarge := 0;
if (pages = 0) or (pages > MAX_HEAP_REGIONS) then exit; if (pages = 0) or (pages > MAX_HEAP_REGIONS) then exit;
@@ -39,7 +47,9 @@ begin
miss := false; miss := false;
for i := 0 to pages - 1 do begin for i := 0 to pages - 1 do begin
if not page_mappable(curr_page + i) then begin if not page_mappable(curr_page + i) then begin
miss := true; curr_page := curr_page + i; break; miss := true;
curr_page := curr_page + i;
break;
end; end;
end; end;
if not miss then begin if not miss then begin
@@ -47,7 +57,8 @@ begin
while i < pages do begin while i < pages do begin
if not arch.x86.memory.virtual.new_page(curr_page + i) then begin if not arch.x86.memory.virtual.new_page(curr_page + i) then begin
while i > 0 do begin while i > 0 do begin
dec(i); arch.x86.memory.virtual.free_page(curr_page + i); dec(i);
arch.x86.memory.virtual.free_page(curr_page + i);
end; end;
exit; exit;
end; end;
@@ -59,23 +70,57 @@ begin
inc(curr_page); inc(curr_page);
end; end;
end; end;
procedure release(address: PtrUInt; pages: uint32); procedure release(address: PtrUInt; pages: uint32);
var i: uint32; page_num: uint16; var
i: uint32;
page_num: uint16;
begin begin
if (pages = 0) or (pages > MAX_HEAP_REGIONS) then begin if (pages = 0) or (pages > MAX_HEAP_REGIONS) then begin
fatal('LMM', 'Invalid heap region release'); exit; fatal('LMM', 'Invalid heap region release');
exit;
end; end;
page_num := address shr 22; page_num := address shr 22;
for i := 0 to pages - 1 do arch.x86.memory.virtual.free_page(page_num + uint16(i)); for i := 0 to pages - 1 do arch.x86.memory.virtual.free_page(page_num + uint16(i));
end; end;
function identityReserve(address: PtrUInt): pointer; function identityReserve(address: PtrUInt): pointer;
var block: uint16; var
block: uint16;
begin begin
block := address shr 22; block := address shr 22;
force_alloc_block(block, 0); force_alloc_block(block, 0);
map_page(block, block); map_page(block, block);
identityReserve := pointer(uint32(block) shl 22); identityReserve := pointer(uint32(block) shl 22);
end; end;
function freeBacking: uint64;
begin freeBacking := pmm_free_blocks; end; function freePhysicalBytes: uint64;
begin
freePhysicalBytes := uint64(pmm_free_blocks) * $400000;
end;
function totalPhysicalBytes: uint64;
begin
totalPhysicalBytes := uint64(pmm_total_blocks) * $400000;
end;
function physicalAddress(address: PtrUInt): uint64;
begin
physicalAddress := arch.x86.memory.virtual.vtop(address);
end;
function mapDevice(address: uint64; bytes: SizeUInt): pointer;
var
page, last: uint32;
begin
mapDevice := nil;
if (bytes = 0) or (address > $FFFFFFFF) or (bytes - 1 > $FFFFFFFF - address) then exit;
page := uint32(address) shr 22;
last := uint32(address + bytes - 1) shr 22;
while page <= last do begin
identityReserve(page shl 22);
inc(page);
end;
mapDevice := pointer(PtrUInt(address));
end;
end. end.
@@ -12,12 +12,20 @@
{ Build-selected x86 adapter. } { Build-selected x86 adapter. }
unit arch.platform.process; unit arch.platform.process;
interface interface
{$i ../../common/platform.process.inc} {$i ../../common/platform.process.inc}
implementation implementation
uses arch.x86.proc.context, arch.x86.bda; uses arch.x86.proc.context, arch.x86.bda;
function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt; function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt;
begin prepare := arch.x86.proc.context.prepare(stack, bytes, entry); end; begin
prepare := arch.x86.proc.context.prepare(stack, bytes, entry);
end;
function timerTicks: uint32; function timerTicks: uint32;
begin timerTicks := PUInt32(@Counters.c32)^; end; begin
timerTicks := PUInt32(@Counters.c32)^;
end;
end. end.
+6 -1
View File
@@ -12,12 +12,17 @@
{ i386 initial frame, extracted from proc.mgr (Kieron Morris). } { i386 initial frame, extracted from proc.mgr (Kieron Morris). }
unit arch.x86.proc.context; unit arch.x86.proc.context;
interface interface
function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt; function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt;
implementation implementation
uses memory.raw; uses memory.raw;
function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt; function prepare(stack: pointer; bytes: SizeUInt; entry: pointer): PtrUInt;
var top, frame: PtrUInt; i: uint32; var
top, frame: PtrUInt;
i: uint32;
begin begin
prepare := 0; prepare := 0;
if (stack = nil) or (entry = nil) or (bytes < 64) or if (stack = nil) or (entry = nil) or (bytes < 64) or
+14 -35
View File
@@ -119,7 +119,6 @@ function Round(d: Double): int64;
implementation implementation
{ ---- Raw driver.io.serial debug helpers (COM1 $3F8, no dependencies) ---- } { ---- Raw driver.io.serial debug helpers (COM1 $3F8, no dependencies) ---- }
procedure serial_putch(ch: char); assembler; procedure serial_putch(ch: char); assembler;
asm asm
push edx push edx
@@ -154,7 +153,8 @@ begin
end; end;
procedure serial_putstr(s: pchar); procedure serial_putstr(s: pchar);
var i: uint32; var
i: uint32;
begin begin
i := 0; i := 0;
while s[i] <> #0 do begin while s[i] <> #0 do begin
@@ -196,20 +196,11 @@ begin
end; end;
end; end;
{$i ../common/system.init.inc}
procedure fpc_initializeunits; [public, alias: 'FPC_INITIALIZEUNITS']; compilerproc; procedure fpc_initializeunits; [public, alias: 'FPC_INITIALIZEUNITS']; compilerproc;
var
i : longint;
proc : CodePointer;
begin begin
{ Walk the compiler-generated INITFINAL table and call each unit's initializeUnits;
initialization procedure (if non-nil). This runs before kmain, so
initialization sections must only do trivial work — write to static
globals, register boot entries, etc. No I/O or heap allocation. }
for i := 1 to InitFinalTable.TableCount do begin
proc := InitFinalTable.Procs[i].InitProc;
if proc <> nil then
TProcedure(proc)();
end;
end; end;
procedure fpc_do_exit; [public, alias: 'FPC_DO_EXIT']; compilerproc; procedure fpc_do_exit; [public, alias: 'FPC_DO_EXIT']; compilerproc;
@@ -348,7 +339,8 @@ begin
end; end;
function fpc_mul_dword_to_qword(f1, f2: uint32): qword; [public, alias: 'FPC_MUL_DWORD_TO_QWORD']; compilerproc; function fpc_mul_dword_to_qword(f1, f2: uint32): qword; [public, alias: 'FPC_MUL_DWORD_TO_QWORD']; compilerproc;
var res: qword; var
res: qword;
begin begin
asm asm
MOV EAX, f1 MOV EAX, f1
@@ -368,8 +360,10 @@ procedure udiv64(dividendLo, dividendHi, divisorLo, divisorHi: uint32;
var var
bit: longint; bit: longint;
begin begin
quotLo := 0; quotHi := 0; quotLo := 0;
remLo := 0; remHi := 0; quotHi := 0;
remLo := 0;
remHi := 0;
for bit := 63 downto 0 do begin for bit := 63 downto 0 do begin
{ rem := rem shl 1 } { rem := rem shl 1 }
@@ -567,7 +561,6 @@ begin
end; end;
{ ---------- Float-to-integer intrinsics ---------- } { ---------- Float-to-integer intrinsics ---------- }
function Trunc(d: Double): int64; [public, alias: 'FPC_TRUNC']; function Trunc(d: Double): int64; [public, alias: 'FPC_TRUNC'];
var var
oldcw, newcw: word; oldcw, newcw: word;
@@ -599,8 +592,8 @@ begin
end; end;
{ ---------- Memory allocation compilerprocs ---------- } { ---------- Memory allocation compilerprocs ---------- }
function kernel_kalloc(size: uint32): Pointer; external name 'kernel_kalloc'; function kernel_kalloc(size: uint32): Pointer; external name 'kernel_kalloc';
procedure kernel_kfree(p: Pointer); external name 'kernel_kfree'; procedure kernel_kfree(p: Pointer); external name 'kernel_kfree';
function fpc_getmem(size: PtrUInt): Pointer; function fpc_getmem(size: PtrUInt): Pointer;
@@ -616,7 +609,6 @@ begin
end; end;
{ ---------- Exception handling compilerprocs ---------- } { ---------- Exception handling compilerprocs ---------- }
procedure fpc_reraise; [public, alias: 'FPC_RERAISE']; compilerproc; procedure fpc_reraise; [public, alias: 'FPC_RERAISE']; compilerproc;
begin begin
{ In a bare-metal core.version re-raise is a fatal condition } { In a bare-metal core.version re-raise is a fatal condition }
@@ -641,30 +633,17 @@ begin
end; end;
procedure init(); procedure init();
var
i : longint;
proc : CodePointer;
begin begin
ASURO_KERNEL_START := uint32(@AK_START); ASURO_KERNEL_START := uint32(@AK_START);
ASURO_KERNEL_END := uint32(@AK_END); ASURO_KERNEL_END := uint32(@AK_END);
ASURO_KERNEL_SIZE:= ASURO_KERNEL_END - ASURO_KERNEL_START; ASURO_KERNEL_SIZE := ASURO_KERNEL_END - ASURO_KERNEL_START;
ExceptAddrStack := nil; ExceptAddrStack := nil;
ErrorAddr := nil; ErrorAddr := nil;
ErrorCode := 0; ErrorCode := 0;
ExitCode := 0; ExitCode := 0;
ExitProc := nil; ExitProc := nil;
{ Walk the INITFINAL table generated by compile_initcalls.sh and call initializeUnits;
each unit's initialization section. FPC with -n does not insert this
call automatically, so we do it explicitly here — after basic system
globals are set up but before kmain proceeds.
Note: we inline the walk rather than calling fpc_initializeunits
because compilerproc procedures cannot be called from Pascal code. }
for i := 1 to InitFinalTable.TableCount do begin
proc := InitFinalTable.Procs[i].InitProc;
if proc <> nil then
TProcedure(proc)();
end;
end; end;
end. end.
File diff suppressed because it is too large. Load diff
+2
View File
@@ -11,8 +11,10 @@
// limitations under the License. // limitations under the License.
unit arch.x86_64.debug; unit arch.x86_64.debug;
interface interface
procedure init; procedure init;
implementation implementation
uses debug.early; uses debug.early;
{ The stub initializes COM1. Bounded polling also allows boot without a UART. } { The stub initializes COM1. Bounded polling also allows boot without a UART. }
File diff suppressed because it is too large. Load diff
Loaded 20 of 59 files, more files were not shown because too many files have changed in this diff. Show more