Skip to content

Commit

Permalink
Added Stackoverflow interruptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Anivice committed Jan 15, 2025
1 parent c31baf8 commit 1036a2b
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 44 deletions.
6 changes: 5 additions & 1 deletion src/cpu/SysdarftCPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ void SysdarftCPU::Boot()
do_abort_0x05();
}

SysdarftCPUInstructionExecutor::execute(timestamp++);
try {
SysdarftCPUInstructionExecutor::execute(timestamp++);
} catch (std::exception & e) {
std::cerr << "Unexpected error detected: " << e.what() << std::endl;
}
}

SysdarftCursesUI::cleanup();
Expand Down
31 changes: 27 additions & 4 deletions src/cpu/SysdarftCPUInterruption.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#include <GlobalEvents.h>
#include <SysdarftCPUDecoder.h>
#include <SysdarftCursesUI.h>
#include <termios.h>
#include <thread>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
#include <GlobalEvents.h>
#include <SysdarftCPUDecoder.h>
#include <SysdarftCursesUI.h>
#include <SysdarftInstructionExec.h>

int my_getch()
{
Expand Down Expand Up @@ -49,7 +50,20 @@ void SysdarftCPUInterruption::do_interruption(const uint64_t code)
{
// software interruptions, maskable
const auto location = do_interruption_lookup(code);
do_preserve_cpu_state();

try {
do_preserve_cpu_state();
} catch (StackOverflow &) {
// TL;DR: stackoverflow happened whilst preserving CPU state during an interruption call!
// Long answer: stackoverflow happened whilst preserving CPU state,
// this will abort the original interruption procedure,
// and directly redirect itself to stackoverflow interruption handler.
// however, this will cause the original reason for interruption to be missing, since, well,
// stack frame is damaged and cannot be used to preserve any useful information anymore.
do_stackoverflow_0x07();
// Abort current routine
throw SysdarftCPUSubroutineRequestToAbortTheCurrentInstructionExecutionProcedureDueToError();
}

// mask
fg.InterruptionMask = 1;
Expand All @@ -65,6 +79,7 @@ void SysdarftCPUInterruption::do_interruption(const uint64_t code)
switch (code) {
case 0x00: do_interruption_fatal_0x00(); return;
case 0x03: do_interruption_debug_0x03(); return;
case 0x07: do_stackoverflow_0x07(); return;
case 0x10: do_interruption_tty_0x10(); return;
case 0x11: do_interruption_set_cur_pos_0x11(); return;
case 0x12: do_interruption_set_cur_visib_0x12(); return;
Expand Down Expand Up @@ -139,6 +154,14 @@ void SysdarftCPUInterruption::do_interruption_debug_0x03()
do_jump_table(location);
}

void SysdarftCPUInterruption::do_stackoverflow_0x07()
{
// We do not preserve CPU state here
// It's impossible since, well, stack frame overflowed and cannot be used
const auto location = do_interruption_lookup(0x07);
do_jump_table(location);
}

void SysdarftCPUInterruption::do_abort_0x05()
{
const auto location = do_interruption_lookup(0x05);
Expand Down
56 changes: 31 additions & 25 deletions src/cpu/SysdarftInstructionExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,39 @@ SysdarftCPUInstructionExecutor::SysdarftCPUInstructionExecutor(const uint64_t me

void SysdarftCPUInstructionExecutor::execute(const __uint128_t timestamp)
{
auto [opcode, width, operands, literal]
= SysdarftCPUInstructionDecoder::pop_instruction_from_ip_and_increase_ip();
try {
try
{
const auto &[opcode, width, operands, literal]
= SysdarftCPUInstructionDecoder::pop_instruction_from_ip_and_increase_ip();
WidthAndOperandsType Arg = std::make_pair(width, operands);

WidthAndOperandsType Arg = std::make_pair(width, operands);
if (debug::verbose) {
log("[CPU] ", literal, "\n");
}

if (debug::verbose) {
log("[CPU] ", literal, "\n");
}
if (hd_int_flag || is_break_here())
{
log("[CPU] Breakpoint reached!\n");
hd_int_flag = false;
breakpoint_handler(timestamp, opcode, Arg);
}

if (hd_int_flag || is_break_here())
{
log("[CPU] Breakpoint reached!\n");
hd_int_flag = false;
breakpoint_handler(timestamp, opcode, Arg);
}

try {
(this->*ExecutorMap.at(opcode))(timestamp, Arg);
} catch (std::out_of_range&) {
log("[CPU] Instruction `", literal, "` not implemented.\n");
} catch (SysdarftDeviceIOError&) {
do_interruption(0x02);
} catch (SysdarftBadInterruption &){
do_interruption(0x04);
} catch (std::exception& err) {
std::string err_str = err.what();
log("[CPU] Unexpected error:", err.what(), "\n");
do_interruption(0x00);
(this->*ExecutorMap.at(opcode))(timestamp, Arg);
} catch (SysdarftDeviceIOError&) {
do_interruption(INT_IO_ERROR);
} catch (SysdarftBadInterruption &){
do_interruption(INT_BAD_INTR);
} catch (IllegalInstruction &) {
do_interruption(INT_ILLEGAL_INSTRUCTION);
} catch (StackOverflow &) {
do_interruption(INT_STACKOVERFLOW);
} catch (SysdarftBaseError &) {
do_interruption(INT_FATAL);
}
} catch (SysdarftCPUSubroutineRequestToAbortTheCurrentInstructionExecutionProcedureDueToError&) {
return; // Abort this routine
} catch (std::exception &) {
throw;
}
}
10 changes: 7 additions & 3 deletions src/include/SysdarftCPUDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#define INT_DEBUG (0x03)
#define INT_BAD_INTR (0x04)
#define INT_ABORT (0x05)
#define INT_ILLEGAL_INSTRUCTION (0x06)
#define INT_STACKOVERFLOW (0x07)

#define INT_TELETYPE (0x10)
#define INT_SET_CUR_POS (0x11)
Expand Down Expand Up @@ -172,15 +174,16 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInterruption : public DecoderDataAccess

/*
* Interruption table:
* Hardware Reserved: [1-F], INVOKED BY HARDWARE, NOT MASKABLE
* Hardware Reserved:
* [1-F], INVOKED BY HARDWARE TO INDICATE AN ERROR, NOT MASKABLE
* [0x00] FATAL ERROR (ErrorCode == %EXR0)
* [0x01] DIV/0
* [0x02] IO ERROR
* [0x03] DEBUG, BREAKPOINT RIGHT NEXT
* [0x04] BAD INTERRUPTION CALL
* [0x05] ABORT
* [0x06]
* [0x07]
* [0x06] ILLEGAL INSTRUCTION
* [0x07] STACK OVERFLOW
* [0x08]
* [0x09]
* [0x0A]
Expand Down Expand Up @@ -215,6 +218,7 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInterruption : public DecoderDataAccess
// Hardware Interruptions
void do_interruption_fatal_0x00();
void do_interruption_debug_0x03();
void do_stackoverflow_0x07();
void do_abort_0x05();
void do_interruption_tty_0x10();
void do_interruption_set_cur_pos_0x11();
Expand Down
28 changes: 26 additions & 2 deletions src/include/SysdarftInstructionExec.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
#include <SysdarftCPUDecoder.h>
#include <SysdarftIOHub.h>

class SysdarftCPUSubroutineRequestToAbortTheCurrentInstructionExecutionProcedureDueToError : SysdarftBaseError {
public:
SysdarftCPUSubroutineRequestToAbortTheCurrentInstructionExecutionProcedureDueToError() :
SysdarftBaseError("Sysdarft Instruction Subroutine Abort") { }
};

#define add_instruction_exec(name) void name(__uint128_t, WidthAndOperandsType &)

class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInstructionExecutor : public SysdarftCPUInstructionDecoder, public SysdarftIOHub
Expand All @@ -18,8 +24,20 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInstructionExecutor : public SysdarftCPU
{
const auto SP = SysdarftRegister::load<StackPointerType>();
const auto SB = SysdarftRegister::load<StackBaseType>();

// Stack overflow
if (SP < sizeof(DataType)) {
throw StackOverflow();
}

const auto StackNewLowerEnd = SP - sizeof(DataType);
SysdarftCPUMemoryAccess::write_memory(StackNewLowerEnd + SB, (char*)&val, sizeof(DataType));

try {
SysdarftCPUMemoryAccess::write_memory(StackNewLowerEnd + SB, (char*)&val, sizeof(DataType));
} catch (IllegalMemoryAccessException & ) {
throw StackOverflow();
}

SysdarftRegister::store<StackPointerType>(StackNewLowerEnd);
}

Expand All @@ -29,7 +47,13 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInstructionExecutor : public SysdarftCPU
DataType val { };
const auto SP = SysdarftRegister::load<StackPointerType>();
const auto SB = SysdarftRegister::load<StackBaseType>();
SysdarftCPUMemoryAccess::read_memory(SB + SP, (char*)&val, sizeof(DataType));

try {
SysdarftCPUMemoryAccess::read_memory(SB + SP, (char*)&val, sizeof(DataType));
} catch (IllegalMemoryAccessException & ) {
throw StackOverflow();
}

SysdarftRegister::store<StackPointerType>(SP + sizeof(DataType));
return val;
}
Expand Down
23 changes: 21 additions & 2 deletions src/include/SysdarftMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class IllegalMemoryAccessException final : public SysdarftBaseError
SysdarftBaseError("Illegal memory access: " + msg) { }
};

class StackOverflow final : public SysdarftBaseError {
public:
StackOverflow() : SysdarftBaseError("STack overflow") { }
};

class SYSDARFT_EXPORT_SYMBOL SysdarftCPUMemoryAccess
{
protected:
Expand All @@ -45,8 +50,16 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUMemoryAccess
template < typename DataType >
void push_memory_to(const uint64_t begin, uint64_t & offset, const DataType & val)
{
if (offset < sizeof(DataType)) {
throw StackOverflow();
}

offset -= sizeof(DataType);
write_memory(begin + offset, (char*)&val, sizeof(DataType));
try {
write_memory(begin + offset, (char*)&val, sizeof(DataType));
} catch (IllegalMemoryAccessException &) {
throw StackOverflow();
}
}

void mpush8(const uint64_t begin, uint64_t & offset, uint8_t value) {
Expand All @@ -69,7 +82,13 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUMemoryAccess
DataType pop_memory_from(const uint64_t begin, uint64_t & offset)
{
DataType result;
read_memory(begin + offset, (char*)&result, sizeof(DataType));

try {
read_memory(begin + offset, (char*)&result, sizeof(DataType));
} catch (IllegalMemoryAccessException &) {
throw StackOverflow();
}

offset += sizeof(DataType);
return result;
}
Expand Down
14 changes: 7 additions & 7 deletions tests/test.io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ class Exec final : public SysdarftCPUInstructionExecutor {
std::map < std::string, std::pair < uint64_t /* line position */, std::vector < uint64_t > > > defined_line_marker;
defined_line_marker.emplace("_loop", std::pair < uint64_t, std::vector < uint64_t > > (0, { }));
std::stringstream ascii_code;
ascii_code << " mov .64bit <%FER0>, <$(16)> \n";
ascii_code << " mov .64bit <*1&64($(0), $(0), $(8))>, <$(1)> \n";
ascii_code << " outs .64bit <$(0x13A)> \n";
ascii_code << " mov .64bit <%FER0>, <$(512)> \n";
ascii_code << " ins .64bit <$(0x138)> \n";
ascii_code << "_loop: \n";
ascii_code << " jmp <%CB>, <_loop> \n";
ascii_code << " mov .64bit <%FER0>, <$(16)> \n";
ascii_code << " mov .64bit <*1&64($(0), $(0), $(8))>, <$(1)> \n";
ascii_code << " out .64bit <$(0x137)>, <$(10)> \n";
ascii_code << " mov .64bit <%FER0>, <$(512)> \n";
ascii_code << " in .64bit <$(0x136)>, <%FER0> \n";
ascii_code << "_loop: \n";
ascii_code << " jmp <%CB>, <_loop> \n";
SysdarftCompile(code, ascii_code, 0xC1800, defined_line_marker);

uint64_t off = BIOS_START;
Expand Down

0 comments on commit 1036a2b

Please sign in to comment.