// === GLOBALS ===
tSpinlock glPhysicalPages;
Uint64 *gaSuperBitmap; // 1 bit = 64 Pages
-Uint64 *gaPrimaryBitmap; // 1 bit = 1 Page
+Uint64 *gaPrimaryBitmap; // 1 bit = 64 Pages
+Uint32 *gaiPageReferences; // Reference Counts
tPAddr giFirstFreePage; // First possibly free page
Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range
Uint64 giPhysRangeFirst[NUM_MM_PHYS_RANGES]; // First free page in each range
Uint64 giPhysRangeLast[NUM_MM_PHYS_RANGES]; // Last free page in each range
+Uint64 giMaxPhysPage = 0; // Maximum Physical page
// === CODE ===
void MM_InitPhys()
continue;
}
// Check page block (64 pages)
- if( gaPrimaryBitmap[addr >> 6] == -1) {
+ if( gaSuperBitmap[addr >> (6+6)] & (1 << (addr>>6)&63)) {
nFree = 0;
addr += 1 << (12+6);
addr &= (1 << (12+6)) - 1;
continue;
}
// Check individual page
- if( gaPrimaryBitmap[addr >> 6] & (1 << (addr&63)) ) {
+ if( gaiPageReferences[addr] ) {
nFree = 0;
addr ++;
continue;
addr -= Num;
for( i = 0; i < Num; i++ )
{
+ gaiPageReferences[addr] = 1;
gaPrimaryBitmap[addr>>6] |= 1 << (addr & 63);
if( gaPrimaryBitmap[addr>>6] == -1 )
gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64);
{
return MM_AllocPhysRange(1, -1);
}
+
+void MM_RefPhys(tPAddr PAddr)
+{
+ if( PAddr > giMaxPhysPage ) return ;
+ gaiPageReferences[ PAddr >> 12 ] ++;
+
+ gaPrimaryBitmap[PAddr >> 18] |= 1 << ((PAddr>>12) & 63);
+ if( gaPrimaryBitmap[PAddr >> 18] == -1 )
+ gaSuperBitmap[PAddr >> 24] |= 1 << ((PAddr >> 18) & 64);
+}
+
+void MM_DerefPhys(tPAddr PAddr)
+{
+ if( PAddr > giMaxPhysPage ) return ;
+ gaiPageReferences[ PAddr >> 12 ] --;
+ if( gaiPageReferences[ PAddr >> 12 ] )
+ {
+ gaPrimaryBitmap[PAddr >> 18] &= ~(1 << ((PAddr >> 12) & 63));
+ gaSuperBitmap[PAddr >> 24] &= ~(1 << ((PAddr >> 18) & 64));
+ }
+}
extern tGDT gGDT[];
extern void APStartup(); // 16-bit AP startup code
extern Uint GetRIP(); // start.asm
-extern Uint64 gaInitPML4[512]; // start.asm
-extern void Kernel_Stack_Top;
+extern Uint64 gInitialPML4[512]; // start.asm
+extern void gInitialKernelStack;
extern tSpinlock glThreadListLock;
extern int giNumCPUs;
extern int giNextTID;
gCurrentThread = &gThreadZero;
#endif
- gThreadZero.MemState.CR3 = (Uint)gaInitPML4 - KERNEL_BASE;
+ gThreadZero.MemState.CR3 = (Uint)gInitialPML4 - KERNEL_BASE;
// Set timer frequency
outb(0x43, 0x34); // Set Channel 0, Low/High, Rate Generator
return;
}
- curBase = (Uint)&Kernel_Stack_Top;
+ curBase = (Uint)&gInitialKernelStack;
LOG("curBase = 0x%x, newBase = 0x%x", curBase, newBase);
mov cr4, eax
; Load PDP4
- mov eax, gInitialPML4
+ mov eax, gInitialPML4 - KERNEL_BASE
mov cr3, eax
; Enable long/compatability mode
mov cr0, eax
; Load GDT
- lgdt [gGDTPtr]
+ lgdt [gGDTPtr - KERNEL_BASE]
mov ax, 0x10
mov ss, ax
mov ds, ax
jmp 0x08:start64 - KERNEL_BASE
[section .data]
+[global gGDT]
gGDT:
dd 0,0
dd 0x00000000, 0x00209800 ; 0x08: 64-bit Code
times MAX_CPUS dd 0, 0, 0, 0 ; 0x38+16*n: TSS 0
gGDTPtr:
dw $-gGDT-1
- dd gGDT
+ dd gGDT-KERNEL_BASE
dd 0
[section .padata]
+[global gInitialPML4]
gInitialPML4: ; Covers 256 TiB (Full 48-bit Virtual Address Space)
dd gInitialPDP - KERNEL_BASE + 3, 0 ; Identity Map Low 4Mb
times 256-1 dq 0