From c705bf39ff0e90c74299394e5efaa245d2832343 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Thu, 27 Oct 2011 00:05:20 +0200 Subject: [PATCH] Ported kernel to new syscall API and started cleaning up the old one. --- games/conway.cpp | 2 +- games/pong.cpp | 2 +- games/snake.cpp | 2 +- hello/hello.cpp | 2 +- libmaxsi/hsrc/sortix-keyboard.h | 2 +- libmaxsi/sortix-keyboard.cpp | 6 +- sortix/Makefile | 1 + sortix/descriptor_tables.cpp | 4 +- sortix/initrd.cpp | 25 +++---- sortix/initrd.h | 1 - sortix/interrupt.cpp | 2 +- sortix/kernel.cpp | 15 ++++- sortix/keyboard.cpp | 32 ++++----- sortix/keyboard.h | 1 - sortix/log.cpp | 10 +++ sortix/process.cpp | 40 +++++++++++- sortix/process.h | 5 +- sortix/scheduler.cpp | 33 +++++----- sortix/scheduler.h | 2 - sortix/sound.cpp | 11 ++-- sortix/sound.h | 2 +- sortix/syscall.cpp | 91 ++++++++++++-------------- sortix/syscall.h | 29 ++++----- sortix/syscallnum.h | 43 +++++++++++++ sortix/vga.cpp | 52 +++++++-------- sortix/vga.h | 5 -- sortix/x86/syscall.s | 111 ++++++++++++++++++++++++++++++++ sortix/x86/x86.h | 9 +++ utils/cat.cpp | 2 +- utils/mxsh.cpp | 2 +- 30 files changed, 375 insertions(+), 169 deletions(-) create mode 100644 sortix/syscallnum.h create mode 100644 sortix/x86/syscall.s diff --git a/games/conway.cpp b/games/conway.cpp index dad9c181..45c7c55e 100644 --- a/games/conway.cpp +++ b/games/conway.cpp @@ -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; } diff --git a/games/pong.cpp b/games/pong.cpp index 143aaea7..150d280a 100644 --- a/games/pong.cpp +++ b/games/pong.cpp @@ -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; diff --git a/games/snake.cpp b/games/snake.cpp index 5be965d2..71e6bdb0 100644 --- a/games/snake.cpp +++ b/games/snake.cpp @@ -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; } diff --git a/hello/hello.cpp b/hello/hello.cpp index 16966412..5ddc8a87 100644 --- a/hello/hello.cpp +++ b/hello/hello.cpp @@ -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; } diff --git a/libmaxsi/hsrc/sortix-keyboard.h b/libmaxsi/hsrc/sortix-keyboard.h index bde88d2a..bcbca8cd 100644 --- a/libmaxsi/hsrc/sortix-keyboard.h +++ b/libmaxsi/hsrc/sortix-keyboard.h @@ -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); } } diff --git a/libmaxsi/sortix-keyboard.cpp b/libmaxsi/sortix-keyboard.cpp index a2f22c4c..619d0b0b 100644 --- a/libmaxsi/sortix-keyboard.cpp +++ b/libmaxsi/sortix-keyboard.cpp @@ -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); } } } diff --git a/sortix/Makefile b/sortix/Makefile index 7f527f4b..1e71b4fb 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -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 diff --git a/sortix/descriptor_tables.cpp b/sortix/descriptor_tables.cpp index af71d234..ff30d8f8 100644 --- a/sortix/descriptor_tables.cpp +++ b/sortix/descriptor_tables.cpp @@ -26,6 +26,7 @@ #include #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 diff --git a/sortix/initrd.cpp b/sortix/initrd.cpp index 09534857..c8212254 100644 --- a/sortix/initrd.cpp +++ b/sortix/initrd.cpp @@ -25,6 +25,7 @@ #include "platform.h" #include "initrd.h" #include +#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); - } - } } } diff --git a/sortix/initrd.h b/sortix/initrd.h index ae5e1a3d..5a826a9a 100644 --- a/sortix/initrd.h +++ b/sortix/initrd.h @@ -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 diff --git a/sortix/interrupt.cpp b/sortix/interrupt.cpp index 799970d1..764bb332 100644 --- a/sortix/interrupt.cpp +++ b/sortix/interrupt.cpp @@ -87,7 +87,7 @@ namespace Sortix Sound::Mute(); const char* programname = "sh"; regs->ebx = (uint32_t) programname; - SysExecute(regs); + SysExecuteOld(regs); return; } diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 8e6258c9..6afa58e4 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -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(); diff --git a/sortix/keyboard.cpp b/sortix/keyboard.cpp index 6fe4e51a..e5aaab8e 100644 --- a/sortix/keyboard.cpp +++ b/sortix/keyboard.cpp @@ -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 - } } } diff --git a/sortix/keyboard.h b/sortix/keyboard.h index 3e94ed17..db0ddf03 100644 --- a/sortix/keyboard.h +++ b/sortix/keyboard.h @@ -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); } } diff --git a/sortix/log.cpp b/sortix/log.cpp index 5d67e181..b69c01ec 100644 --- a/sortix/log.cpp +++ b/sortix/log.cpp @@ -26,6 +26,7 @@ #include #include #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); } } } diff --git a/sortix/process.cpp b/sortix/process.cpp index 7c1ea6ab..d5f48ecc 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -24,10 +24,14 @@ #include "platform.h" #include +#include #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); + } } diff --git a/sortix/process.h b/sortix/process.h index 8860408d..ae8f6513 100644 --- a/sortix/process.h +++ b/sortix/process.h @@ -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 diff --git a/sortix/scheduler.cpp b/sortix/scheduler.cpp index 45ce1811..a3f1d707 100644 --- a/sortix/scheduler.cpp +++ b/sortix/scheduler.cpp @@ -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("\n", CurrentThread()); } - void SysSleep(CPU::InterruptRegisters* R) + void SysSleep(size_t secs) { //Log::PrintF("\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("\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); } } diff --git a/sortix/scheduler.h b/sortix/scheduler.h index e30dbd00..9961a16f 100644 --- a/sortix/scheduler.h +++ b/sortix/scheduler.h @@ -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 diff --git a/sortix/sound.cpp b/sortix/sound.cpp index fef4ccae..7e2d2241 100644 --- a/sortix/sound.cpp +++ b/sortix/sound.cpp @@ -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); } } } diff --git a/sortix/sound.h b/sortix/sound.h index ec3815f2..8f37da68 100644 --- a/sortix/sound.h +++ b/sortix/sound.h @@ -29,9 +29,9 @@ namespace Sortix { namespace Sound { + void Init(); void Mute(); void Play(nat Frequency); - void SysSetFrequency(CPU::InterruptRegisters* R); } } diff --git a/sortix/syscall.cpp b/sortix/syscall.cpp index d61f79ad..be76510a 100644 --- a/sortix/syscall.cpp +++ b/sortix/syscall.cpp @@ -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; } } } diff --git a/sortix/syscall.h b/sortix/syscall.h index 246df5eb..3fd72656 100644 --- a/sortix/syscall.h +++ b/sortix/syscall.h @@ -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 diff --git a/sortix/syscallnum.h b/sortix/syscallnum.h new file mode 100644 index 00000000..b84a3d2a --- /dev/null +++ b/sortix/syscallnum.h @@ -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 . + + 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 + diff --git a/sortix/vga.cpp b/sortix/vga.cpp index 9a7ba1a4..43afe66d 100644 --- a/sortix/vga.cpp +++ b/sortix/vga.cpp @@ -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; } } diff --git a/sortix/vga.h b/sortix/vga.h index b7692f03..75c0c356 100644 --- a/sortix/vga.h +++ b/sortix/vga.h @@ -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 diff --git a/sortix/x86/syscall.s b/sortix/x86/syscall.s new file mode 100644 index 00000000..2b30447f --- /dev/null +++ b/sortix/x86/syscall.s @@ -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 . + + 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 + diff --git a/sortix/x86/x86.h b/sortix/x86/x86.h index fbfdf19f..7b099dfa 100644 --- a/sortix/x86/x86.h +++ b/sortix/x86/x86.h @@ -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; + }; } } diff --git a/utils/cat.cpp b/utils/cat.cpp index 7eef22c5..c50d8ae2 100644 --- a/utils/cat.cpp +++ b/utils/cat.cpp @@ -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; } diff --git a/utils/mxsh.cpp b/utils/mxsh.cpp index 61dd614d..f6d150e2 100644 --- a/utils/mxsh.cpp +++ b/utils/mxsh.cpp @@ -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; }