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:
Justin C. Miller
2018-09-12 20:59:08 -07:00
parent c2f85ce61b
commit 62c559043d
13 changed files with 233 additions and 136 deletions

View File

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