Skip to content

Commit

Permalink
Corrected interruption logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Anivice committed Jan 15, 2025
1 parent 7ec6c8d commit 79b08e9
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 42 deletions.
51 changes: 25 additions & 26 deletions src/SysdarftMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,27 @@ void complicated_to_gnu(option * dest, const option_complicated * src)
}

volatile std::atomic < SysdarftCPU * > g_cpu_instance = nullptr;
// Signal handler for window resize
void resize_handler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->handle_resize();
}
}

void int_handler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->set_abort_next();
}
}

void stop_handler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->system_hlt();
}
}

void boot_sysdarft(
const uint64_t memory_size,
Expand Down Expand Up @@ -105,6 +126,10 @@ void boot_sysdarft(
SysdarftCPU CPUInstance(memory_size, bios_code, hdd, fda, fdb);
g_cpu_instance = &CPUInstance;

std::signal(SIGINT, int_handler);
std::signal(SIGWINCH, resize_handler);
std::signal(SIGTSTP, stop_handler);

try {
CPUInstance.Boot();
} catch (...) {
Expand All @@ -115,28 +140,6 @@ void boot_sysdarft(
g_cpu_instance = nullptr;
}

// Signal handler for window resize
void resize_handler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->handle_resize();
}
}

void int_hamdler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->set_abort_next();
}
}

void stop_handler(int)
{
if (g_cpu_instance) {
g_cpu_instance.load()->system_hlt();
}
}

int main(int argc, char** argv)
{
try
Expand Down Expand Up @@ -303,10 +306,6 @@ int main(int argc, char** argv)
fdb = parsed_options["fdb"].at(0);
}

std::signal(SIGINT, int_hamdler);
std::signal(SIGWINCH, resize_handler);
std::signal(SIGTSTP, stop_handler);

// boot system
boot_sysdarft(memory_size, bios_path, hdd, fda, fdb);
return EXIT_SUCCESS;
Expand Down
2 changes: 2 additions & 0 deletions src/cpu/OutputCurrentContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ void SysdarftCPUInstructionExecutor::show_context()
}
log(xxd_like_dump(stack_off, stack_buffer), "\n");

# ifdef __INSANE_DEBUG__
////////////////////////////////////////////////////////////////////////////////
// SHOW NEXT 8 INSTRUCTIONS
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -351,5 +352,6 @@ void SysdarftCPUInstructionExecutor::show_context()
for (const auto &instruction : next_8_instructions) {
log(instruction, "\n");
}
# endif //__INSANE_DEBUG__
#endif
}
4 changes: 3 additions & 1 deletion src/cpu/SysdarftCPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ void SysdarftCPU::Boot()
SystemHalted = false;
do_abort_int = false;
hd_int_flag = false;
timestamp = 0;

SysdarftCursesUI::initialize();

