$line = trim($line);
if(empty($line)) continue;
- //echo $line,"\n";
- //echo intVal($line),"\n";
if( intVal($line) != 0)
$i = $line;
else
- $lSyscalls[$i++] = explode("\t", $line, 2);
- //echo $i,"\n";
+ $lSyscalls[$i++] = explode("\t", $line, 3);
}
$lMax = $i;
$j = 0;
for($i=0;$i<$lMax;$i++)
{
- $lHeader .= "\"".$lSyscalls[$i][0]."\",";
+ if(!isset($lSyscalls[$i]))
+ $lHeader .= "\"\",";
+ else
+ $lHeader .= "\"".$lSyscalls[$i][0]."\",";
$j ++;
if($j == 6) {
$lHeader .= "\n\t";
}
$lHeader .= "\"\"\n};\n#endif\n";
-//echo $lHeader;
-
$fp = fopen("include/syscalls.h", "w"); fwrite($fp, $lHeader); fclose($fp);
$fp = fopen("include/syscalls.inc.asm", "w"); fwrite($fp, $lAsmInc); fclose($fp);
endif
OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
-OBJ += heap.o drvutil.o logging.o debug.o lib.o adt.o
+OBJ += heap.o drvutil.o logging.o debug.o lib.o adt.o time.o
OBJ += messages.o modules.o syscalls.o system.o threads.o
OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS)))
OBJ += drv/vterm.o drv/proc.o drv/fifo.o drv/iocache.o drv/dma.o drv/pci.o drv/kb.o drv/vga.o
-BUILD_NUM = 2156
+BUILD_NUM = 2157
#include <acess.h>
// === MACROS ===
-#define NUM_TIMERS 8
#define TIMER_QUANTUM 100
// 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz
#define TIMER_RATE 12 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2
#define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ))
#define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ))
-// === TYPEDEFS ===
-typedef struct sTimer {
- int FiresAfter;
- void (*Callback)(void*);
- void *Argument;
-} tTimer;
+// === IMPORTS ===
+extern Sint64 giTimestamp;
+extern Uint64 giTicks;
+extern Uint64 giPartMiliseconds;
// === PROTOTYPES ===
void Time_Interrupt();
-void Timer_CallTimers();
-
-// === GLOBALS ===
-Uint64 giTicks = 0;
-Sint64 giTimestamp = 0;
-Uint64 giPartMiliseconds = 0;
-tTimer gTimers[NUM_TIMERS];
// === CODE ===
/**
giPartMiliseconds -= 0x80000000;
}
- //Log("giTimestamp = %lli", giTimestamp);
-
Timer_CallTimers();
// Make sure the RTC Fires again
}
}
#endif
-
-/**
- * \fn Sint64 now()
- * \brief Return the current timestamp
- */
-Sint64 now()
-{
- return giTimestamp;
-}
-
-/**
- * \fn void Timer_CallTimers()
- */
-void Timer_CallTimers()
-{
- int i;
- void (*callback)(void *);
-
- for(i = 0;
- i < NUM_TIMERS;
- i ++)
- {
- if(gTimers[i].Callback == NULL) continue;
- if(giTimestamp < gTimers[i].FiresAfter) continue;
- callback = gTimers[i].Callback;
- gTimers[i].Callback = NULL;
- callback(gTimers[i].Argument);
- }
-}
-
-/**
- * \fn int Time_CreateTimer(int Delta, void *Callback, void *Argument)
- */
-int Time_CreateTimer(int Delta, void *Callback, void *Argument)
-{
- int ret;
-
- if(Callback == NULL) return -1;
-
- for(ret = 0;
- ret < NUM_TIMERS;
- ret++)
- {
- if(gTimers[ret].Callback != NULL) continue;
- gTimers[ret].Callback = Callback;
- gTimers[ret].FiresAfter = giTimestamp + Delta;
- gTimers[ret].Argument = Argument;
- //Log("Callback = %p", Callback);
- //Log("Timer %i fires at %lli", ret, gTimers[ret].FiresAfter);
- return ret;
- }
- return -1;
-}
-
-/**
- * \fn void Time_RemoveTimer(int ID)
- */
-void Time_RemoveTimer(int ID)
-{
- if(ID < 0 || ID >= NUM_TIMERS) return;
- gTimers[ID].Callback = NULL;
-}
-
-/**
- * \fn void Time_Delay(int Delay)
- * \brief Delay for a small ammount of time
- */
-void Time_Delay(int Delay)
-{
- Sint64 dest = giTimestamp + Delay;
- while(dest < giTimestamp) Threads_Yield();
-}
-
-// === EXPORTS ===
-EXPORT(now);
-EXPORT(Time_CreateTimer);
-EXPORT(Time_RemoveTimer);
-EXPORT(Time_Delay);
A_OBJ = start32.ao start64.ao desctab.ao
-A_OBJ += main.o lib.o proc.o
+A_OBJ += main.o lib.o proc.o mm_virt.o mm_phys.o
--- /dev/null
+/*
+ * Acess2 x86_64 Port
+ *
+ * Physical Memory Manager
+ */
+#include <acess.h>
+//#include <mm_phys.h>
+
+enum eMMPhys_Ranges
+{
+ MM_PHYS_16BIT, // Does anything need this?
+ MM_PHYS_20BIT, // Real-Mode
+ MM_PHYS_24BIT, // ISA DMA
+ MM_PHYS_32BIT, // x86 Hardware
+ MM_PHYS_MAX, // Doesn't care
+ NUM_MM_PHYS_RANGES
+};
+
+// === GLOBALS ===
+tSpinlock glPhysicalPages;
+Uint64 *gaSuperBitmap; // 1 bit = 64 Pages
+Uint64 *gaPrimaryBitmap; // 1 bit = 1 Page
+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
+
+// === CODE ===
+void MM_InitPhys()
+{
+}
+
+/**
+ * \brief Allocate a contiguous range of physical pages with a maximum
+ * bit size of \a Bits
+ * \param Num Number of pages to allocate
+ * \param Bits Maximum size of the physical address
+ * \note If \a Bits is <= 0, any sized address is used (with preference
+ * to higher addresses)
+ */
+tPAddr MM_AllocPhysRange(int Num, int Bits)
+{
+ tPAddr addr;
+ int rangeID;
+ int nFree = 0, i;
+
+ if( Bits <= 0 ) // Speedup for the common case
+ rangeID = MM_PHYS_MAX;
+ else if( Bits > 32 )
+ rangeID = MM_PHYS_MAX;
+ else if( Bits > 24 )
+ rangeID = MM_PHYS_32BIT;
+ else if( Bits > 20 )
+ rangeID = MM_PHYS_24BIT;
+ else if( Bits > 16 )
+ rangeID = MM_PHYS_20BIT;
+ else
+ rangeID = MM_PHYS_16BIT;
+
+ LOCK(&glPhysicalPages);
+
+ // Check if the range actually has any free pages
+ while(giPhysRangeFree[rangeID] == 0 && rangeID)
+ rangeID --;
+
+ // What the? Oh, man. No free pages
+ if(giPhysRangeFree[rangeID] == 0) {
+ RELEASE(&glPhysicalPages);
+ // TODO: Page out
+ // ATM. Just Warning
+ Log_Warning("Arch",
+ "Out of memory (unable to fulfil request for %i pages), zero remaining",
+ Num
+ );
+ return 0;
+ }
+
+ // Check if there is enough in the range
+ if(giPhysRangeFree[rangeID] >= Num)
+ {
+ // Do a cheap scan, scanning upwards from the first free page in
+ // the range
+ nFree = 1;
+ addr = giPhysRangeFirst[ rangeID ];
+ while( addr < giPhysRangeLast[ rangeID ] )
+ {
+ // Check the super bitmap
+ if( gaSuperBitmap[addr >> (6+6)] == -1 ) {
+ nFree = 0;
+ addr += 1 << (6+6);
+ addr &= (1 << (6+6)) - 1;
+ continue;
+ }
+ // Check page block (64 pages)
+ if( gaPrimaryBitmap[addr >> 6] == -1) {
+ nFree = 0;
+ addr += 1 << (12+6);
+ addr &= (1 << (12+6)) - 1;
+ continue;
+ }
+ // Check individual page
+ if( gaPrimaryBitmap[addr >> 6] & (1 << (addr&63)) ) {
+ nFree = 0;
+ addr ++;
+ continue;
+ }
+ nFree ++;
+ addr ++;
+ if(nFree == Num)
+ break;
+ }
+ // If we don't find a contiguous block, nFree will not be equal
+ // to Num, so we set it to zero and do the expensive lookup.
+ if(nFree != Num) nFree = 0;
+ }
+
+ if( !nFree )
+ {
+ // Oops. ok, let's do an expensive check (scan down the list
+ // until a free range is found)
+ nFree = 1;
+ addr = giPhysRangeLast[ rangeID ];
+ RELEASE(&glPhysicalPages);
+ // TODO: Page out
+ // ATM. Just Warning
+ Log_Warning("Arch",
+ "Out of memory (unable to fulfil request for %i pages)",
+ Num
+ );
+ return 0;
+ }
+
+ // Mark pages as allocated
+ addr -= Num;
+ for( i = 0; i < Num; i++ )
+ {
+ gaPrimaryBitmap[addr>>6] |= 1 << (addr & 63);
+ if( gaPrimaryBitmap[addr>>6] == -1 )
+ gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64);
+
+ if(addr >> 32) rangeID = MM_PHYS_MAX;
+ else if(addr >> 24) rangeID = MM_PHYS_32BIT;
+ else if(addr >> 20) rangeID = MM_PHYS_24BIT;
+ else if(addr >> 16) rangeID = MM_PHYS_20BIT;
+ else if(addr >> 0) rangeID = MM_PHYS_16BIT;
+ giPhysRangeFree[ rangeID ] --;
+ }
+
+ RELEASE(&glPhysicalPages);
+ return addr;
+}
+
+/**
+ * \brief Allocate a single physical page, with no preference as to address
+ * size.
+ */
+tPAddr MM_AllocPhys(void)
+{
+ return MM_AllocPhysRange(1, -1);
+}
--- /dev/null
+/*
+ * Acess2 x86_64 Port
+ *
+ * Virtual Memory Manager
+ */
+#include <acess.h>
+#include <mm_virt.h>
+
+// === CONSTANTS ===
+#define PML4_SHIFT 39
+#define PDP_SHIFT 30
+#define PDIR_SHIFT 21
+#define PTAB_SHIFT 12
+
+#define PF_PRESENT 0x1
+#define PF_WRITE 0x2
+#define PF_USER 0x4
+#define PF_NX 0x80000000##00000000
+#define PF_COW 0x200
+#define PF_PAGED 0x400
+
+// === MACROS ===
+#define PAGETABLE(idx) (*((tPAddr*)MM_FRACTAL_BASE+(idx)))
+#define PAGEDIR(idx) PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&0x7FFFFFF))
+#define PAGEDIRPTR(idx) PAGETABLE((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF))
+#define PAGEMAPLVL4(idx) PAGETABLE((MM_FRACTAL_BASE>>30)+((idx)&0x1FF))
+
+// === GLOBALS ===
+
+// === CODE ===
+void MM_InitVirt(void)
+{
+
+}
+
+/**
+ * \brief Map a physical page to a virtual one
+ */
+int MM_Map(tVAddr VAddr, tPAddr PAddr)
+{
+ tPAddr tmp;
+
+ // Check PML4
+ if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
+ {
+ tmp = MM_AllocPhys();
+ if(!tmp) return 0;
+ PAGEMAPLVL4(VAddr >> 39) = tmp | 3;
+ memset( &PAGEDIRPTR( (VAddr>>39)<<9 ), 0, 4096 );
+ }
+
+ // Check PDP
+ if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
+ {
+ tmp = MM_AllocPhys();
+ if(!tmp) return 0;
+ PAGEDIRPTR(VAddr >> 30) = tmp | 3;
+ memset( &PAGEDIR( (VAddr>>30)<<9 ), 0, 4096 );
+ }
+
+ // Check Page Dir
+ if( !(PAGEDIR(VAddr >> 21) & 1) )
+ {
+ tmp = MM_AllocPhys();
+ if(!tmp) return 0;
+ PAGEDIR(VAddr >> 21) = tmp | 3;
+ memset( &PAGETABLE( (VAddr>>21)<<9 ), 0, 4096 );
+ }
+
+ // Check if this virtual address is already mapped
+ if( PAGETABLE(VAddr >> 12) & 1 )
+ return 0;
+
+ PAGETABLE(VAddr >> 12) = PAddr | 3;
+
+ return 1;
+}
+
+/**
+ * \brief Allocate a block of memory at the specified virtual address
+ */
+tPAddr MM_Allocate(tVAddr VAddr)
+{
+ tPAddr ret;
+
+ ret = MM_AllocPhys();
+ if(!ret) return 0;
+
+ if( !MM_Map(VAddr, ret) )
+ {
+ MM_DerefPhys(ret);
+ return 0;
+ }
+
+ return ret;
+}
+
+/**
+ * \brief Get the physical address of a virtual location
+ */
+tPAddr MM_GetPhysAddr(tVAddr Addr)
+{
+ if( !(PAGEMAPLVL4(Addr >> 39) & 1) )
+ return 0;
+ if( !(PAGEDIRPTR(Addr >> 30) & 1) )
+ return 0;
+ if( !(PAGEDIR(Addr >> 21) & 1) )
+ return 0;
+ if( !(PAGETABLE(Addr >> 12) & 1) )
+ return 0;
+
+ return (PAGETABLE(Addr >> 12) & ~0xFFF) | (Addr & 0xFFF);
+}
+
+/**
+ * \brief Sets the flags on a page
+ */
+void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
+{
+ tPAddr *ent;
+
+ // Validity Check
+ if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
+ return ;
+ if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
+ return ;
+ if( !(PAGEDIR(VAddr >> 21) & 1) )
+ return ;
+ if( !(PAGETABLE(VAddr >> 12) & 1) )
+ return ;
+
+ // Set Flags
+ ent = &PAGETABLE(VAddr >> 12);
+
+ // Read-Only
+ if( Mask & MM_PFLAG_RO )
+ {
+ if( Flags & MM_PFLAG_RO ) {
+ *ent &= ~PF_WRITE;
+ }
+ else {
+ *ent |= PF_WRITE;
+ }
+ }
+
+ // Kernel
+ if( Mask & MM_PFLAG_KERNEL )
+ {
+ if( Flags & MM_PFLAG_KERNEL ) {
+ *ent &= ~PF_USER;
+ }
+ else {
+ *ent |= PF_USER;
+ }
+ }
+
+ // Copy-On-Write
+ if( Mask & MM_PFLAG_COW )
+ {
+ if( Flags & MM_PFLAG_COW ) {
+ *ent &= ~PF_WRITE;
+ *ent |= PF_COW;
+ }
+ else {
+ *ent &= ~PF_COW;
+ *ent |= PF_WRITE;
+ }
+ }
+
+ // Execute
+ if( Mask & MM_PFLAG_EXEC )
+ {
+ if( Flags & MM_PFLAG_EXEC ) {
+ *ent &= ~PF_NX;
+ }
+ else {
+ *ent |= PF_NX;
+ }
+ }
+}
+
+Uint MM_GetFlags(tVAddr VAddr)
+{
+ tPAddr *ent;
+ Uint ret = 0;
+
+ // Validity Check
+ if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
+ return 0;
+ if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
+ return 0;
+ if( !(PAGEDIR(VAddr >> 21) & 1) )
+ return 0;
+ if( !(PAGETABLE(VAddr >> 12) & 1) )
+ return 0;
+
+ // Set Flags
+ ent = &PAGETABLE(VAddr >> 12);
+
+ // Read-Only
+ if( !(*ent & PF_WRITE) ) ret |= MM_PFLAG_RO;
+ // Kernel
+ if( !(*ent & PF_USER) ) ret |= MM_PFLAG_KERNEL;
+ // Copy-On-Write
+ if( *ent & PF_COW ) ret |= MM_PFLAG_COW;
+ // Execute
+ if( !(*ent & PF_NX) ) ret |= MM_PFLAG_EXEC;
+
+ return ret;
+}
[BITS 32]
+KERNEL_BASE equ 0xFFFF800000000000
+
[section .multiboot]
mboot:
MULTIBOOT_MAGIC equ 0x1BADB002
mov fs, ax
mov gs, ax
- jmp 0x08:start64
+ jmp 0x08:start64 - KERNEL_BASE
[section .data]
gGDT:
dd 0
[section .padata]
-gInitialPML4: ; Covers 256 TiB (Full 48-bit Virtual Address Space
- dd gInitialPDP + 3, 0 ; Identity Map Low 4Mb
+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
- dd gInitialPDP + 3, 0 ; Map Low 4Mb to kernel base
+ dd gInitialPDP - KERNEL_BASE + 3, 0 ; Map Low 4Mb to kernel base
times 256-1 dq 0
gInitialPDP: ; Covers 512 GiB
- dd gInitialPD + 3, 0
+ dd gInitialPD - KERNEL_BASE + 3, 0
times 511 dq 0
gInitialPD: ; Covers 1 GiB
- dd gInitialPT1 + 3, 0
- dd gInitialPT2 + 3, 0
+ dd gInitialPT1 - KERNEL_BASE + 3, 0
+ dd gInitialPT2 - KERNEL_BASE + 3, 0
gInitialPT1: ; Covers 2 MiB
%assign i 1
;
[bits 64]
+[global start64]
start64:
+ ; Set kernel stack
+ ; Call main
jmp $
+
+[global GetRIP]
+GetRIP:
+ mov rax, [rsp]
+ ret
* \return Physical page mapped at \a Addr
*/
extern tPAddr MM_GetPhysAddr(tVAddr Addr);
-/**
- * \brief Checks is a memory range is user accessable
- * \param VAddr Base address to check
- * \return 1 if the memory is all user-accessable, 0 otherwise
- */
-extern int MM_IsUser(tVAddr VAddr);
/**
* \brief Set the access flags on a page
* \param VAddr Virtual address of the page
* \param Mask Flags to set
*/
extern void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask);
+/**
+ * \brief Get the flags on a flag
+ * \param VAddr Virtual address of page
+ * \return Flags value of the page
+ */
+extern Uint MM_GetFlags(tVAddr VAddr);
+/**
+ * \brief Checks is a memory range is user accessable
+ * \param VAddr Base address to check
+ * \return 1 if the memory is all user-accessable, 0 otherwise
+ */
+#define MM_IsUser(VAddr) (!(MM_GetFlags((VAddr))&MM_PFLAG_KERNEL))
/**
* \brief Temporarily map a page into the address space
* \param PAddr Physical addres to map
SYS_LOADMOD, // 20 - Load a module into the kernel
SYS_GETPHYS = 32, // 32 - Get the physical address of a page
- SYS_MAP, // 33 - Map a physical address
+ SYS_MAP, // 33 -
SYS_ALLOCATE, // 34 - Allocate a page
SYS_UNMAP, // 35 - Unmap a page
SYS_PREALLOC, // 36 - Preallocate a page
%define SYS_LOADMOD 20 ; Load a module into the kernel
%define SYS_GETPHYS 32 ; Get the physical address of a page
-%define SYS_MAP 33 ; Map a physical address
+%define SYS_MAP 33 ;
%define SYS_ALLOCATE 34 ; Allocate a page
%define SYS_UNMAP 35 ; Unmap a page
%define SYS_PREALLOC 36 ; Preallocate a page
};
// -- Processes --
// --- Locks ---
-volatile int giThreadListLock = 0; ///\note NEVER use a heap function while locked
+tSpinlock glThreadListLock = 0; ///\note NEVER use a heap function while locked
// --- Current State ---
volatile int giNumActiveThreads = 0;
volatile int giTotalTickets = 0;
if(Num < 0) return;
if(Num > MAX_TICKETS) Num = MAX_TICKETS;
- LOCK( &giThreadListLock );
+ LOCK( &glThreadListLock );
giTotalTickets -= cur->NumTickets;
cur->NumTickets = Num;
giTotalTickets += Num;
//LOG("giTotalTickets = %i", giTotalTickets);
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
}
/**
LOCK( &Thread->IsLocked );
// Lock thread list
- LOCK( &giThreadListLock );
+ LOCK( &glThreadListLock );
// Get previous thread on list
prev = Threads_int_GetPrev( &gActiveThreads, Thread );
// Release spinlocks
RELEASE( &Thread->IsLocked ); // Released first so that it IS released
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
//Log("Thread %i went *hurk*", Thread->TID);
//Log_Log("Threads", "%i going to sleep", cur->TID);
// Acquire Spinlock
- LOCK( &giThreadListLock );
+ LOCK( &glThreadListLock );
// Get thread before current thread
thread = Threads_int_GetPrev( &gActiveThreads, cur );
// Don't sleep if there is a message waiting
if( cur->Messages ) {
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
return;
}
cur->Status = THREAD_STAT_SLEEPING;
// Release Spinlock
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
while(cur->Status != THREAD_STAT_ACTIVE) HALT();
}
case THREAD_STAT_ACTIVE: break;
case THREAD_STAT_SLEEPING:
//Log_Log("Threads", "Waking %i (%p) from sleeping", Thread->TID, Thread);
- LOCK( &giThreadListLock );
+ LOCK( &glThreadListLock );
prev = Threads_int_GetPrev(&gSleepingThreads, Thread);
prev->Next = Thread->Next; // Remove from sleeping queue
Thread->Next = gActiveThreads; // Add to active queue
giNumActiveThreads ++;
giTotalTickets += Thread->NumTickets;
Thread->Status = THREAD_STAT_ACTIVE;
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
break;
case THREAD_STAT_WAITING:
Warning("Thread_Wake - Waiting threads are not currently supported");
*/
void Threads_AddActive(tThread *Thread)
{
- LOCK( &giThreadListLock );
+ LOCK( &glThreadListLock );
Thread->Next = gActiveThreads;
gActiveThreads = Thread;
giNumActiveThreads ++;
giTotalTickets += Thread->NumTickets;
//Log("Threads_AddActive: giNumActiveThreads = %i, giTotalTickets = %i",
// giNumActiveThreads, giTotalTickets);
- RELEASE( &giThreadListLock );
+ RELEASE( &glThreadListLock );
}
/**