Compare commits

..

2 Commits

Author SHA1 Message Date
db2814596b Move PIT test to test module 2023-11-25 21:01:46 -05:00
8cfa7bc009 Add hulk.thread module 2023-11-25 20:58:11 -05:00
4 changed files with 130 additions and 10 deletions

View File

@ -26,6 +26,7 @@ import hulk.usb;
import hulk.pit; import hulk.pit;
import hulk.time; import hulk.time;
import hulk.test; import hulk.test;
import hulk.thread;
extern extern(C) __gshared ubyte _hulk_bss_size; extern extern(C) __gshared ubyte _hulk_bss_size;
@ -33,7 +34,7 @@ extern extern(C) __gshared ubyte _hulk_bss_size;
private __gshared HulkHeader hulk_header = { private __gshared HulkHeader hulk_header = {
&_hulk_bss_size, /* hulk_bss_size */ &_hulk_bss_size, /* hulk_bss_size */
&hulk_start, /* entry */ &hulk_start, /* entry */
16u * 1024u, /* stack_size */ Thread.STACK_SIZE, /* stack_size */
Hurl.HULK_BASE, /* virt_base */ Hurl.HULK_BASE, /* virt_base */
Hurl.HULK_STACK_TOP, /* virt_stack_top */ Hurl.HULK_STACK_TOP, /* virt_stack_top */
Hurl.HULK_FRAMEBUFFER, /* virt_fb_buffer */ Hurl.HULK_FRAMEBUFFER, /* virt_fb_buffer */
@ -88,18 +89,14 @@ void hulk_start()
Pit.initialize(); Pit.initialize();
Pci.initialize(); Pci.initialize();
Usb.initialize(); Usb.initialize();
Thread.initialize();
resume_interrupts(); resume_interrupts();
/* Check that PIT millisecond interrupt is firing. */ Test.run();
size_t uptime = Time.uptime();
while (Time.uptime() <= uptime)
{
}
Klog.writefln("\a5HULK Initialization Complete!"); Klog.writefln("\a5HULK Initialization Complete!");
/* Run kernel tests. */ /* Run kernel tests. */
Test.run();
/* Idle loop. */ /* Idle loop. */
Time.msleep(1); Time.msleep(1);

View File

@ -11,11 +11,12 @@ import hulk.klog;
import hulk.apic; import hulk.apic;
import hulk.cpu; import hulk.cpu;
import hulk.kfont; import hulk.kfont;
import hulk.thread;
struct Idt struct Idt
{ {
/** Interrupt stack frame indices. */ /** Interrupt stack frame indices. */
private static enum public static enum
{ {
ISF_RBP, ISF_RBP,
ISF_R15, ISF_R15,
@ -147,7 +148,7 @@ struct Idt
mov $$", isr, ", %rdi mov $$", isr, ", %rdi
movabs $$isr, %rax movabs $$isr, %rax
callq *%rax callq *%rax
mov %rbp, %rsp mov %rax, %rsp
popq %rbp popq %rbp
popq %r15 popq %r15
popq %r14 popq %r14
@ -184,8 +185,15 @@ struct Idt
} }
} }
public extern(C) void isr(ulong vector, ulong * stack_frame) /**
* Interrupt service routine.
*
* This function returns the stack pointer of the thread to execute when
* returning from this function.
*/
public extern(C) ulong * isr(ulong vector, ulong * stack_frame)
{ {
Thread.current_thread.stack_pointer = stack_frame;
if ((vector >= Idt.INT_APIC_BASE) && (vector < (Idt.INT_APIC_BASE + Idt.INT_APIC_COUNT))) if ((vector >= Idt.INT_APIC_BASE) && (vector < (Idt.INT_APIC_BASE + Idt.INT_APIC_COUNT)))
{ {
Apic.isr(vector); Apic.isr(vector);
@ -217,4 +225,5 @@ public extern(C) void isr(ulong vector, ulong * stack_frame)
} }
} }
} }
return Thread.current_thread.stack_pointer;
} }

