mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Ported kernel to new syscall API and started cleaning up the old one.
This commit is contained in:
parent
011e6eca95
commit
c705bf39ff
30 changed files with 375 additions and 169 deletions
|
@ -111,7 +111,7 @@ void Update()
|
|||
// Read the keyboard input from the user.
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint;
|
||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
||||
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||
{
|
||||
bool keyup = codepoint & DEPRESSED;
|
||||
if ( keyup ) { continue; }
|
||||
|
|
|
@ -185,7 +185,7 @@ void ReadInput()
|
|||
{
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint;
|
||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
||||
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||
{
|
||||
bool keyup = codepoint & DEPRESSED;
|
||||
codepoint &= ~DEPRESSED;
|
||||
|
|
|
@ -100,7 +100,7 @@ void Update()
|
|||
// Read the keyboard input from the user.
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint;
|
||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
||||
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||
{
|
||||
bool keyup = codepoint & DEPRESSED;
|
||||
if ( keyup ) { continue; }
|
||||
|
|
|
@ -16,7 +16,7 @@ int main(int argc, char* argv[])
|
|||
while (true)
|
||||
{
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint = System::Keyboard::ReceieveKeystroke(method);
|
||||
uint32_t codepoint = System::Keyboard::ReceiveKeystroke(method);
|
||||
|
||||
if ( codepoint == 0 ) { continue; }
|
||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace System
|
|||
// no character point was available at this time.
|
||||
const unsigned WAIT = 0;
|
||||
const unsigned POLL = 1;
|
||||
uint32_t ReceieveKeystroke(unsigned method);
|
||||
uint32_t ReceiveKeystroke(unsigned method);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ namespace System
|
|||
{
|
||||
namespace Keyboard
|
||||
{
|
||||
DEFN_SYSCALL1(uint32_t, SysReceieveKeystroke, 8, unsigned);
|
||||
DEFN_SYSCALL1(uint32_t, SysReceiveKeystroke, 8, unsigned);
|
||||
|
||||
uint32_t ReceieveKeystroke(unsigned method)
|
||||
uint32_t ReceiveKeystroke(unsigned method)
|
||||
{
|
||||
return SysReceieveKeystroke(method);
|
||||
return SysReceiveKeystroke(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ ifdef X86FAMILY
|
|||
x86-family/memorymanagement.o \
|
||||
$(CPU)/interrupt.o \
|
||||
$(CPU)/gdt.o \
|
||||
$(CPU)/syscall.o \
|
||||
x86-family/x86-family.o
|
||||
CPUFLAGS:=$(CPUFLAGS) -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow
|
||||
endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <libmaxsi/memory.h>
|
||||
#include "descriptor_tables.h"
|
||||
#include "panic.h"
|
||||
#include "syscall.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
|
@ -232,8 +233,7 @@ namespace Sortix
|
|||
SetGate(45, (uint32_t) irq13, 0x08, 0x8E);
|
||||
SetGate(46, (uint32_t) irq14, 0x08, 0x8E);
|
||||
SetGate(47, (uint32_t) irq15, 0x08, 0x8E);
|
||||
SetGate(128, (uint32_t) isr128, 0x08, 0x8E | 0x60); // System Calls
|
||||
SetGate(177, (uint32_t) isr177, 0x08, 0x8E | 0x60); // System Calls
|
||||
SetGate(128, (uint32_t) syscall_handler, 0x08, 0x8E | 0x60); // System Calls
|
||||
|
||||
idt_flush((uint32_t)&idt_ptr);
|
||||
#else
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "platform.h"
|
||||
#include "initrd.h"
|
||||
#include <libmaxsi/string.h>
|
||||
#include "syscall.h"
|
||||
|
||||
#include "log.h" // DEBUG
|
||||
|
||||
|
@ -37,6 +38,17 @@ namespace Sortix
|
|||
byte* initrd;
|
||||
size_t initrdsize;
|
||||
|
||||
void SysPrintPathFiles()
|
||||
{
|
||||
Header* header = (Header*) initrd;
|
||||
FileHeader* fhtbl = (FileHeader*) (initrd + sizeof(Header));
|
||||
for ( uint32_t i = 0; i < header->numfiles; i++ )
|
||||
{
|
||||
FileHeader* fileheader = &(fhtbl[i]);
|
||||
Log::PrintF("%s\n", fileheader->name);
|
||||
}
|
||||
}
|
||||
|
||||
void Init(byte* theinitrd, size_t size)
|
||||
{
|
||||
initrd = theinitrd;
|
||||
|
@ -47,6 +59,8 @@ namespace Sortix
|
|||
size_t sizeneeded = sizeof(Header) + header->numfiles * sizeof(FileHeader);
|
||||
if ( size < sizeneeded ) { PanicF("initrd.cpp: initrd is too small"); }
|
||||
// TODO: We need to do more validation here!
|
||||
|
||||
Syscall::Register(SYSCALL_PRINT_PATH_FILES, (void*) SysPrintPathFiles);
|
||||
}
|
||||
|
||||
byte* Open(const char* filepath, size_t* size)
|
||||
|
@ -65,16 +79,5 @@ namespace Sortix
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SysPrintPathFiles(CPU::InterruptRegisters* /*R*/)
|
||||
{
|
||||
Header* header = (Header*) initrd;
|
||||
FileHeader* fhtbl = (FileHeader*) (initrd + sizeof(Header));
|
||||
for ( uint32_t i = 0; i < header->numfiles; i++ )
|
||||
{
|
||||
FileHeader* fileheader = &(fhtbl[i]);
|
||||
Log::PrintF("%s\n", fileheader->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ namespace Sortix
|
|||
};
|
||||
|
||||
#ifdef SORTIX_KERNEL
|
||||
void SysPrintPathFiles(CPU::InterruptRegisters* R);
|
||||
void Init(byte* initrd, size_t size);
|
||||
byte* Open(const char* filepath, size_t* size);
|
||||
#endif
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace Sortix
|
|||
Sound::Mute();
|
||||
const char* programname = "sh";
|
||||
regs->ebx = (uint32_t) programname;
|
||||
SysExecute(regs);
|
||||
SysExecuteOld(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "vgaterminal.h"
|
||||
#include "elf.h"
|
||||
#include "initrd.h"
|
||||
#include "vga.h"
|
||||
#include "sound.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
|
@ -143,6 +145,9 @@ namespace Sortix
|
|||
BootInfo->mmap_length = sizeof(MBMMap);
|
||||
#endif
|
||||
|
||||
// Initialize system calls.
|
||||
Syscall::Init();
|
||||
|
||||
// Initialize the default terminal.
|
||||
Maxsi::Format::Callback logcallback;
|
||||
void* logpointer;
|
||||
|
@ -220,8 +225,14 @@ namespace Sortix
|
|||
// Initialize the keyboard.
|
||||
Keyboard::Init();
|
||||
|
||||
// Initialize system calls.
|
||||
Syscall::Init();
|
||||
// Initialize the VGA driver.
|
||||
VGA::Init();
|
||||
|
||||
// Initialize the sound driver.
|
||||
Sound::Init();
|
||||
|
||||
// Initialize the process system.
|
||||
Process::Init();
|
||||
|
||||
// Initialize the scheduler.
|
||||
Scheduler::Init();
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "interrupt.h"
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "syscall.h"
|
||||
|
||||
using namespace Maxsi::Keyboard;
|
||||
|
||||
|
@ -627,6 +628,16 @@ namespace Sortix
|
|||
size_t keystrokeQueueLength;
|
||||
uint32_t* keystrokeQueue;
|
||||
|
||||
uint32_t SysReceiveKeystroke()
|
||||
{
|
||||
if ( keystrokeQueueUsed == 0 ) { return 0; }
|
||||
|
||||
uint32_t codepoint = keystrokeQueue[keystrokeQueueOffset++];
|
||||
keystrokeQueueOffset %= keystrokeQueueLength;
|
||||
keystrokeQueueUsed--;
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
// Initialize variables.
|
||||
|
@ -649,6 +660,8 @@ namespace Sortix
|
|||
{
|
||||
Panic("Could not allocate keystroke buffer");
|
||||
}
|
||||
|
||||
Syscall::Register(SYSCALL_RECEIVE_KEYSTROKE, (void*) SysReceiveKeystroke);
|
||||
}
|
||||
|
||||
bool QueueKeystroke(uint32_t keystroke)
|
||||
|
@ -712,25 +725,6 @@ namespace Sortix
|
|||
while ( (CPU::InPortB(0x64) & (1<<1)) != 0 ) { } //loop Until zero
|
||||
CPU::OutPortB(0x60, LEDs);
|
||||
}
|
||||
|
||||
void SysReceieveKeystroke(CPU::InterruptRegisters* R)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
uint32_t codepoint;
|
||||
if ( keystrokeQueueUsed == 0 )
|
||||
{
|
||||
codepoint = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoint = keystrokeQueue[keystrokeQueueOffset];
|
||||
keystrokeQueueOffset++;
|
||||
keystrokeQueueOffset %= keystrokeQueueLength;
|
||||
keystrokeQueueUsed--;
|
||||
}
|
||||
R->eax = codepoint;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace Sortix
|
|||
void Init();
|
||||
void SetLEDs(uint8_t Toggle);
|
||||
void OnIRQ1(CPU::InterruptRegisters* Regs);
|
||||
void SysReceieveKeystroke(CPU::InterruptRegisters* R);
|
||||
bool QueueKeystroke(uint32_t keystroke);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <libmaxsi/string.h>
|
||||
#include <libmaxsi/memory.h>
|
||||
#include "log.h"
|
||||
#include "syscall.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
|
@ -36,10 +37,19 @@ namespace Sortix
|
|||
Maxsi::Format::Callback deviceCallback = NULL;
|
||||
void* devicePointer = NULL;
|
||||
|
||||
size_t SysPrintString(const char* str)
|
||||
{
|
||||
// TODO: Check that str is a user-readable string!
|
||||
|
||||
return Print(str);
|
||||
}
|
||||
|
||||
void Init(Maxsi::Format::Callback callback, void* user)
|
||||
{
|
||||
deviceCallback = callback;
|
||||
devicePointer = user;
|
||||
|
||||
Syscall::Register(SYSCALL_PRINT_STRING, (void*) SysPrintString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include <libmaxsi/memory.h>
|
||||
#include <libmaxsi/string.h>
|
||||
#include "process.h"
|
||||
#include "memorymanagement.h"
|
||||
#include "initrd.h"
|
||||
#include "elf.h"
|
||||
#include "syscall.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
|
@ -79,7 +83,36 @@ namespace Sortix
|
|||
segments = NULL;
|
||||
}
|
||||
|
||||
void SysExecute(CPU::InterruptRegisters* R)
|
||||
int SysExecute(const char* programname)
|
||||
{
|
||||
// TODO: Validate that filepath is a user-space readable string!
|
||||
|
||||
size_t programsize = 0;
|
||||
byte* program = InitRD::Open(programname, &programsize);
|
||||
if ( !program ) { return -1; }
|
||||
|
||||
addr_t entry = ELF::Construct(CurrentProcess(), program, programsize);
|
||||
if ( !entry )
|
||||
{
|
||||
Log::PrintF("Could not create process '%s'", programname);
|
||||
if ( String::Compare(programname, "sh") == 0 )
|
||||
{
|
||||
Panic("Couldn't create the shell process");
|
||||
}
|
||||
|
||||
return SysExecute("sh");
|
||||
}
|
||||
|
||||
// This is a hacky way to set up the thread!
|
||||
CPU::InterruptRegisters* regs = Syscall::InterruptRegs();
|
||||
regs->eip = entry;
|
||||
regs->useresp = 0x80000000UL;
|
||||
regs->ebp = 0x80000000UL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SysExecuteOld(CPU::InterruptRegisters* R)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
const char* programname = (const char*) R->ebx;
|
||||
|
@ -99,4 +132,9 @@ namespace Sortix
|
|||
R->ebp = 0x80000000UL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Process::Init()
|
||||
{
|
||||
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace Sortix
|
|||
Process(addr_t addrspace);
|
||||
~Process();
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
|
||||
private:
|
||||
addr_t _addrspace;
|
||||
|
||||
|
@ -79,7 +82,7 @@ namespace Sortix
|
|||
|
||||
Process* CurrentProcess();
|
||||
|
||||
void SysExecute(CPU::InterruptRegisters* R);
|
||||
void SysExecuteOld(CPU::InterruptRegisters* R);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "multiboot.h"
|
||||
#include "memorymanagement.h"
|
||||
#include "descriptor_tables.h"
|
||||
#include "syscall.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
|
@ -53,6 +54,9 @@ namespace Sortix
|
|||
Thread* firstUnrunnableThread;
|
||||
Thread* firstSleeping;
|
||||
size_t AllocatedThreadId;
|
||||
|
||||
void SysSleep(size_t secs);
|
||||
void SysUSleep(size_t usecs);
|
||||
}
|
||||
|
||||
Thread::Thread(Process* process, size_t id, addr_t stack, size_t stackLength)
|
||||
|
@ -229,6 +233,9 @@ namespace Sortix
|
|||
Memory::InvalidatePage(KernelStackPage);
|
||||
|
||||
GDT::SetKernelStack((size_t*) (MapTo+4096));
|
||||
|
||||
Syscall::Register(SYSCALL_SLEEP, (void*) SysSleep);
|
||||
Syscall::Register(SYSCALL_USLEEP, (void*) SysUSleep);
|
||||
}
|
||||
|
||||
// Once the init process is spawned and IRQ0 is enabled, this process
|
||||
|
@ -325,7 +332,7 @@ namespace Sortix
|
|||
Sound::Mute();
|
||||
const char* programname = "sh";
|
||||
R->ebx = (uint32_t) programname;
|
||||
SysExecute(R);
|
||||
SysExecuteOld(R);
|
||||
sigintpending = false;
|
||||
Log::Print("^C\n");
|
||||
#else
|
||||
|
@ -485,32 +492,24 @@ namespace Sortix
|
|||
//Log::PrintF("<ExitedThread nextthread=\"%p\"/>\n", CurrentThread());
|
||||
}
|
||||
|
||||
void SysSleep(CPU::InterruptRegisters* R)
|
||||
void SysSleep(size_t secs)
|
||||
{
|
||||
//Log::PrintF("<SysSleep>\n");
|
||||
#ifdef PLATFORM_X86
|
||||
intmax_t TimeToSleep = ((uintmax_t) R->ebx) * 1000ULL;
|
||||
intmax_t TimeToSleep = ((uintmax_t) secs) * 1000ULL;
|
||||
if ( TimeToSleep == 0 ) { return; }
|
||||
Syscall::Incomplete();
|
||||
CurrentThread()->Sleep(TimeToSleep);
|
||||
Switch(R, 0);
|
||||
Switch(Syscall::InterruptRegs(), 0);
|
||||
//Log::PrintF("</SysSleep>\n");
|
||||
#else
|
||||
#warning "This syscall is not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SysUSleep(CPU::InterruptRegisters* R)
|
||||
void SysUSleep(size_t usecs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
intmax_t TimeToSleep = ((uintmax_t) R->ebx) / 1000ULL;
|
||||
intmax_t TimeToSleep = ((uintmax_t) usecs) / 1000ULL;
|
||||
if ( TimeToSleep == 0 ) { return; }
|
||||
Syscall::Incomplete();
|
||||
CurrentThread()->Sleep(TimeToSleep);
|
||||
Switch(R, 0);
|
||||
#else
|
||||
#warning "This syscall is not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
Switch(Syscall::InterruptRegs(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,8 +109,6 @@ namespace Sortix
|
|||
// System Calls.
|
||||
void SysCreateThread(CPU::InterruptRegisters* R);
|
||||
void SysExitThread(CPU::InterruptRegisters* R);
|
||||
void SysSleep(CPU::InterruptRegisters* R);
|
||||
void SysUSleep(CPU::InterruptRegisters* R);
|
||||
}
|
||||
|
||||
// Scheduling
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "sound.h"
|
||||
#include "syscall.h"
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
|
@ -53,12 +54,14 @@ namespace Sortix
|
|||
}
|
||||
}
|
||||
|
||||
void SysSetFrequency(CPU::InterruptRegisters* R)
|
||||
void SysSetFrequency(unsigned frequency)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
unsigned frequency = R->ebx;
|
||||
if ( frequency == 0 ) { Mute(); } else { Play(frequency); }
|
||||
#endif
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
Syscall::Register(SYSCALL_SET_FREQUENCY, (void*) SysSetFrequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace Sortix
|
|||
{
|
||||
namespace Sound
|
||||
{
|
||||
void Init();
|
||||
void Mute();
|
||||
void Play(nat Frequency);
|
||||
void SysSetFrequency(CPU::InterruptRegisters* R);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,77 +24,68 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "syscall.h"
|
||||
#include "scheduler.h"
|
||||
#include "interrupt.h"
|
||||
#include "log.h"
|
||||
#include "syscallnum.h"
|
||||
#include "panic.h"
|
||||
#include "vga.h"
|
||||
#include "keyboard.h"
|
||||
#include "sound.h"
|
||||
#include "process.h"
|
||||
#include "initrd.h"
|
||||
#include "thread.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
#include "log.h" // DEBUG
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace Syscall
|
||||
{
|
||||
void SysStdOutPrint(CPU::InterruptRegisters* R)
|
||||
extern "C"
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
// TODO: Validate our input pointer is legal for the current thread/process!
|
||||
R->eax = (uint32_t) Log::Print((const char*) R->ebx);
|
||||
#else
|
||||
#warning "This syscall is not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
CPU::SyscallRegisters* syscall_state_ptr;
|
||||
int system_was_incomplete;
|
||||
size_t SYSCALL_MAX = SYSCALL_MAX_NUM;
|
||||
void* syscall_list[SYSCALL_MAX_NUM];
|
||||
}
|
||||
|
||||
const size_t NumSyscalls = 12;
|
||||
const Syscall Syscalls[NumSyscalls] =
|
||||
int BadSyscall()
|
||||
{
|
||||
&Scheduler::SysCreateThread,
|
||||
&Scheduler::SysExitThread,
|
||||
&Scheduler::SysSleep,
|
||||
&Scheduler::SysUSleep,
|
||||
&SysStdOutPrint,
|
||||
&VGA::SysCreateFrame,
|
||||
&VGA::SysChangeFrame,
|
||||
&VGA::SysDeleteFrame,
|
||||
&Keyboard::SysReceieveKeystroke,
|
||||
&Sound::SysSetFrequency,
|
||||
&SysExecute,
|
||||
&InitRD::SysPrintPathFiles,
|
||||
};
|
||||
// TODO: Send signal, set errno, or crash/abort process?
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
Interrupt::RegisterHandler(0x80, &OnCall);
|
||||
for ( size_t i = 0; i < SYSCALL_MAX; i++ )
|
||||
{
|
||||
syscall_list[i] = (void*) BadSyscall;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCall(CPU::InterruptRegisters* registers)
|
||||
void Register(size_t index, void* funcptr)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
size_t callId = registers->eax;
|
||||
if ( SYSCALL_MAX <= index )
|
||||
{
|
||||
PanicF("attempted to register syscall 0x%p to index %zu, but "
|
||||
"SYSCALL_MAX = %zu", funcptr, index, SYSCALL_MAX);
|
||||
}
|
||||
|
||||
// Make sure the requested syscall exists.
|
||||
if ( callId >= NumSyscalls ) { return; }
|
||||
syscall_list[index] = funcptr;
|
||||
}
|
||||
|
||||
#ifdef USING_OLD_SYSCALL
|
||||
Syscalls[registers->eax](registers);
|
||||
#else
|
||||
Thread* thread = CurrentThread();
|
||||
void Incomplete()
|
||||
{
|
||||
system_was_incomplete = 1;
|
||||
|
||||
thread->BeginSyscall(registers);
|
||||
CPU::InterruptRegisters* regs = InterruptRegs();
|
||||
CurrentThread()->SaveRegisters(regs);
|
||||
// TODO: Make the thread blocking if not already.
|
||||
Scheduler::Switch(regs, 0);
|
||||
}
|
||||
|
||||
Syscalls[registers->eax](thread);
|
||||
CPU::InterruptRegisters* InterruptRegs()
|
||||
{
|
||||
return (CPU::InterruptRegisters*) syscall_state_ptr;
|
||||
}
|
||||
|
||||
thread->OnSysReturn();
|
||||
#endif
|
||||
|
||||
#else
|
||||
#warning "System calls are not available on this platform"
|
||||
while(true);
|
||||
#endif
|
||||
CPU::SyscallRegisters* SyscallRegs()
|
||||
{
|
||||
return syscall_state_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,30 +25,29 @@
|
|||
#ifndef SORTIX_SYSCALL_H
|
||||
#define SORTIX_SYSCALL_H
|
||||
|
||||
#include "scheduler.h"
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
#define SYSPARAM __attribute__ ((aligned (4)));
|
||||
#elif defined(PLATFORM_X64)
|
||||
#define SYSPARAM __attribute__ ((aligned (8)));
|
||||
#endif
|
||||
|
||||
#define USING_OLD_SYSCALL
|
||||
#include "syscallnum.h"
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace Syscall
|
||||
{
|
||||
void Init();
|
||||
void OnCall(CPU::InterruptRegisters* R);
|
||||
void Register(size_t index, void* funcptr);
|
||||
|
||||
#ifdef USING_OLD_SYSCALL
|
||||
typedef void (*Syscall)(CPU::InterruptRegisters* r);
|
||||
#else
|
||||
typedef void (*Syscall)(Thread* R);
|
||||
#endif
|
||||
// Aborts the current system call such that the current thread is marked
|
||||
// as blocking, and control is transferred to the next runnable thread.
|
||||
// This allows the thread to wait for an condition that makes the thread
|
||||
// runnable again and stores the return value in the proper register.
|
||||
// Once called, you may safely return from the system call in good faith
|
||||
// that its return value shall be discarded.
|
||||
void Incomplete();
|
||||
|
||||
CPU::InterruptRegisters* InterruptRegs();
|
||||
CPU::SyscallRegisters* SyscallRegs();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void syscall_handler();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
43
sortix/syscallnum.h
Normal file
43
sortix/syscallnum.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
syscallnum.h
|
||||
Stores numerical constants for each available system call on this kernel.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_SYSCALLNUM_H
|
||||
#define SORTIX_SYSCALLNUM_H
|
||||
|
||||
#define SYSCALL_BAD_SYSCALL 0
|
||||
#define SYSCALL_EXIT 1
|
||||
#define SYSCALL_SLEEP 2
|
||||
#define SYSCALL_USLEEP 3
|
||||
#define SYSCALL_PRINT_STRING 4
|
||||
#define SYSCALL_CREATE_FRAME 5
|
||||
#define SYSCALL_CHANGE_FRAME 6
|
||||
#define SYSCALL_DELETE_FRAME 7
|
||||
#define SYSCALL_RECEIVE_KEYSTROKE 8
|
||||
#define SYSCALL_SET_FREQUENCY 9
|
||||
#define SYSCALL_EXEC 10
|
||||
#define SYSCALL_PRINT_PATH_FILES 11
|
||||
#define SYSCALL_MAX_NUM 12 /* index of highest constant + 1 */
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include "vga.h"
|
||||
#include "memorymanagement.h"
|
||||
#include "scheduler.h"
|
||||
#include "syscall.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
|
@ -34,6 +35,10 @@ namespace Sortix
|
|||
{
|
||||
namespace VGA
|
||||
{
|
||||
addr_t SysCreateFrame();
|
||||
int SysChangeFrame(int fd);
|
||||
int SysDeleteFrame(int fd);
|
||||
|
||||
uint16_t* const vga = (uint16_t* const) 0xB8000;
|
||||
const int width = 80;
|
||||
const int height = 80;
|
||||
|
@ -43,6 +48,10 @@ namespace Sortix
|
|||
void Init()
|
||||
{
|
||||
currentframe = NULL;
|
||||
|
||||
Syscall::Register(SYSCALL_CREATE_FRAME, (void*) SysCreateFrame);
|
||||
Syscall::Register(SYSCALL_CHANGE_FRAME, (void*) SysChangeFrame);
|
||||
Syscall::Register(SYSCALL_DELETE_FRAME, (void*) SysDeleteFrame);
|
||||
}
|
||||
|
||||
// Changes the position of the hardware cursor.
|
||||
|
@ -60,11 +69,10 @@ namespace Sortix
|
|||
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
||||
}
|
||||
|
||||
void SysCreateFrame(CPU::InterruptRegisters* R)
|
||||
addr_t SysCreateFrame()
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
addr_t page = Page::Get();
|
||||
if ( page == NULL ) { R->eax = 0; return; }
|
||||
if ( !page ) { return 0; }
|
||||
|
||||
Process* process = CurrentProcess();
|
||||
addr_t mapto = Page::AlignUp(process->_endcodesection);
|
||||
|
@ -74,7 +82,7 @@ namespace Sortix
|
|||
|
||||
if ( !Memory::MapUser(page, mapto) )
|
||||
{
|
||||
Page::Put(page); R->eax = 0; return;
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
Maxsi::Memory::Set(userframe, 0, sizeof(UserFrame));
|
||||
|
@ -83,7 +91,7 @@ namespace Sortix
|
|||
if ( frame == NULL )
|
||||
{
|
||||
Memory::UnmapUser(mapto);
|
||||
Page::Put(page); R->eax = 0; return;
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
int fd = process->descriptors.Allocate(frame);
|
||||
|
@ -91,7 +99,7 @@ namespace Sortix
|
|||
{
|
||||
delete frame;
|
||||
Memory::UnmapUser(mapto);
|
||||
Page::Put(page); R->eax = 0; return;
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
userframe->fd = fd;
|
||||
|
@ -102,20 +110,16 @@ namespace Sortix
|
|||
|
||||
process->_endcodesection = mapto + 0x1000UL;
|
||||
|
||||
R->eax = mapto;
|
||||
#endif
|
||||
return mapto;
|
||||
}
|
||||
|
||||
void SysChangeFrame(CPU::InterruptRegisters* R)
|
||||
int SysChangeFrame(int fd)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
int fd = (int) R->ebx;
|
||||
|
||||
Process* process = CurrentProcess();
|
||||
Device* device = process->descriptors.Get(fd);
|
||||
if ( device == NULL ) { R->eax = -1; return; }
|
||||
if ( !device ) { return -1; }
|
||||
|
||||
if ( !device->IsType(Device::VGABUFFER) ) { R->eax = -2; return; }
|
||||
if ( !device->IsType(Device::VGABUFFER) ) { return -2; }
|
||||
|
||||
DevVGAFrame* frame = (DevVGAFrame*) device;
|
||||
|
||||
|
@ -126,10 +130,8 @@ namespace Sortix
|
|||
|
||||
// TODO: Check if userframe is actually user-space writable!
|
||||
|
||||
//Log::PrintF("changeframe: fd = %u, frame = 0x%p, currentframe = 0x%p, userframe = 0x%p\n", fd, frame, currentframe, frame->userframe); while(true);
|
||||
|
||||
// Check if we need to do anything.
|
||||
if ( frame == currentframe ) { R->eax = 0; return; }
|
||||
if ( frame == currentframe ) { return 0; }
|
||||
|
||||
// If there is already a currently used frame? If so, swap it from
|
||||
// the VGA memory and back to the RAM. This should be done
|
||||
|
@ -173,22 +175,20 @@ namespace Sortix
|
|||
frame->onscreen = true;
|
||||
currentframe = frame;
|
||||
SetCursor(width, height-1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SysDeleteFrame(CPU::InterruptRegisters* R)
|
||||
int SysDeleteFrame(int fd)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
int fd = (int) R->ebx;
|
||||
|
||||
Process* process = CurrentProcess();
|
||||
Device* device = process->descriptors.Get(fd);
|
||||
process->descriptors.Free(fd);
|
||||
|
||||
if ( device == NULL ) { R->eax = -1; return; }
|
||||
if ( !device->Close() ) { R->eax = -1; return; }
|
||||
R->eax = 0;
|
||||
#endif
|
||||
if ( device == NULL ) { return -1; }
|
||||
if ( !device->Close() ) { return -1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,11 +67,6 @@ namespace Sortix
|
|||
|
||||
void Init();
|
||||
void SetCursor(nat x, nat y);
|
||||
|
||||
// System Calls.
|
||||
void SysCreateFrame(CPU::InterruptRegisters* R);
|
||||
void SysChangeFrame(CPU::InterruptRegisters* R);
|
||||
void SysDeleteFrame(CPU::InterruptRegisters* R);
|
||||
}
|
||||
|
||||
class DevVGAFrame : public Device
|
||||
|
|
111
sortix/x86/syscall.s
Normal file
111
sortix/x86/syscall.s
Normal file
|
@ -0,0 +1,111 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
syscall.s
|
||||
An assembly stub that acts as glue for system calls.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
.global syscall_handler
|
||||
|
||||
.section .text
|
||||
.type syscall_handler, @function
|
||||
syscall_handler:
|
||||
cli
|
||||
|
||||
# Compabillity with InterruptRegisters.
|
||||
pushl $0x0
|
||||
pushl $0x80
|
||||
|
||||
# Push eax, ecx, edx, ebx, esp, ebp, esi, edi, cr2
|
||||
pushal
|
||||
|
||||
# Push the user-space data segment.
|
||||
movl %ds, %ebp
|
||||
pushl %ebp
|
||||
|
||||
# Load the kernel data segment.
|
||||
movw $0x10, %bp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
# Compabillity with InterruptRegisters.
|
||||
movl %cr2, %ebp
|
||||
pushl %ebp
|
||||
|
||||
# Store the state structure's pointer so the call can modify it if needed.
|
||||
mov %esp, syscall_state_ptr
|
||||
|
||||
# By default, assume the system call was complete.
|
||||
movl $0, system_was_incomplete
|
||||
|
||||
# Make sure the requested system call is valid.
|
||||
cmp SYSCALL_MAX, %eax
|
||||
jl valid_eax
|
||||
xorl %eax, %eax
|
||||
|
||||
valid_eax:
|
||||
# Read a system call function pointer.
|
||||
xorl %ebp, %ebp
|
||||
movl syscall_list(%ebp,%eax,4), %eax
|
||||
|
||||
# Give the system call function the values given by user-space.
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
|
||||
# Call the system call.
|
||||
calll *%eax
|
||||
|
||||
# Clean up after the call.
|
||||
addl $20, %esp
|
||||
|
||||
# Test if the system call was incomplete
|
||||
movl system_was_incomplete, %ebx
|
||||
testl %ebx, %ebx
|
||||
|
||||
# If the system call was incomplete, the value in %eax is meaningless.
|
||||
jg return_to_userspace
|
||||
|
||||
# The system call was completed, so store the return value.
|
||||
movl %eax, 36(%esp)
|
||||
|
||||
return_to_userspace:
|
||||
# Compabillity with InterruptRegisters.
|
||||
addl $4, %esp
|
||||
|
||||
# Restore the user-space data segment.
|
||||
popl %ebp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
popal
|
||||
|
||||
# Compabillity with InterruptRegisters.
|
||||
addl $8, %esp
|
||||
|
||||
# Return to user-space.
|
||||
iretl
|
||||
|
|
@ -39,6 +39,15 @@ namespace Sortix
|
|||
uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
|
||||
uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically.
|
||||
};
|
||||
|
||||
struct SyscallRegisters
|
||||
{
|
||||
uint32_t cr2; // For compabillity with below, may be removed soon.
|
||||
uint32_t ds;
|
||||
uint32_t di, si, bp, trash, b, d, c, a;
|
||||
uint32_t int_no, err_code; // Also compabillity.
|
||||
uint32_t ip, cs, flags, sp, ss;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ int main(int argc, char* argv[])
|
|||
while (true)
|
||||
{
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint = System::Keyboard::ReceieveKeystroke(method);
|
||||
uint32_t codepoint = System::Keyboard::ReceiveKeystroke(method);
|
||||
|
||||
if ( codepoint == 0 ) { continue; }
|
||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||
|
|
|
@ -15,7 +15,7 @@ void command()
|
|||
while (true)
|
||||
{
|
||||
unsigned method = System::Keyboard::POLL;
|
||||
uint32_t codepoint = System::Keyboard::ReceieveKeystroke(method);
|
||||
uint32_t codepoint = System::Keyboard::ReceiveKeystroke(method);
|
||||
|
||||
if ( codepoint == 0 ) { continue; }
|
||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||
|
|
Loading…
Reference in a new issue