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:
@@ -1,11 +1,22 @@
|
|||||||
global _start
|
global _start
|
||||||
_start:
|
_start:
|
||||||
xor rbp, rbp ; Sentinel rbp
|
xor rbp, rbp ; Sentinel rbp
|
||||||
|
mov r11, 0 ; counter
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
;mov rax, 1 ; DEBUG syscall
|
mov rax, 1 ; DEBUG syscall
|
||||||
mov rax, 0 ; NOOP syscall
|
;mov rax, 0 ; NOOP syscall
|
||||||
syscall
|
;syscall
|
||||||
|
int 0xee
|
||||||
|
|
||||||
|
inc r11
|
||||||
|
cmp r11, 5
|
||||||
|
|
||||||
|
jle .loop
|
||||||
|
|
||||||
|
mov rax, 3 ; PAUSE syscall
|
||||||
|
; syscall
|
||||||
|
int 0xee
|
||||||
|
|
||||||
|
mov r11, 0
|
||||||
jmp .loop
|
jmp .loop
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ cpu_id::cpu_id()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cpu_id::regs
|
cpu_id::regs
|
||||||
cpu_id::get(uint32_t leaf, uint32_t sub) const
|
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)
|
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)
|
UISR(0xee, isrSyscall)
|
||||||
ISR (0xed, isrLINT0)
|
|
||||||
ISR (0xee, isrLINT1)
|
|
||||||
ISR (0xef, isrSpurious)
|
|
||||||
|
|
||||||
ISR (0xf0, isrIgnore0)
|
ISR (0xf0, isrIgnore0)
|
||||||
ISR (0xf1, isrIgnore1)
|
ISR (0xf1, isrIgnore1)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "kutil/memory.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
@@ -19,9 +21,11 @@ extern "C" {
|
|||||||
|
|
||||||
#define ISR(i, name) extern void name ();
|
#define ISR(i, name) extern void name ();
|
||||||
#define EISR(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 ();
|
#define IRQ(i, q, name) extern void name ();
|
||||||
#include "interrupt_isrs.inc"
|
#include "interrupt_isrs.inc"
|
||||||
#undef IRQ
|
#undef IRQ
|
||||||
|
#undef UISR
|
||||||
#undef EISR
|
#undef EISR
|
||||||
#undef ISR
|
#undef ISR
|
||||||
}
|
}
|
||||||
@@ -39,9 +43,11 @@ get_irq(unsigned vector)
|
|||||||
switch (vector) {
|
switch (vector) {
|
||||||
#define ISR(i, name)
|
#define ISR(i, name)
|
||||||
#define EISR(i, name)
|
#define EISR(i, name)
|
||||||
|
#define UISR(i, name)
|
||||||
#define IRQ(i, q, name) case i : return q;
|
#define IRQ(i, q, name) case i : return q;
|
||||||
#include "interrupt_isrs.inc"
|
#include "interrupt_isrs.inc"
|
||||||
#undef IRQ
|
#undef IRQ
|
||||||
|
#undef UISR
|
||||||
#undef EISR
|
#undef EISR
|
||||||
#undef ISR
|
#undef ISR
|
||||||
|
|
||||||
@@ -52,7 +58,6 @@ get_irq(unsigned vector)
|
|||||||
static void
|
static void
|
||||||
disable_legacy_pic()
|
disable_legacy_pic()
|
||||||
{
|
{
|
||||||
|
|
||||||
static const uint16_t PIC1 = 0x20;
|
static const uint16_t PIC1 = 0x20;
|
||||||
static const uint16_t PIC2 = 0xa0;
|
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 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 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);
|
#define IRQ(i, q, name) idt_set_entry(i, reinterpret_cast<uint64_t>(& name), 0x08, 0x8e);
|
||||||
#include "interrupt_isrs.inc"
|
#include "interrupt_isrs.inc"
|
||||||
#undef IRQ
|
#undef IRQ
|
||||||
|
#undef UISR
|
||||||
#undef EISR
|
#undef EISR
|
||||||
#undef ISR
|
#undef ISR
|
||||||
|
|
||||||
@@ -97,71 +104,6 @@ interrupts_init()
|
|||||||
log::info(logs::boot, "Interrupts enabled.");
|
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
|
addr_t
|
||||||
isr_handler(addr_t return_rsp, cpu_state regs)
|
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->puts("\nGeneral Protection Fault:\n");
|
||||||
cons->set_color();
|
cons->set_color();
|
||||||
|
|
||||||
cons->puts(" flags:");
|
cons->printf(" errorcode: %lx", regs.errorcode);
|
||||||
if (regs.errorcode & 0x01) cons->puts(" external");
|
if (regs.errorcode & 0x01) cons->puts(" external");
|
||||||
|
|
||||||
int index = (regs.errorcode & 0xf8) >> 3;
|
int index = (regs.errorcode & 0xffff) >> 4;
|
||||||
if (index) {
|
if (index) {
|
||||||
switch (regs.errorcode & 0x06) {
|
switch ((regs.errorcode & 0x07) >> 1) {
|
||||||
case 0:
|
case 0:
|
||||||
cons->printf(" GDT[%d]\n", index);
|
cons->printf(" GDT[%x]\n", index);
|
||||||
gdt_dump();
|
gdt_dump();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
cons->printf(" IDT[%d]\n", index);
|
cons->printf(" IDT[%x]\n", index);
|
||||||
idt_dump();
|
idt_dump();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cons->printf(" LDT[%d]??\n", index);
|
cons->printf(" LDT[%x]??\n", index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cons->putc('\n');
|
cons->putc('\n');
|
||||||
}
|
}
|
||||||
print_regs(regs);
|
print_regs(regs);
|
||||||
|
/*
|
||||||
print_stacktrace(2);
|
print_stacktrace(2);
|
||||||
print_stack(regs);
|
print_stack(regs);
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
_halt();
|
_halt();
|
||||||
@@ -263,17 +207,22 @@ isr_handler(addr_t return_rsp, cpu_state regs)
|
|||||||
_halt();
|
_halt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case isr::isrSyscall: {
|
||||||
|
return_rsp = syscall_dispatch(return_rsp, regs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cons->set_color(9);
|
cons->set_color(9);
|
||||||
cons->puts("\nReceived ISR interrupt:\n");
|
cons->printf("\nReceived %02x interrupt:\n",
|
||||||
cons->set_color();
|
(static_cast<isr>(regs.interrupt)));
|
||||||
|
|
||||||
cons->printf(" ISR: %02lx\n", regs.interrupt);
|
cons->set_color();
|
||||||
cons->printf(" ERR: %lx\n", regs.errorcode);
|
cons->printf(" ISR: %02lx ERR: %lx\n\n",
|
||||||
cons->puts("\n");
|
regs.interrupt, regs.errorcode);
|
||||||
|
|
||||||
print_regs(regs);
|
print_regs(regs);
|
||||||
print_stacktrace(2);
|
//print_stacktrace(2);
|
||||||
_halt();
|
_halt();
|
||||||
}
|
}
|
||||||
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
*reinterpret_cast<uint32_t *>(0xffffff80fee000b0) = 0;
|
||||||
@@ -302,34 +251,5 @@ irq_handler(addr_t return_rsp, cpu_state regs)
|
|||||||
addr_t
|
addr_t
|
||||||
syscall_handler(addr_t return_rsp, cpu_state regs)
|
syscall_handler(addr_t return_rsp, cpu_state regs)
|
||||||
{
|
{
|
||||||
console *cons = console::get();
|
return syscall_dispatch(return_rsp, regs);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ enum class isr : uint8_t
|
|||||||
{
|
{
|
||||||
#define ISR(i, name) name = i,
|
#define ISR(i, name) name = i,
|
||||||
#define EISR(i, name) name = i,
|
#define EISR(i, name) name = i,
|
||||||
|
#define UISR(i, name) name = i,
|
||||||
#define IRQ(i, q, name) name = i,
|
#define IRQ(i, q, name) name = i,
|
||||||
#include "interrupt_isrs.inc"
|
#include "interrupt_isrs.inc"
|
||||||
#undef IRQ
|
#undef IRQ
|
||||||
|
#undef UISR
|
||||||
#undef EISR
|
#undef EISR
|
||||||
#undef ISR
|
#undef ISR
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ irq_handler_prelude:
|
|||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%define EISR(i, name) EMIT_EISR name, i
|
%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 ISR(i, name) EMIT_ISR name, i
|
||||||
%define IRQ(i, q, name) EMIT_IRQ 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;
|
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;
|
free_page_header *page = m_page_cache;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
#include "io.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
@@ -11,8 +12,8 @@
|
|||||||
#include "kutil/assert.h"
|
#include "kutil/assert.h"
|
||||||
|
|
||||||
scheduler scheduler::s_instance(nullptr);
|
scheduler scheduler::s_instance(nullptr);
|
||||||
//static const uint32_t quantum = 2000000;
|
static const uint32_t quantum = 2000000;
|
||||||
static const uint32_t quantum = 20000000;
|
//static const uint32_t quantum = 20000000;
|
||||||
|
|
||||||
const int stack_size = 0x1000;
|
const int stack_size = 0x1000;
|
||||||
const uint64_t rflags_noint = 0x002;
|
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 size = (header->vaddr + header->mem_size) - aligned;
|
||||||
size_t pages = page_manager::page_count(size);
|
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);
|
i, header->vaddr, header->mem_size);
|
||||||
|
|
||||||
log::debug(logs::task, " - aligned to: vaddr %016lx pages %d",
|
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))
|
!bitfield_has(header->flags, elf::section_flags::alloc))
|
||||||
continue;
|
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);
|
i, header->addr, header->size);
|
||||||
|
|
||||||
void *dest = reinterpret_cast<void *>(header->addr);
|
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();
|
state.rip = image.entrypoint();
|
||||||
proc->flags &= ~process_flags::loading;
|
proc->flags &= ~process_flags::loading;
|
||||||
|
|
||||||
log::debug(logs::task, "Loaded! New process state:");
|
log::debug(logs::task, " Loaded! New process rip: %016lx", state.rip);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
loader_state->rcx = reinterpret_cast<uint64_t>(proc);
|
||||||
|
|
||||||
log::debug(logs::task, "Creating process %s:", name);
|
log::debug(logs::task, "Creating process %s: pid %d pri %d", name, proc->pid, proc->priority);
|
||||||
log::debug(logs::task, " PID %d", pid);
|
|
||||||
log::debug(logs::task, " Pri %d", pid);
|
|
||||||
log::debug(logs::task, " RSP0 %016lx", state);
|
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, " PML4 %016lx", pml4);
|
||||||
log::debug(logs::task, " Loading %016lx [%d]", loader_state->rax, loader_state->rbx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -187,7 +179,11 @@ scheduler::schedule(addr_t rsp0)
|
|||||||
{
|
{
|
||||||
m_current->rsp = rsp0;
|
m_current->rsp = rsp0;
|
||||||
m_runlists[m_current->priority].remove(m_current);
|
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;
|
uint8_t pri = 0;
|
||||||
while (m_runlists[pri].empty()) {
|
while (m_runlists[pri].empty()) {
|
||||||
@@ -198,14 +194,18 @@ scheduler::schedule(addr_t rsp0)
|
|||||||
m_current = m_runlists[pri].pop_front();
|
m_current = m_runlists[pri].pop_front();
|
||||||
rsp0 = m_current->rsp;
|
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
|
// Set rsp0 to after the end of the about-to-be-popped cpu state
|
||||||
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
||||||
|
wrmsr(ia32_gs_base, rsp0);
|
||||||
|
|
||||||
// Swap page tables
|
// Swap page tables
|
||||||
page_table *pml4 = m_current->pml4;
|
page_table *pml4 = m_current->pml4;
|
||||||
page_manager::set_pml4(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.",
|
log::debug(logs::task, "Scheduler switched to process %d, priority %d%s.",
|
||||||
m_current->pid, m_current->priority, loading ? " (loading)" : "");
|
m_current->pid, m_current->priority, loading ? " (loading)" : "");
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ enum class process_flags : uint32_t
|
|||||||
};
|
};
|
||||||
IS_BITFIELD(process_flags);
|
IS_BITFIELD(process_flags);
|
||||||
|
|
||||||
|
/// A process
|
||||||
struct process
|
struct process
|
||||||
{
|
{
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
@@ -39,6 +40,10 @@ struct process
|
|||||||
|
|
||||||
addr_t rsp;
|
addr_t rsp;
|
||||||
page_table *pml4;
|
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>;
|
using process_list = kutil::linked_list<process>;
|
||||||
@@ -79,7 +84,6 @@ public:
|
|||||||
/// \returns A reference to the global system scheduler
|
/// \returns A reference to the global system scheduler
|
||||||
static scheduler & get() { return s_instance; }
|
static scheduler & get() { return s_instance; }
|
||||||
|
|
||||||
private:
|
|
||||||
friend addr_t isr_handler(addr_t, cpu_state);
|
friend addr_t isr_handler(addr_t, cpu_state);
|
||||||
|
|
||||||
/// Handle a timer tick
|
/// Handle a timer tick
|
||||||
@@ -87,6 +91,7 @@ private:
|
|||||||
/// \returns The stack pointer to switch to
|
/// \returns The stack pointer to switch to
|
||||||
addr_t tick(addr_t rsp0);
|
addr_t tick(addr_t rsp0);
|
||||||
|
|
||||||
|
private:
|
||||||
lapic *m_apic;
|
lapic *m_apic;
|
||||||
|
|
||||||
uint32_t m_next_pid;
|
uint32_t m_next_pid;
|
||||||
@@ -94,6 +99,7 @@ private:
|
|||||||
process_node *m_current;
|
process_node *m_current;
|
||||||
process_slab m_process_allocator;
|
process_slab m_process_allocator;
|
||||||
process_list m_runlists[num_priorities];
|
process_list m_runlists[num_priorities];
|
||||||
|
process_list m_blocked;
|
||||||
|
|
||||||
static scheduler s_instance;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "kutil/memory.h"
|
||||||
|
|
||||||
enum class syscall : uint64_t
|
enum class syscall : uint64_t
|
||||||
{
|
{
|
||||||
noop,
|
noop,
|
||||||
debug,
|
debug,
|
||||||
message,
|
message,
|
||||||
|
pause,
|
||||||
|
|
||||||
last_syscall
|
last_syscall
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cpu_state;
|
||||||
|
addr_t syscall_dispatch(addr_t, const cpu_state &);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user