mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Pause syscall and int 0xee interrupt syscalls
The syscall/sysret instructions don't swap stacks. This was bad but passable until syscalls caused the scheduler to run, and scheduling a task that paused due to interrupt. Adding a new (hopefully temporary) syscall interrupt `int 0xee` to allow me to test syscalls without stack issues before I tackle the syscall/sysret issue. Also implemented a basic `pause` syscall that causes the calling process to become unready. Because nothing can wake a process yet, it never returns.
This commit is contained in:
@@ -52,6 +52,7 @@ cpu_id::cpu_id()
|
||||
|
||||
}
|
||||
|
||||
|
||||
cpu_id::regs
|
||||
cpu_id::get(uint32_t leaf, uint32_t sub) const
|
||||
{
|
||||
|
||||
68
src/kernel/debug.cpp
Normal file
68
src/kernel/debug.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "gdt.h"
|
||||
|
||||
#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value));
|
||||
|
||||
void
|
||||
print_regs(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
print_reg("rax", regs.rax);
|
||||
print_reg("rbx", regs.rbx);
|
||||
print_reg("rcx", regs.rcx);
|
||||
print_reg("rdx", regs.rdx);
|
||||
print_reg("rdi", regs.rdi);
|
||||
print_reg("rsi", regs.rsi);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg(" r8", regs.r8);
|
||||
print_reg(" r9", regs.r9);
|
||||
print_reg("r10", regs.r10);
|
||||
print_reg("r11", regs.r11);
|
||||
print_reg("r12", regs.r12);
|
||||
print_reg("r13", regs.r13);
|
||||
print_reg("r14", regs.r14);
|
||||
print_reg("r15", regs.r15);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg("rbp", regs.rbp);
|
||||
print_reg("rsp", regs.user_rsp);
|
||||
print_reg("sp0", tss_get_stack(0));
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg(" ds", regs.ds);
|
||||
print_reg(" cs", regs.cs);
|
||||
print_reg(" ss", regs.ss);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg("rip", regs.rip);
|
||||
}
|
||||
|
||||
void
|
||||
print_stacktrace(int skip)
|
||||
{
|
||||
console *cons = console::get();
|
||||
int frame = 0;
|
||||
uint64_t bp = get_frame(skip);
|
||||
while (bp) {
|
||||
cons->printf(" frame %2d: %lx\n", frame, bp);
|
||||
bp = get_frame(++frame + skip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_stack(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
cons->puts("\nStack:\n");
|
||||
uint64_t sp = regs.user_rsp;
|
||||
while (sp <= regs.rbp) {
|
||||
cons->printf("%016x: %016x\n", sp, *reinterpret_cast<uint64_t *>(sp));
|
||||
sp += sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
|
||||
19
src/kernel/debug.h
Normal file
19
src/kernel/debug.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
/// \file debug.h
|
||||
/// Debugging utilities
|
||||
|
||||
#include "kutil/memory.h"
|
||||
|
||||
extern "C" {
|
||||
addr_t get_rsp();
|
||||
addr_t get_rip();
|
||||
addr_t get_frame(int frame);
|
||||
|
||||
}
|
||||
|
||||
void print_regs(const cpu_state ®s);
|
||||
void print_stack(const cpu_state ®s);
|
||||
void print_stacktrace(int skip = 0);
|
||||
|
||||
#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value));
|
||||
|
||||
@@ -237,12 +237,13 @@ IRQ (0xde, 0xbe, irqBE)
|
||||
IRQ (0xdf, 0xbf, irqBF)
|
||||
|
||||
|
||||
ISR (0xe7, isrAssert)
|
||||
ISR (0xe0, isrTimer)
|
||||
ISR (0xe1, isrLINT0)
|
||||
ISR (0xe2, isrLINT1)
|
||||
ISR (0xe3, isrSpurious)
|
||||
ISR (0xe4, isrAssert)
|
||||
|
||||
ISR (0xec, isrTimer)
|
||||
ISR (0xed, isrLINT0)
|
||||
ISR (0xee, isrLINT1)
|
||||
ISR (0xef, isrSpurious)
|
||||
UISR(0xee, isrSyscall)
|
||||
|
||||
ISR (0xf0, isrIgnore0)
|
||||
ISR (0xf1, isrIgnore1)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kutil/memory.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "device_manager.h"
|
||||
#include "gdt.h"
|
||||
#include "interrupts.h"
|
||||
@@ -19,9 +21,11 @@ extern "C" {
|
||||
|
||||
#define ISR(i, name) extern void name ();
|
||||
#define EISR(i, name) extern void name ();
|
||||
#define UISR(i, name) extern void name ();
|
||||
#define IRQ(i, q, name) extern void name ();
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef UISR
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
}
|
||||
@@ -39,9 +43,11 @@ get_irq(unsigned vector)
|
||||
switch (vector) {
|
||||
#define ISR(i, name)
|
||||
#define EISR(i, name)
|
||||
#define UISR(i, name)
|
||||
#define IRQ(i, q, name) case i : return q;
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef UISR
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
@@ -52,7 +58,6 @@ get_irq(unsigned vector)
|
||||
static void
|
||||
disable_legacy_pic()
|
||||
{
|
||||
|
||||
static const uint16_t PIC1 = 0x20;
|
||||
static const uint16_t PIC2 = 0xa0;
|
||||
|
||||
@@ -85,9 +90,11 @@ interrupts_init()
|
||||
{
|
||||
#define ISR(i, name) idt_set_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
|
||||
#define EISR(i, name) idt_set_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
|
||||
#define UISR(i, name) idt_set_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0xee);
|
||||
#define IRQ(i, q, name) idt_set_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef UISR
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
@@ -97,71 +104,6 @@ interrupts_init()
|
||||
log::info(logs::boot, "Interrupts enabled.");
|
||||
}
|
||||
|
||||
#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value));
|
||||
|
||||
extern "C" uint64_t get_frame(int frame);
|
||||
|
||||
void
|
||||
print_stacktrace(int skip = 0)
|
||||
{
|
||||
console *cons = console::get();
|
||||
int frame = 0;
|
||||
uint64_t bp = get_frame(skip);
|
||||
while (bp) {
|
||||
cons->printf(" frame %2d: %lx\n", frame, bp);
|
||||
bp = get_frame(++frame + skip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_regs(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
print_reg("rax", regs.rax);
|
||||
print_reg("rbx", regs.rbx);
|
||||
print_reg("rcx", regs.rcx);
|
||||
print_reg("rdx", regs.rdx);
|
||||
print_reg("rdi", regs.rdi);
|
||||
print_reg("rsi", regs.rsi);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg(" r8", regs.r8);
|
||||
print_reg(" r9", regs.r9);
|
||||
print_reg("r10", regs.r10);
|
||||
print_reg("r11", regs.r11);
|
||||
print_reg("r12", regs.r12);
|
||||
print_reg("r13", regs.r13);
|
||||
print_reg("r14", regs.r14);
|
||||
print_reg("r15", regs.r15);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg("rbp", regs.rbp);
|
||||
print_reg("rsp", regs.user_rsp);
|
||||
print_reg("sp0", tss_get_stack(0));
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg(" ds", regs.ds);
|
||||
print_reg(" cs", regs.cs);
|
||||
print_reg(" ss", regs.ss);
|
||||
|
||||
cons->puts("\n");
|
||||
print_reg("rip", regs.rip);
|
||||
}
|
||||
|
||||
void
|
||||
print_stack(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
cons->puts("\nStack:\n");
|
||||
uint64_t sp = regs.user_rsp;
|
||||
while (sp <= regs.rbp) {
|
||||
cons->printf("%016x: %016x\n", sp, *reinterpret_cast<uint64_t *>(sp));
|
||||
sp += sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
|
||||
addr_t
|
||||
isr_handler(addr_t return_rsp, cpu_state regs)
|
||||
{
|
||||
@@ -197,33 +139,35 @@ isr_handler(addr_t return_rsp, cpu_state regs)
|
||||
cons->puts("\nGeneral Protection Fault:\n");
|
||||
cons->set_color();
|
||||
|
||||
cons->puts(" flags:");
|
||||
cons->printf(" errorcode: %lx", regs.errorcode);
|
||||
if (regs.errorcode & 0x01) cons->puts(" external");
|
||||
|
||||
int index = (regs.errorcode & 0xf8) >> 3;
|
||||
int index = (regs.errorcode & 0xffff) >> 4;
|
||||
if (index) {
|
||||
switch (regs.errorcode & 0x06) {
|
||||
switch ((regs.errorcode & 0x07) >> 1) {
|
||||
case 0:
|
||||
cons->printf(" GDT[%d]\n", index);
|
||||
cons->printf(" GDT[%x]\n", index);
|
||||
gdt_dump();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
cons->printf(" IDT[%d]\n", index);
|
||||
cons->printf(" IDT[%x]\n", index);
|
||||
idt_dump();
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->printf(" LDT[%d]??\n", index);
|
||||
cons->printf(" LDT[%x]??\n", index);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cons->putc('\n');
|
||||
}
|
||||
print_regs(regs);
|
||||
/*
|
||||
print_stacktrace(2);
|
||||
print_stack(regs);
|
||||
*/
|
||||
|
||||
}
|
||||
_halt();
|
||||
@@ -263,17 +207,22 @@ isr_handler(addr_t return_rsp, cpu_state regs)
|
||||
_halt();
|
||||
break;
|
||||
|
||||
case isr::isrSyscall: {
|
||||
return_rsp = syscall_dispatch(return_rsp, regs);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->set_color(9);
|
||||
cons->puts("\nReceived ISR interrupt:\n");
|
||||
cons->set_color();
|
||||
cons->printf("\nReceived %02x interrupt:\n",
|
||||
(static_cast<isr>(regs.interrupt)));
|
||||
|
||||
cons->printf(" ISR: %02lx\n", regs.interrupt);
|
||||
cons->printf(" ERR: %lx\n", regs.errorcode);
|
||||
cons->puts("\n");
|
||||
cons->set_color();
|
||||
cons->printf(" ISR: %02lx ERR: %lx\n\n",
|
||||
regs.interrupt, regs.errorcode);
|
||||
|
||||
print_regs(regs);
|
||||
print_stacktrace(2);
|
||||
//print_stacktrace(2);
|
||||
_halt();
|
||||
}
|
||||
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
||||
@@ -302,34 +251,5 @@ irq_handler(addr_t return_rsp, cpu_state regs)
|
||||
addr_t
|
||||
syscall_handler(addr_t return_rsp, cpu_state regs)
|
||||
{
|
||||
console *cons = console::get();
|
||||
syscall call = static_cast<syscall>(regs.rax);
|
||||
|
||||
switch (call) {
|
||||
case syscall::noop:
|
||||
break;
|
||||
|
||||
case syscall::debug:
|
||||
cons->set_color(11);
|
||||
cons->printf("\nReceived DEBUG syscall\n");
|
||||
cons->set_color();
|
||||
print_regs(regs);
|
||||
break;
|
||||
|
||||
case syscall::message:
|
||||
cons->set_color(11);
|
||||
cons->printf("\nReceived MESSAGE syscall\n");
|
||||
cons->set_color();
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->set_color(9);
|
||||
cons->printf("\nReceived unknown syscall: %02x\n", call);
|
||||
cons->set_color();
|
||||
print_regs(regs);
|
||||
_halt();
|
||||
break;
|
||||
}
|
||||
|
||||
return return_rsp;
|
||||
return syscall_dispatch(return_rsp, regs);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,11 @@ enum class isr : uint8_t
|
||||
{
|
||||
#define ISR(i, name) name = i,
|
||||
#define EISR(i, name) name = i,
|
||||
#define UISR(i, name) name = i,
|
||||
#define IRQ(i, q, name) name = i,
|
||||
#include "interrupt_isrs.inc"
|
||||
#undef IRQ
|
||||
#undef UISR
|
||||
#undef EISR
|
||||
#undef ISR
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ irq_handler_prelude:
|
||||
%endmacro
|
||||
|
||||
%define EISR(i, name) EMIT_EISR name, i
|
||||
%define UISR(i, name) EMIT_ISR name, i
|
||||
%define ISR(i, name) EMIT_ISR name, i
|
||||
%define IRQ(i, q, name) EMIT_IRQ name, i
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ page_manager::get_table_page()
|
||||
}
|
||||
reinterpret_cast<free_page_header *>(virt)->next = nullptr;
|
||||
|
||||
log::info(logs::memory, "Mappd %d new page table pages at %lx", n, phys);
|
||||
log::debug(logs::memory, "Mappd %d new page table pages at %lx", n, phys);
|
||||
}
|
||||
|
||||
free_page_header *page = m_page_cache;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "cpu.h"
|
||||
#include "gdt.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "page_manager.h"
|
||||
#include "scheduler.h"
|
||||
@@ -11,8 +12,8 @@
|
||||
#include "kutil/assert.h"
|
||||
|
||||
scheduler scheduler::s_instance(nullptr);
|
||||
//static const uint32_t quantum = 2000000;
|
||||
static const uint32_t quantum = 20000000;
|
||||
static const uint32_t quantum = 2000000;
|
||||
//static const uint32_t quantum = 20000000;
|
||||
|
||||
const int stack_size = 0x1000;
|
||||
const uint64_t rflags_noint = 0x002;
|
||||
@@ -69,7 +70,7 @@ load_process(const void *image_start, size_t bytes, process *proc, cpu_state sta
|
||||
size_t size = (header->vaddr + header->mem_size) - aligned;
|
||||
size_t pages = page_manager::page_count(size);
|
||||
|
||||
log::debug(logs::task, " Loadable segment %02d: vaddr %016lx size %016lx",
|
||||
log::debug(logs::task, " Loadable segment %02u: vaddr %016lx size %016lx",
|
||||
i, header->vaddr, header->mem_size);
|
||||
|
||||
log::debug(logs::task, " - aligned to: vaddr %016lx pages %d",
|
||||
@@ -89,7 +90,7 @@ load_process(const void *image_start, size_t bytes, process *proc, cpu_state sta
|
||||
!bitfield_has(header->flags, elf::section_flags::alloc))
|
||||
continue;
|
||||
|
||||
log::debug(logs::task, " Loadable section %u: vaddr %016lx size %016lx",
|
||||
log::debug(logs::task, " Loadable section %02u: vaddr %016lx size %016lx",
|
||||
i, header->addr, header->size);
|
||||
|
||||
void *dest = reinterpret_cast<void *>(header->addr);
|
||||
@@ -100,12 +101,7 @@ load_process(const void *image_start, size_t bytes, process *proc, cpu_state sta
|
||||
state.rip = image.entrypoint();
|
||||
proc->flags &= ~process_flags::loading;
|
||||
|
||||
log::debug(logs::task, "Loaded! New process state:");
|
||||
log::debug(logs::task, " CS: %d [%d]", state.cs >> 3, state.cs & 0x07);
|
||||
log::debug(logs::task, " SS: %d [%d]", state.ss >> 3, state.ss & 0x07);
|
||||
log::debug(logs::task, " RFLAGS: %08x", state.rflags);
|
||||
log::debug(logs::task, " RIP: %016lx", state.rip);
|
||||
log::debug(logs::task, " uRSP: %016lx", state.user_rsp);
|
||||
log::debug(logs::task, " Loaded! New process rip: %016lx", state.rip);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -166,13 +162,9 @@ scheduler::create_process(const char *name, const void *data, size_t size)
|
||||
|
||||
loader_state->rcx = reinterpret_cast<uint64_t>(proc);
|
||||
|
||||
log::debug(logs::task, "Creating process %s:", name);
|
||||
log::debug(logs::task, " PID %d", pid);
|
||||
log::debug(logs::task, " Pri %d", pid);
|
||||
log::debug(logs::task, "Creating process %s: pid %d pri %d", name, proc->pid, proc->priority);
|
||||
log::debug(logs::task, " RSP0 %016lx", state);
|
||||
log::debug(logs::task, " RSP3 %016lx", state->user_rsp);
|
||||
log::debug(logs::task, " PML4 %016lx", pml4);
|
||||
log::debug(logs::task, " Loading %016lx [%d]", loader_state->rax, loader_state->rbx);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -187,7 +179,11 @@ scheduler::schedule(addr_t rsp0)
|
||||
{
|
||||
m_current->rsp = rsp0;
|
||||
m_runlists[m_current->priority].remove(m_current);
|
||||
m_runlists[m_current->priority].push_back(m_current);
|
||||
|
||||
if (m_current->flags && process_flags::ready)
|
||||
m_runlists[m_current->priority].push_back(m_current);
|
||||
else
|
||||
m_blocked.push_back(m_current);
|
||||
|
||||
uint8_t pri = 0;
|
||||
while (m_runlists[pri].empty()) {
|
||||
@@ -198,14 +194,18 @@ scheduler::schedule(addr_t rsp0)
|
||||
m_current = m_runlists[pri].pop_front();
|
||||
rsp0 = m_current->rsp;
|
||||
|
||||
static const uint64_t ia32_gs_base = 0xc0000101;
|
||||
static const uint64_t ia32_kernel_gs_base = 0xc0000102;
|
||||
|
||||
// Set rsp0 to after the end of the about-to-be-popped cpu state
|
||||
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
||||
wrmsr(ia32_gs_base, rsp0);
|
||||
|
||||
// Swap page tables
|
||||
page_table *pml4 = m_current->pml4;
|
||||
page_manager::set_pml4(pml4);
|
||||
|
||||
bool loading = bitfield_has(m_current->flags, process_flags::loading);
|
||||
bool loading = m_current->flags && process_flags::loading;
|
||||
log::debug(logs::task, "Scheduler switched to process %d, priority %d%s.",
|
||||
m_current->pid, m_current->priority, loading ? " (loading)" : "");
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ enum class process_flags : uint32_t
|
||||
};
|
||||
IS_BITFIELD(process_flags);
|
||||
|
||||
/// A process
|
||||
struct process
|
||||
{
|
||||
uint32_t pid;
|
||||
@@ -39,6 +40,10 @@ struct process
|
||||
|
||||
addr_t rsp;
|
||||
page_table *pml4;
|
||||
|
||||
/// Helper to check if this process is ready
|
||||
/// \returns true if the process has the ready flag
|
||||
inline bool ready() { return bitfield_has(flags, process_flags::ready); }
|
||||
};
|
||||
|
||||
using process_list = kutil::linked_list<process>;
|
||||
@@ -79,7 +84,6 @@ public:
|
||||
/// \returns A reference to the global system scheduler
|
||||
static scheduler & get() { return s_instance; }
|
||||
|
||||
private:
|
||||
friend addr_t isr_handler(addr_t, cpu_state);
|
||||
|
||||
/// Handle a timer tick
|
||||
@@ -87,6 +91,7 @@ private:
|
||||
/// \returns The stack pointer to switch to
|
||||
addr_t tick(addr_t rsp0);
|
||||
|
||||
private:
|
||||
lapic *m_apic;
|
||||
|
||||
uint32_t m_next_pid;
|
||||
@@ -94,6 +99,7 @@ private:
|
||||
process_node *m_current;
|
||||
process_slab m_process_allocator;
|
||||
process_list m_runlists[num_priorities];
|
||||
process_list m_blocked;
|
||||
|
||||
static scheduler s_instance;
|
||||
};
|
||||
|
||||
60
src/kernel/syscall.cpp
Normal file
60
src/kernel/syscall.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "scheduler.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern "C" {
|
||||
void _halt();
|
||||
}
|
||||
|
||||
addr_t
|
||||
syscall_dispatch(addr_t return_rsp, const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
syscall call = static_cast<syscall>(regs.rax);
|
||||
|
||||
switch (call) {
|
||||
case syscall::noop:
|
||||
break;
|
||||
|
||||
case syscall::debug:
|
||||
cons->set_color(11);
|
||||
cons->printf("\nReceived DEBUG syscall\n");
|
||||
cons->set_color();
|
||||
print_regs(regs);
|
||||
break;
|
||||
|
||||
case syscall::message:
|
||||
cons->set_color(11);
|
||||
cons->printf("\nReceived MESSAGE syscall\n");
|
||||
cons->set_color();
|
||||
break;
|
||||
|
||||
case syscall::pause:
|
||||
{
|
||||
cons->set_color(11);
|
||||
|
||||
auto &s = scheduler::get();
|
||||
auto *p = s.current();
|
||||
p->flags -= process_flags::ready;
|
||||
//log::debug(logs::task, "Pausing process %d, flags: %08x", p->pid, p->flags);
|
||||
cons->printf("\nReceived PAUSE syscall\n");
|
||||
return_rsp = s.tick(return_rsp);
|
||||
//log::debug(logs::task, "Switching to stack %016lx", return_rsp);
|
||||
cons->printf("\nDONE WITH PAUSE syscall\n");
|
||||
cons->set_color();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->set_color(9);
|
||||
cons->printf("\nReceived unknown syscall: %02x\n", call);
|
||||
cons->set_color();
|
||||
_halt();
|
||||
break;
|
||||
}
|
||||
|
||||
return return_rsp;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "kutil/memory.h"
|
||||
|
||||
enum class syscall : uint64_t
|
||||
{
|
||||
noop,
|
||||
debug,
|
||||
message,
|
||||
pause,
|
||||
|
||||
last_syscall
|
||||
};
|
||||
|
||||
struct cpu_state;
|
||||
addr_t syscall_dispatch(addr_t, const cpu_state &);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user