~swisschili/bluejay

b58ab67dd44af8fde4802345312a320a92485d21 — swissChili 4 months ago d00ec61 master
Fix IDT error # bug, add debug helper, continue debugging spawn_thread crash

The crash occurs after the newly-created stack is accessed, suggesting
that there is some bug in the paging code.
M include/kernel/log.h => include/kernel/log.h +3 -0
@@ 8,6 8,9 @@
#define WARN "[\033[93m WARN  " RESET "] "
#define ERROR "[\033[91m ERROR " RESET "] "
#define DEBUG "[\033[93m DEBUG " RESET "] "
#define BRKPT "[\033[96m BRKPT " RESET "] "
#define REACHED_HERE FORMAT_AT(__FILE__, __LINE__)
#define FORMAT_AT(file, line) "@" file ":%d\n", line

void kprintf(const char *format, ...);
void kassert_int(bool condition, const char *message, const char *file,

M include/kernel/task.h => include/kernel/task.h +1 -0
@@ 23,6 23,7 @@ struct process
	// NOTE: must be PAGE ALIGNED
	uint last_stack_pos;
};

/**
 * The smallest schedulable unit, a thread of a process.
 */

M src/kernel/idt.s => src/kernel/idt.s +2 -2
@@ 40,11 40,11 @@ ISRERR 13
ISRERR 14
ISRNOERR 15
ISRNOERR 16
ISRNOERR 17
ISRERR 17
ISRNOERR 18
ISRNOERR 19
ISRNOERR 20
ISRNOERR 21
ISRERR 21
ISRNOERR 22
ISRNOERR 23
ISRNOERR 24

M src/kernel/main.c => src/kernel/main.c +1 -1
@@ 65,7 65,7 @@ int kmain(struct multiboot_info *mboot)

	asm("sti");

	// init_tasks();
	init_tasks();
	init_sync();

	pci_init();

M src/kernel/paging.c => src/kernel/paging.c +8 -0
@@ 5,6 5,14 @@
#include "log.h"
#include "pic.h"

/**
 * NOTE: In order to understand this code you should have the paging
 * section of the Intel IA-32 and 64 manual volume 3 open. Sadly I
 * have littered this with magic numbers that you will need to consult
 * the manual to understand.
 * TODO: Fix this!
 */

#define NUM_FRAMES 0xffffffff / 0x1000 / 32
/* frames bitset, 0 = free, 1 = used */
static uint frames[NUM_FRAMES];

M src/kernel/pic.c => src/kernel/pic.c +4 -2
@@ 33,7 33,8 @@ void irq_handler(struct registers regs)
	if (interrupt_handlers[regs.interrupt_number])
		interrupt_handlers[regs.interrupt_number](&regs);
	else
		kprintf(ERROR "Unhandled hardware interrupt: %d, called from %d\n", regs.interrupt_number, regs.eip);
		kprintf(ERROR "Unhandled hardware interrupt: %d, called from %d\n",
				regs.interrupt_number, regs.eip);
}

void isr_handler(struct registers regs)


@@ 41,7 42,8 @@ void isr_handler(struct registers regs)
	if (interrupt_handlers[regs.interrupt_number])
		interrupt_handlers[regs.interrupt_number](&regs);
	else
		kprintf(ERROR "Unhandled interrupt: %d, called from %d\n", regs.interrupt_number, regs.eip);
		kprintf(ERROR "Unhandled interrupt: %d, called from %d\n",
				regs.interrupt_number, regs.eip);
}

void add_interrupt_handler(uchar interrupt, void (*handler)(struct registers *))

M src/kernel/task.c => src/kernel/task.c +8 -1
@@ 81,6 81,8 @@ void spawn_thread(void (*function)(void *), void *data)
{
	asm("cli");

	kprintf(DEBUG "Spawning thread %p, data=%p\n", function, data);

	struct process *proc = current_task->task.proc;
	// Virtual address of page directory (in kernel memory)
	uint *dir_v = PHYS_TO_VIRT(proc->page_directory_p);


@@ 93,11 95,14 @@ void spawn_thread(void (*function)(void *), void *data)
	// Alloc a new page in the current process mapping to the new stack
	alloc_page(dir_v, (void *)proc->last_stack_pos);

	kprintf(INFO "new_stack_base_v = %p\n", new_stack_base_v);
	new_stack_base_v -= sizeof(uint);
	*((uint *)new_stack_base_v) = (size_t)data;
	new_stack_base_v -= sizeof(uint);
	*((uint *)new_stack_base_v) = (size_t)&kill_this_thread;

	kprintf(DEBUG "Set stack\n");

	struct ll_task_i *ll_task = malloc(sizeof(struct ll_task_i));
	memset(ll_task, 0, sizeof(struct ll_task_i));
	struct task *task = &ll_task->task;


@@ 175,9 180,11 @@ void switch_to_task(struct task *task)

void _do_switch_task(struct registers regs)
{
	// sti is called in switch_to_task
	// Resetting eflags in _switch_to_task iret will switch this back
	asm("cli");

	kprintf(DEBUG "switching tasks\n");

	// save context for this task
	current_task->task.state = regs;


M src/kernel/task_api.s => src/kernel/task_api.s +0 -26
@@ 1,29 1,3 @@
	;; This is very much the same as _switch_to_task, but we used iret
	;; and switch to ring3.
	[global _switch_to_user_task]
	;; _switch_to_user_task(uint page_directory, uint eip, uint ebp, uint esp)
_switch_to_user_task:			; (page_directory, eip, ebp, esp)
	add esp, 4					; We don't care about the return address

	pop ecx 					; Page directory
	pop eax 					; eip
	pop ebp
	pop ebx						; esp

	mov dx, 0x23				; User mode data segment
	mov ds, dx
	mov es, dx
	mov fs, dx
	mov gs, dx
	
	mov cr3, ecx 				; Set page directory

	push 0x23
	push ebx 					; esp

	sti
	jmp eax 					; Jump back to code

	[global _switch_to_task]
_switch_to_task:				; (uint page_directory, struct
								; registers regs)