View File

@ -5,6 +5,7 @@ module hulk.test;
import hulk.klog; import hulk.klog;
import hulk.list; import hulk.list;
import hulk.time;
struct Test struct Test
{ {
@ -14,10 +15,21 @@ struct Test
public static void run() public static void run()
{ {
Klog.writefln("\a3Running kernel tests"); Klog.writefln("\a3Running kernel tests");
test_pit();
test_list(); test_list();
Klog.writefln("\a3Kernel tests complete"); Klog.writefln("\a3Kernel tests complete");
} }
private static void test_pit()
{
Klog.writefln("Testing PIT...");
/* Check that PIT millisecond interrupt is firing. */
size_t uptime = Time.uptime();
while (Time.uptime() <= uptime)
{
}
}
private static void test_list() private static void test_list()
{ {
Klog.writefln("Testing list..."); Klog.writefln("Testing list...");

102
src/hulk/thread.d Normal file
View File

@ -0,0 +1,102 @@
/**
* Kernel thread functionality.
*/
module hulk.thread;
import hulk.hurl.a1;
import hulk.idt;
import hulk.gdt;
import hulk.memory;
import hulk.list;
import hulk.cpu;
import hulk.hurl;
struct Thread
{
/* TODO: currently kernel thread stack size is fixed. */
enum STACK_SIZE = 16 * 1024;
/** List of all kernel threads. */
private static __gshared List!Thread threads;
/** Currently executing kernel thread. */
static __gshared Thread * current_thread;
/** Current kernel thread stack pointer. */
ulong * stack_pointer;
static assert(stack_pointer.offsetof == 0);
/** Base address of kernel thread stack. */
void * stack_addr;
/** Interrupt stack template. */
static immutable __gshared ulong[Idt.ISF_COUNT] interrupt_stack_template = [
0x16161616_16161616u, /* RBP */
0x15151515_15151515u, /* R15 */
0x14141414_14141414u, /* R14 */
0x13131313_13131313u, /* R13 */
0x12121212_12121212u, /* R12 */
0x11111111_11111111u, /* R11 */
0x10101010_10101010u, /* R10 */
0x09090909_09090909u, /* R9 */
0x08080808_08080808u, /* R8 */
0x06060606_06060606u, /* RDI */
0x05050505_05050505u, /* RSI */
0x04040404_04040404u, /* RDX */
0x03030303_03030303u, /* RCX */
0x02020202_02020202u, /* RBX */
0x01010101_01010101u, /* RAX */
0u, /* Error Code */
0u, /* RIP */
Gdt.SELECTOR_KERNEL_CODE, /* CS */
0u, /* RFLAGS */
0u, /* RSP */
Gdt.SELECTOR_KERNEL_DATA, /* SS */
];
/**
* Initialize a kernel thread.
*/
public void initialize(void function() fn)
{
stack_addr = A1.allocate(STACK_SIZE);
ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE);
stack_pointer = stack_top - Idt.ISF_COUNT;
memcpy64(stack_pointer, &interrupt_stack_template[0], Idt.ISF_COUNT);
stack_pointer[Idt.ISF_RIP] = cast(ulong)fn;
stack_pointer[Idt.ISF_RFLAGS] = read_rflags();
stack_pointer[Idt.ISF_RSP] = cast(ulong)stack_top;
}
/**
* Initialize main kernel thread.
*/
public void initialize_main_thread()
{
stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE);
}
/**
* Initialize kernel threading.
*/
public static void initialize()
{
Thread * thread = A1.allocate!Thread();
thread.initialize_main_thread();
current_thread = thread;
}
/**
* Create and start a kernel thread.
*
* TODO: fn must not return.
* TODO: threads are always runnable.
* TODO: threads cannot be destroyed.
*/
public static Thread * start(void function() fn)
{
Thread * thread = A1.allocate!Thread();
thread.initialize(fn);
return thread;
}
}