while (!SystemHalted)
{
// capture and control area
if (do_abort_int) {
if (do_abort_int)
{
do_abort_int = false;
do_abort_0x05();
}
Expand Down
43 changes: 30 additions & 13 deletions src/cpu/SysdarftCPUInterruption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ SysdarftCPUInterruption::SysdarftCPUInterruption(const uint64_t memory) :

void SysdarftCPUInterruption::do_interruption(const uint64_t code)
{
auto do_interruption = [&](decltype(SysdarftRegister::load<FlagRegisterType>()) & fg)
auto fg = SysdarftRegister::load<FlagRegisterType>();

auto mask_fg = [&]()
{
// mask
fg.InterruptionMask = 1;
SysdarftRegister::store<FlagRegisterType>(fg);
};

auto do_interruption = [&]()
{
// software interruptions, maskable
const auto location = do_interruption_lookup(code);
Expand All @@ -61,13 +70,20 @@ void SysdarftCPUInterruption::do_interruption(const uint64_t code)
// 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();

// we are about to abort the cpu instruction execution here since this is a fatal error,
// and we are not sure who raised this.
// It can be raised by anyone in any given state, so we abandon the current instruction routine.
// thus, mask fg will not be executed unless we do it manually again, at here
mask_fg();

// Abort current routine
throw SysdarftCPUSubroutineRequestToAbortTheCurrentInstructionExecutionProcedureDueToError();
}

// mask
fg.InterruptionMask = 1;
SysdarftRegister::store<FlagRegisterType>(fg);
// mask interruption flag
// this will be done AFTER the preservation of CPU state
mask_fg();

// setup jump table
do_jump_table(location);
Expand All @@ -89,17 +105,14 @@ void SysdarftCPUInterruption::do_interruption(const uint64_t code)
case 0x16: do_get_system_hardware_info_0x16(); return;
case 0x17: do_ring_bell_0x17(); return;
default:
auto fg = SysdarftRegister::load<FlagRegisterType>();
// do interruption, but doesn't check interruption mask since
// this is not maskable interruptions
do_interruption(fg);
do_interruption();
}
}

if (auto fg = SysdarftRegister::load<FlagRegisterType>();
!fg.InterruptionMask)
{
do_interruption(fg);
if (!fg.InterruptionMask) {
do_interruption();
}
}

Expand Down Expand Up @@ -141,8 +154,9 @@ void SysdarftCPUInterruption::do_iret()
// Hardware Interruptions
void SysdarftCPUInterruption::do_interruption_fatal_0x00()
{
log("Unrecoverable Fatal Error!");
throw SysdarftCPUFatal();
const auto location = do_interruption_lookup(0x00);
set_mask(); // we don't preserve the CPU state here so that further damage won't be done
do_jump_table(location);
}

void SysdarftCPUInterruption::do_interruption_debug_0x03()
Expand All @@ -151,6 +165,7 @@ void SysdarftCPUInterruption::do_interruption_debug_0x03()
// software interruptions
const auto location = do_interruption_lookup(0x03);
do_preserve_cpu_state();
set_mask();
do_jump_table(location);
}

Expand All @@ -159,13 +174,15 @@ 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);
set_mask();
do_jump_table(location);
}

void SysdarftCPUInterruption::do_abort_0x05()
{
const auto location = do_interruption_lookup(0x05);
do_preserve_cpu_state();
set_mask();
do_jump_table(location);
}

Expand Down Expand Up @@ -199,7 +216,7 @@ void SysdarftCPUInterruption::do_interruption_newline_0x13()
void SysdarftCPUInterruption::do_interruption_getinput_0x14()
{
char ch;
while (!SystemHalted) // abort if external halt is triggered
while (!SystemHalted && !do_abort_int) // abort if external halt or keyboard interrupt is triggered
{
if (const ssize_t n = read(STDIN_FILENO, &ch, 1); n > 0)
{
Expand Down
1 change: 1 addition & 0 deletions src/cpu/SysdarftInstructionExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ void SysdarftCPUInstructionExecutor::execute(const __uint128_t timestamp)

if (debug::verbose) {
log("[CPU] ", literal, "\n");
show_context();
}

if (hd_int_flag || is_break_here())
Expand Down
1 change: 0 additions & 1 deletion src/include/SysdarftCPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class MultipleCPUInstanceCreation final : public SysdarftBaseError
class SYSDARFT_EXPORT_SYMBOL SysdarftCPU final : public SysdarftCPUInstructionExecutor {
private:
__uint128_t timestamp;
std::atomic < bool > do_abort_int = false;

public:
explicit SysdarftCPU(uint64_t memory,
Expand Down
11 changes: 10 additions & 1 deletion src/include/SysdarftCPUDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInterruption : public DecoderDataAccess
protected:
// External halt is handled at upper level
std::atomic<bool> SystemHalted = false;
std::atomic < bool > do_abort_int = false;

struct InterruptionPointer {
uint64_t InterruptionTargetCodeBase;
Expand Down Expand Up @@ -234,7 +235,15 @@ class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInterruption : public DecoderDataAccess
void do_interruption(uint64_t code);
void do_iret();

explicit SysdarftCPUInterruption(const uint64_t memory);
explicit SysdarftCPUInterruption(uint64_t memory);
private:

void set_mask()
{
auto fg = SysdarftRegister::load<FlagRegisterType>();
fg.InterruptionMask = 1;
SysdarftRegister::store<FlagRegisterType>(fg);
}
};

class SYSDARFT_EXPORT_SYMBOL SysdarftCPUInstructionDecoder : public SysdarftCPUInterruption
Expand Down

0 comments on commit 79b08e9

Please sign in to comment.