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.
diff --git a/include/kernel/log.h b/include/kernel/log.h
index a4ae42b..78a7047 100644
--- a/include/kernel/log.h
+++ b/include/kernel/log.h
@@ -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,
diff --git a/include/kernel/task.h b/include/kernel/task.h
index 38ff7ee..3126180 100644
--- a/include/kernel/task.h
+++ b/include/kernel/task.h
@@ -23,6 +23,7 @@
 	// NOTE: must be PAGE ALIGNED
 	uint last_stack_pos;
 };
+
 /**
  * The smallest schedulable unit, a thread of a process.
  */
diff --git a/src/kernel/idt.s b/src/kernel/idt.s
index 1b70054..5ed637e 100644
--- a/src/kernel/idt.s
+++ b/src/kernel/idt.s
@@ -40,11 +40,11 @@
 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
diff --git a/src/kernel/main.c b/src/kernel/main.c
index b61efda..17a54d7 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -65,7 +65,7 @@
 
 	asm("sti");
 
-	// init_tasks();
+	init_tasks();
 	init_sync();
 
 	pci_init();
diff --git a/src/kernel/paging.c b/src/kernel/paging.c
index f1fd125..f959a92 100644
--- a/src/kernel/paging.c
+++ b/src/kernel/paging.c
@@ -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];
diff --git a/src/kernel/pic.c b/src/kernel/pic.c
index e4ed88c..8c18097 100644
--- a/src/kernel/pic.c
+++ b/src/kernel/pic.c
@@ -33,7 +33,8 @@
 	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 @@
 	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 *))
diff --git a/src/kernel/task.c b/src/kernel/task.c
index 85cce5b..1ec1337 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -81,6 +81,8 @@
 {
 	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 @@
 	// 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 _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;
 
diff --git a/src/kernel/task_api.s b/src/kernel/task_api.s
index 5c7eaa9..fce9811 100644
--- a/src/kernel/task_api.s
+++ b/src/kernel/task_api.s
@@ -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)