Ported kernel to new syscall API and started cleaning up the old one.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-10-27 00:05:20 +02:00
parent 011e6eca95
commit c705bf39ff
30 changed files with 375 additions and 169 deletions

View File

@ -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; }

View File

@ -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;

View File

@ -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; }

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}
}
}
}

View File

@ -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

View File

@ -87,7 +87,7 @@ namespace Sortix
Sound::Mute();
const char* programname = "sh";
regs->ebx = (uint32_t) programname;
SysExecute(regs);
SysExecuteOld(regs);
return;
}

View File

@ -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();

View File

@ -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
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -29,9 +29,9 @@ namespace Sortix
{
namespace Sound
{
void Init();
void Mute();
void Play(nat Frequency);
void SysSetFrequency(CPU::InterruptRegisters* R);
}
}

View File

@ -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;
}
}
}

View File

@ -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
View 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

View File

@ -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;
}
}

View File

@ -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
View 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

View File

@ -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;
};
}
}

View File

@ -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; }

View File

@ -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; }