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.
|
// Read the keyboard input from the user.
|
||||||
unsigned method = System::Keyboard::POLL;
|
unsigned method = System::Keyboard::POLL;
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||||
{
|
{
|
||||||
bool keyup = codepoint & DEPRESSED;
|
bool keyup = codepoint & DEPRESSED;
|
||||||
if ( keyup ) { continue; }
|
if ( keyup ) { continue; }
|
||||||
|
|
|
@ -185,7 +185,7 @@ void ReadInput()
|
||||||
{
|
{
|
||||||
unsigned method = System::Keyboard::POLL;
|
unsigned method = System::Keyboard::POLL;
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||||
{
|
{
|
||||||
bool keyup = codepoint & DEPRESSED;
|
bool keyup = codepoint & DEPRESSED;
|
||||||
codepoint &= ~DEPRESSED;
|
codepoint &= ~DEPRESSED;
|
||||||
|
|
|
@ -100,7 +100,7 @@ void Update()
|
||||||
// Read the keyboard input from the user.
|
// Read the keyboard input from the user.
|
||||||
unsigned method = System::Keyboard::POLL;
|
unsigned method = System::Keyboard::POLL;
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
while ( (codepoint = System::Keyboard::ReceieveKeystroke(method) ) != 0 )
|
while ( (codepoint = System::Keyboard::ReceiveKeystroke(method) ) != 0 )
|
||||||
{
|
{
|
||||||
bool keyup = codepoint & DEPRESSED;
|
bool keyup = codepoint & DEPRESSED;
|
||||||
if ( keyup ) { continue; }
|
if ( keyup ) { continue; }
|
||||||
|
|
|
@ -16,7 +16,7 @@ int main(int argc, char* argv[])
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned method = System::Keyboard::POLL;
|
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 == 0 ) { continue; }
|
||||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace System
|
||||||
// no character point was available at this time.
|
// no character point was available at this time.
|
||||||
const unsigned WAIT = 0;
|
const unsigned WAIT = 0;
|
||||||
const unsigned POLL = 1;
|
const unsigned POLL = 1;
|
||||||
uint32_t ReceieveKeystroke(unsigned method);
|
uint32_t ReceiveKeystroke(unsigned method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,11 @@ namespace System
|
||||||
{
|
{
|
||||||
namespace Keyboard
|
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 \
|
x86-family/memorymanagement.o \
|
||||||
$(CPU)/interrupt.o \
|
$(CPU)/interrupt.o \
|
||||||
$(CPU)/gdt.o \
|
$(CPU)/gdt.o \
|
||||||
|
$(CPU)/syscall.o \
|
||||||
x86-family/x86-family.o
|
x86-family/x86-family.o
|
||||||
CPUFLAGS:=$(CPUFLAGS) -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow
|
CPUFLAGS:=$(CPUFLAGS) -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <libmaxsi/memory.h>
|
#include <libmaxsi/memory.h>
|
||||||
#include "descriptor_tables.h"
|
#include "descriptor_tables.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
using namespace Maxsi;
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
@ -232,8 +233,7 @@ namespace Sortix
|
||||||
SetGate(45, (uint32_t) irq13, 0x08, 0x8E);
|
SetGate(45, (uint32_t) irq13, 0x08, 0x8E);
|
||||||
SetGate(46, (uint32_t) irq14, 0x08, 0x8E);
|
SetGate(46, (uint32_t) irq14, 0x08, 0x8E);
|
||||||
SetGate(47, (uint32_t) irq15, 0x08, 0x8E);
|
SetGate(47, (uint32_t) irq15, 0x08, 0x8E);
|
||||||
SetGate(128, (uint32_t) isr128, 0x08, 0x8E | 0x60); // System Calls
|
SetGate(128, (uint32_t) syscall_handler, 0x08, 0x8E | 0x60); // System Calls
|
||||||
SetGate(177, (uint32_t) isr177, 0x08, 0x8E | 0x60); // System Calls
|
|
||||||
|
|
||||||
idt_flush((uint32_t)&idt_ptr);
|
idt_flush((uint32_t)&idt_ptr);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
#include <libmaxsi/string.h>
|
#include <libmaxsi/string.h>
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
#include "log.h" // DEBUG
|
#include "log.h" // DEBUG
|
||||||
|
|
||||||
|
@ -37,6 +38,17 @@ namespace Sortix
|
||||||
byte* initrd;
|
byte* initrd;
|
||||||
size_t initrdsize;
|
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)
|
void Init(byte* theinitrd, size_t size)
|
||||||
{
|
{
|
||||||
initrd = theinitrd;
|
initrd = theinitrd;
|
||||||
|
@ -47,6 +59,8 @@ namespace Sortix
|
||||||
size_t sizeneeded = sizeof(Header) + header->numfiles * sizeof(FileHeader);
|
size_t sizeneeded = sizeof(Header) + header->numfiles * sizeof(FileHeader);
|
||||||
if ( size < sizeneeded ) { PanicF("initrd.cpp: initrd is too small"); }
|
if ( size < sizeneeded ) { PanicF("initrd.cpp: initrd is too small"); }
|
||||||
// TODO: We need to do more validation here!
|
// TODO: We need to do more validation here!
|
||||||
|
|
||||||
|
Syscall::Register(SYSCALL_PRINT_PATH_FILES, (void*) SysPrintPathFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte* Open(const char* filepath, size_t* size)
|
byte* Open(const char* filepath, size_t* size)
|
||||||
|
@ -65,16 +79,5 @@ namespace Sortix
|
||||||
|
|
||||||
return NULL;
|
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
|
#ifdef SORTIX_KERNEL
|
||||||
void SysPrintPathFiles(CPU::InterruptRegisters* R);
|
|
||||||
void Init(byte* initrd, size_t size);
|
void Init(byte* initrd, size_t size);
|
||||||
byte* Open(const char* filepath, size_t* size);
|
byte* Open(const char* filepath, size_t* size);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Sortix
|
||||||
Sound::Mute();
|
Sound::Mute();
|
||||||
const char* programname = "sh";
|
const char* programname = "sh";
|
||||||
regs->ebx = (uint32_t) programname;
|
regs->ebx = (uint32_t) programname;
|
||||||
SysExecute(regs);
|
SysExecuteOld(regs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
#include "vgaterminal.h"
|
#include "vgaterminal.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
|
#include "vga.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
using namespace Maxsi;
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
@ -143,6 +145,9 @@ namespace Sortix
|
||||||
BootInfo->mmap_length = sizeof(MBMMap);
|
BootInfo->mmap_length = sizeof(MBMMap);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Initialize system calls.
|
||||||
|
Syscall::Init();
|
||||||
|
|
||||||
// Initialize the default terminal.
|
// Initialize the default terminal.
|
||||||
Maxsi::Format::Callback logcallback;
|
Maxsi::Format::Callback logcallback;
|
||||||
void* logpointer;
|
void* logpointer;
|
||||||
|
@ -220,8 +225,14 @@ namespace Sortix
|
||||||
// Initialize the keyboard.
|
// Initialize the keyboard.
|
||||||
Keyboard::Init();
|
Keyboard::Init();
|
||||||
|
|
||||||
// Initialize system calls.
|
// Initialize the VGA driver.
|
||||||
Syscall::Init();
|
VGA::Init();
|
||||||
|
|
||||||
|
// Initialize the sound driver.
|
||||||
|
Sound::Init();
|
||||||
|
|
||||||
|
// Initialize the process system.
|
||||||
|
Process::Init();
|
||||||
|
|
||||||
// Initialize the scheduler.
|
// Initialize the scheduler.
|
||||||
Scheduler::Init();
|
Scheduler::Init();
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
using namespace Maxsi::Keyboard;
|
using namespace Maxsi::Keyboard;
|
||||||
|
|
||||||
|
@ -627,6 +628,16 @@ namespace Sortix
|
||||||
size_t keystrokeQueueLength;
|
size_t keystrokeQueueLength;
|
||||||
uint32_t* keystrokeQueue;
|
uint32_t* keystrokeQueue;
|
||||||
|
|
||||||
|
uint32_t SysReceiveKeystroke()
|
||||||
|
{
|
||||||
|
if ( keystrokeQueueUsed == 0 ) { return 0; }
|
||||||
|
|
||||||
|
uint32_t codepoint = keystrokeQueue[keystrokeQueueOffset++];
|
||||||
|
keystrokeQueueOffset %= keystrokeQueueLength;
|
||||||
|
keystrokeQueueUsed--;
|
||||||
|
return codepoint;
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
// Initialize variables.
|
// Initialize variables.
|
||||||
|
@ -649,6 +660,8 @@ namespace Sortix
|
||||||
{
|
{
|
||||||
Panic("Could not allocate keystroke buffer");
|
Panic("Could not allocate keystroke buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Syscall::Register(SYSCALL_RECEIVE_KEYSTROKE, (void*) SysReceiveKeystroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueueKeystroke(uint32_t keystroke)
|
bool QueueKeystroke(uint32_t keystroke)
|
||||||
|
@ -712,25 +725,6 @@ namespace Sortix
|
||||||
while ( (CPU::InPortB(0x64) & (1<<1)) != 0 ) { } //loop Until zero
|
while ( (CPU::InPortB(0x64) & (1<<1)) != 0 ) { } //loop Until zero
|
||||||
CPU::OutPortB(0x60, LEDs);
|
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 Init();
|
||||||
void SetLEDs(uint8_t Toggle);
|
void SetLEDs(uint8_t Toggle);
|
||||||
void OnIRQ1(CPU::InterruptRegisters* Regs);
|
void OnIRQ1(CPU::InterruptRegisters* Regs);
|
||||||
void SysReceieveKeystroke(CPU::InterruptRegisters* R);
|
|
||||||
bool QueueKeystroke(uint32_t keystroke);
|
bool QueueKeystroke(uint32_t keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <libmaxsi/string.h>
|
#include <libmaxsi/string.h>
|
||||||
#include <libmaxsi/memory.h>
|
#include <libmaxsi/memory.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
using namespace Maxsi;
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
@ -36,10 +37,19 @@ namespace Sortix
|
||||||
Maxsi::Format::Callback deviceCallback = NULL;
|
Maxsi::Format::Callback deviceCallback = NULL;
|
||||||
void* devicePointer = 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)
|
void Init(Maxsi::Format::Callback callback, void* user)
|
||||||
{
|
{
|
||||||
deviceCallback = callback;
|
deviceCallback = callback;
|
||||||
devicePointer = user;
|
devicePointer = user;
|
||||||
|
|
||||||
|
Syscall::Register(SYSCALL_PRINT_STRING, (void*) SysPrintString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,14 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include <libmaxsi/memory.h>
|
#include <libmaxsi/memory.h>
|
||||||
|
#include <libmaxsi/string.h>
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
#include "initrd.h"
|
#include "initrd.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
using namespace Maxsi;
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
|
@ -79,7 +83,36 @@ namespace Sortix
|
||||||
segments = NULL;
|
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
|
#ifdef PLATFORM_X86
|
||||||
const char* programname = (const char*) R->ebx;
|
const char* programname = (const char*) R->ebx;
|
||||||
|
@ -99,4 +132,9 @@ namespace Sortix
|
||||||
R->ebp = 0x80000000UL;
|
R->ebp = 0x80000000UL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::Init()
|
||||||
|
{
|
||||||
|
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,9 @@ namespace Sortix
|
||||||
Process(addr_t addrspace);
|
Process(addr_t addrspace);
|
||||||
~Process();
|
~Process();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
addr_t _addrspace;
|
addr_t _addrspace;
|
||||||
|
|
||||||
|
@ -79,7 +82,7 @@ namespace Sortix
|
||||||
|
|
||||||
Process* CurrentProcess();
|
Process* CurrentProcess();
|
||||||
|
|
||||||
void SysExecute(CPU::InterruptRegisters* R);
|
void SysExecuteOld(CPU::InterruptRegisters* R);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
#include "descriptor_tables.h"
|
#include "descriptor_tables.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
@ -53,6 +54,9 @@ namespace Sortix
|
||||||
Thread* firstUnrunnableThread;
|
Thread* firstUnrunnableThread;
|
||||||
Thread* firstSleeping;
|
Thread* firstSleeping;
|
||||||
size_t AllocatedThreadId;
|
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)
|
Thread::Thread(Process* process, size_t id, addr_t stack, size_t stackLength)
|
||||||
|
@ -229,6 +233,9 @@ namespace Sortix
|
||||||
Memory::InvalidatePage(KernelStackPage);
|
Memory::InvalidatePage(KernelStackPage);
|
||||||
|
|
||||||
GDT::SetKernelStack((size_t*) (MapTo+4096));
|
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
|
// Once the init process is spawned and IRQ0 is enabled, this process
|
||||||
|
@ -325,7 +332,7 @@ namespace Sortix
|
||||||
Sound::Mute();
|
Sound::Mute();
|
||||||
const char* programname = "sh";
|
const char* programname = "sh";
|
||||||
R->ebx = (uint32_t) programname;
|
R->ebx = (uint32_t) programname;
|
||||||
SysExecute(R);
|
SysExecuteOld(R);
|
||||||
sigintpending = false;
|
sigintpending = false;
|
||||||
Log::Print("^C\n");
|
Log::Print("^C\n");
|
||||||
#else
|
#else
|
||||||
|
@ -485,32 +492,24 @@ namespace Sortix
|
||||||
//Log::PrintF("<ExitedThread nextthread=\"%p\"/>\n", CurrentThread());
|
//Log::PrintF("<ExitedThread nextthread=\"%p\"/>\n", CurrentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysSleep(CPU::InterruptRegisters* R)
|
void SysSleep(size_t secs)
|
||||||
{
|
{
|
||||||
//Log::PrintF("<SysSleep>\n");
|
//Log::PrintF("<SysSleep>\n");
|
||||||
#ifdef PLATFORM_X86
|
intmax_t TimeToSleep = ((uintmax_t) secs) * 1000ULL;
|
||||||
intmax_t TimeToSleep = ((uintmax_t) R->ebx) * 1000ULL;
|
|
||||||
if ( TimeToSleep == 0 ) { return; }
|
if ( TimeToSleep == 0 ) { return; }
|
||||||
|
Syscall::Incomplete();
|
||||||
CurrentThread()->Sleep(TimeToSleep);
|
CurrentThread()->Sleep(TimeToSleep);
|
||||||
Switch(R, 0);
|
Switch(Syscall::InterruptRegs(), 0);
|
||||||
//Log::PrintF("</SysSleep>\n");
|
//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) usecs) / 1000ULL;
|
||||||
intmax_t TimeToSleep = ((uintmax_t) R->ebx) / 1000ULL;
|
|
||||||
if ( TimeToSleep == 0 ) { return; }
|
if ( TimeToSleep == 0 ) { return; }
|
||||||
|
Syscall::Incomplete();
|
||||||
CurrentThread()->Sleep(TimeToSleep);
|
CurrentThread()->Sleep(TimeToSleep);
|
||||||
Switch(R, 0);
|
Switch(Syscall::InterruptRegs(), 0);
|
||||||
#else
|
|
||||||
#warning "This syscall is not supported on this arch"
|
|
||||||
while(true);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,8 +109,6 @@ namespace Sortix
|
||||||
// System Calls.
|
// System Calls.
|
||||||
void SysCreateThread(CPU::InterruptRegisters* R);
|
void SysCreateThread(CPU::InterruptRegisters* R);
|
||||||
void SysExitThread(CPU::InterruptRegisters* R);
|
void SysExitThread(CPU::InterruptRegisters* R);
|
||||||
void SysSleep(CPU::InterruptRegisters* R);
|
|
||||||
void SysUSleep(CPU::InterruptRegisters* R);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scheduling
|
// Scheduling
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
namespace Sortix
|
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); }
|
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
|
namespace Sound
|
||||||
{
|
{
|
||||||
|
void Init();
|
||||||
void Mute();
|
void Mute();
|
||||||
void Play(nat Frequency);
|
void Play(nat Frequency);
|
||||||
void SysSetFrequency(CPU::InterruptRegisters* R);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,77 +24,68 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "scheduler.h"
|
#include "syscallnum.h"
|
||||||
#include "interrupt.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "vga.h"
|
#include "thread.h"
|
||||||
#include "keyboard.h"
|
#include "scheduler.h"
|
||||||
#include "sound.h"
|
|
||||||
#include "process.h"
|
#include "log.h" // DEBUG
|
||||||
#include "initrd.h"
|
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
namespace Syscall
|
namespace Syscall
|
||||||
{
|
{
|
||||||
void SysStdOutPrint(CPU::InterruptRegisters* R)
|
extern "C"
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_X86
|
CPU::SyscallRegisters* syscall_state_ptr;
|
||||||
// TODO: Validate our input pointer is legal for the current thread/process!
|
int system_was_incomplete;
|
||||||
R->eax = (uint32_t) Log::Print((const char*) R->ebx);
|
size_t SYSCALL_MAX = SYSCALL_MAX_NUM;
|
||||||
#else
|
void* syscall_list[SYSCALL_MAX_NUM];
|
||||||
#warning "This syscall is not supported on this arch"
|
|
||||||
while(true);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t NumSyscalls = 12;
|
int BadSyscall()
|
||||||
const Syscall Syscalls[NumSyscalls] =
|
|
||||||
{
|
{
|
||||||
&Scheduler::SysCreateThread,
|
// TODO: Send signal, set errno, or crash/abort process?
|
||||||
&Scheduler::SysExitThread,
|
return -1;
|
||||||
&Scheduler::SysSleep,
|
}
|
||||||
&Scheduler::SysUSleep,
|
|
||||||
&SysStdOutPrint,
|
|
||||||
&VGA::SysCreateFrame,
|
|
||||||
&VGA::SysChangeFrame,
|
|
||||||
&VGA::SysDeleteFrame,
|
|
||||||
&Keyboard::SysReceieveKeystroke,
|
|
||||||
&Sound::SysSetFrequency,
|
|
||||||
&SysExecute,
|
|
||||||
&InitRD::SysPrintPathFiles,
|
|
||||||
};
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
Interrupt::RegisterHandler(0x80, &OnCall);
|
for ( size_t i = 0; i < SYSCALL_MAX; i++ )
|
||||||
}
|
|
||||||
|
|
||||||
void OnCall(CPU::InterruptRegisters* registers)
|
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_X86
|
syscall_list[i] = (void*) BadSyscall;
|
||||||
size_t callId = registers->eax;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the requested syscall exists.
|
void Register(size_t index, void* funcptr)
|
||||||
if ( callId >= NumSyscalls ) { return; }
|
{
|
||||||
|
if ( SYSCALL_MAX <= index )
|
||||||
|
{
|
||||||
|
PanicF("attempted to register syscall 0x%p to index %zu, but "
|
||||||
|
"SYSCALL_MAX = %zu", funcptr, index, SYSCALL_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USING_OLD_SYSCALL
|
syscall_list[index] = funcptr;
|
||||||
Syscalls[registers->eax](registers);
|
}
|
||||||
#else
|
|
||||||
Thread* thread = CurrentThread();
|
|
||||||
|
|
||||||
thread->BeginSyscall(registers);
|
void Incomplete()
|
||||||
|
{
|
||||||
|
system_was_incomplete = 1;
|
||||||
|
|
||||||
Syscalls[registers->eax](thread);
|
CPU::InterruptRegisters* regs = InterruptRegs();
|
||||||
|
CurrentThread()->SaveRegisters(regs);
|
||||||
|
// TODO: Make the thread blocking if not already.
|
||||||
|
Scheduler::Switch(regs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
thread->OnSysReturn();
|
CPU::InterruptRegisters* InterruptRegs()
|
||||||
#endif
|
{
|
||||||
|
return (CPU::InterruptRegisters*) syscall_state_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
CPU::SyscallRegisters* SyscallRegs()
|
||||||
#warning "System calls are not available on this platform"
|
{
|
||||||
while(true);
|
return syscall_state_ptr;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,30 +25,29 @@
|
||||||
#ifndef SORTIX_SYSCALL_H
|
#ifndef SORTIX_SYSCALL_H
|
||||||
#define SORTIX_SYSCALL_H
|
#define SORTIX_SYSCALL_H
|
||||||
|
|
||||||
#include "scheduler.h"
|
#include "syscallnum.h"
|
||||||
|
|
||||||
#ifdef PLATFORM_X86
|
|
||||||
#define SYSPARAM __attribute__ ((aligned (4)));
|
|
||||||
#elif defined(PLATFORM_X64)
|
|
||||||
#define SYSPARAM __attribute__ ((aligned (8)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USING_OLD_SYSCALL
|
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
namespace Syscall
|
namespace Syscall
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
void OnCall(CPU::InterruptRegisters* R);
|
void Register(size_t index, void* funcptr);
|
||||||
|
|
||||||
#ifdef USING_OLD_SYSCALL
|
// Aborts the current system call such that the current thread is marked
|
||||||
typedef void (*Syscall)(CPU::InterruptRegisters* r);
|
// as blocking, and control is transferred to the next runnable thread.
|
||||||
#else
|
// This allows the thread to wait for an condition that makes the thread
|
||||||
typedef void (*Syscall)(Thread* R);
|
// runnable again and stores the return value in the proper register.
|
||||||
#endif
|
// 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
|
#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 "vga.h"
|
||||||
#include "memorymanagement.h"
|
#include "memorymanagement.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
using namespace Maxsi;
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ namespace Sortix
|
||||||
{
|
{
|
||||||
namespace VGA
|
namespace VGA
|
||||||
{
|
{
|
||||||
|
addr_t SysCreateFrame();
|
||||||
|
int SysChangeFrame(int fd);
|
||||||
|
int SysDeleteFrame(int fd);
|
||||||
|
|
||||||
uint16_t* const vga = (uint16_t* const) 0xB8000;
|
uint16_t* const vga = (uint16_t* const) 0xB8000;
|
||||||
const int width = 80;
|
const int width = 80;
|
||||||
const int height = 80;
|
const int height = 80;
|
||||||
|
@ -43,6 +48,10 @@ namespace Sortix
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
currentframe = NULL;
|
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.
|
// Changes the position of the hardware cursor.
|
||||||
|
@ -60,11 +69,10 @@ namespace Sortix
|
||||||
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysCreateFrame(CPU::InterruptRegisters* R)
|
addr_t SysCreateFrame()
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_X86
|
|
||||||
addr_t page = Page::Get();
|
addr_t page = Page::Get();
|
||||||
if ( page == NULL ) { R->eax = 0; return; }
|
if ( !page ) { return 0; }
|
||||||
|
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
addr_t mapto = Page::AlignUp(process->_endcodesection);
|
addr_t mapto = Page::AlignUp(process->_endcodesection);
|
||||||
|
@ -74,7 +82,7 @@ namespace Sortix
|
||||||
|
|
||||||
if ( !Memory::MapUser(page, mapto) )
|
if ( !Memory::MapUser(page, mapto) )
|
||||||
{
|
{
|
||||||
Page::Put(page); R->eax = 0; return;
|
Page::Put(page); return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxsi::Memory::Set(userframe, 0, sizeof(UserFrame));
|
Maxsi::Memory::Set(userframe, 0, sizeof(UserFrame));
|
||||||
|
@ -83,7 +91,7 @@ namespace Sortix
|
||||||
if ( frame == NULL )
|
if ( frame == NULL )
|
||||||
{
|
{
|
||||||
Memory::UnmapUser(mapto);
|
Memory::UnmapUser(mapto);
|
||||||
Page::Put(page); R->eax = 0; return;
|
Page::Put(page); return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = process->descriptors.Allocate(frame);
|
int fd = process->descriptors.Allocate(frame);
|
||||||
|
@ -91,7 +99,7 @@ namespace Sortix
|
||||||
{
|
{
|
||||||
delete frame;
|
delete frame;
|
||||||
Memory::UnmapUser(mapto);
|
Memory::UnmapUser(mapto);
|
||||||
Page::Put(page); R->eax = 0; return;
|
Page::Put(page); return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
userframe->fd = fd;
|
userframe->fd = fd;
|
||||||
|
@ -102,20 +110,16 @@ namespace Sortix
|
||||||
|
|
||||||
process->_endcodesection = mapto + 0x1000UL;
|
process->_endcodesection = mapto + 0x1000UL;
|
||||||
|
|
||||||
R->eax = mapto;
|
return mapto;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysChangeFrame(CPU::InterruptRegisters* R)
|
int SysChangeFrame(int fd)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_X86
|
|
||||||
int fd = (int) R->ebx;
|
|
||||||
|
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
Device* device = process->descriptors.Get(fd);
|
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;
|
DevVGAFrame* frame = (DevVGAFrame*) device;
|
||||||
|
|
||||||
|
@ -126,10 +130,8 @@ namespace Sortix
|
||||||
|
|
||||||
// TODO: Check if userframe is actually user-space writable!
|
// 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.
|
// 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
|
// 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
|
// the VGA memory and back to the RAM. This should be done
|
||||||
|
@ -173,22 +175,20 @@ namespace Sortix
|
||||||
frame->onscreen = true;
|
frame->onscreen = true;
|
||||||
currentframe = frame;
|
currentframe = frame;
|
||||||
SetCursor(width, height-1);
|
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();
|
Process* process = CurrentProcess();
|
||||||
Device* device = process->descriptors.Get(fd);
|
Device* device = process->descriptors.Get(fd);
|
||||||
process->descriptors.Free(fd);
|
process->descriptors.Free(fd);
|
||||||
|
|
||||||
if ( device == NULL ) { R->eax = -1; return; }
|
if ( device == NULL ) { return -1; }
|
||||||
if ( !device->Close() ) { R->eax = -1; return; }
|
if ( !device->Close() ) { return -1; }
|
||||||
R->eax = 0;
|
|
||||||
#endif
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,11 +67,6 @@ namespace Sortix
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void SetCursor(nat x, nat y);
|
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
|
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 int_no, err_code; // Interrupt number and error code (if applicable)
|
||||||
uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically.
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned method = System::Keyboard::POLL;
|
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 == 0 ) { continue; }
|
||||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||||
|
|
|
@ -15,7 +15,7 @@ void command()
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned method = System::Keyboard::POLL;
|
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 == 0 ) { continue; }
|
||||||
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
if ( codepoint & Maxsi::Keyboard::DEPRESSED ) { continue; }
|
||||||
|
|
Loading…
Add table
Reference in a new issue