Initial x86 port
diff --git a/arch/arm/crt0.S b/arch/arm/crt0.S
index 68dbc67..f567574 100644
--- a/arch/arm/crt0.S
+++ b/arch/arm/crt0.S
@@ -187,3 +187,14 @@
 abort_stack:
 	.skip 1024
 abort_stack_top:
+
+.rodata:
+.align 2
+
+/* define the heap end as read-only data containing the end defined in the
+ * linker script. other archs that use dynamic memory length discovery can make
+ * this read-write and update it during init.
+ */
+.global _heap_end
+_heap_end:
+	.int _end_of_ram
diff --git a/arch/x86/arch.c b/arch/x86/arch.c
new file mode 100644
index 0000000..99ca572
--- /dev/null
+++ b/arch/x86/arch.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch.h>
+#include <arch/ops.h>
+#include <arch/x86.h>
+#include <arch/x86/mmu.h>
+#include <arch/x86/descriptor.h>
+#include <platform.h>
+#include <sys/types.h>
+#include <string.h>
+
+static tss_t system_tss;
+
+void arch_early_init(void)
+{
+	x86_mmu_init();
+
+	platform_init_mmu_mappings();
+	
+	/* enable caches here for now */
+	clear_in_cr0(X86_CR0_NW | X86_CR0_CD);
+	
+	memset(&system_tss, 0, sizeof(tss_t));
+	
+	system_tss.esp0 = 0;
+	system_tss.ss0 = DATA_SELECTOR;
+	system_tss.ss1 = 0;
+	system_tss.ss2 = 0;
+	system_tss.eflags = 0x00003002;
+	system_tss.bitmap = offsetof(tss_t, tss_bitmap);
+	system_tss.trace = 1; // trap on hardware task switch
+	
+	set_global_desc(TSS_SELECTOR, &system_tss, sizeof(tss_t), 1, 0, 0, SEG_TYPE_TSS, 0, 0);
+
+	x86_ltr(TSS_SELECTOR);
+}
+
+void arch_init(void)
+{
+}
+
diff --git a/arch/x86/asm.S b/arch/x86/asm.S
new file mode 100644
index 0000000..4d7763c
--- /dev/null
+++ b/arch/x86/asm.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+
+	/* context switch frame is as follows:
+	 * ulr
+	 * usp
+	 * lr
+	 * r11
+	 * r10
+	 * r9
+	 * r8
+	 * r7
+	 * r6
+	 * r5
+	 * r4
+	 */
+/* x86_context_switch(addr_t *old_sp, addr_t new_sp) */
+FUNCTION(x86_context_switch)
+	/* TODO */
+	ret
diff --git a/arch/x86/cache-ops.S b/arch/x86/cache-ops.S
new file mode 100644
index 0000000..9ad7c71
--- /dev/null
+++ b/arch/x86/cache-ops.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+#include <arch/ops.h>
+#include <arch/defines.h>
+
+.text
+
+/* stubs */
+
+FUNCTION(arch_disable_cache)
+	ret
+
+FUNCTION(arch_enable_cache)
+	ret
+
+FUNCTION(arch_clean_cache_range)
+	ret
+
+FUNCTION(arch_clean_invalidate_cache_range)
+	ret
+
diff --git a/arch/x86/cache.c b/arch/x86/cache.c
new file mode 100644
index 0000000..b00d6cc
--- /dev/null
+++ b/arch/x86/cache.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
diff --git a/arch/x86/compile.mk b/arch/x86/compile.mk
new file mode 100644
index 0000000..271db17
--- /dev/null
+++ b/arch/x86/compile.mk
@@ -0,0 +1,16 @@
+
+$(BUILDDIR)/%.o: %.c $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.S $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
diff --git a/arch/x86/crt0.S b/arch/x86/crt0.S
new file mode 100644
index 0000000..9cc9ab0
--- /dev/null
+++ b/arch/x86/crt0.S
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#if defined(__ELF__) && 0
+#define MULTIBOOT_HEADER_FLAGS 0x00000002
+#else
+#define MULTIBOOT_HEADER_FLAGS 0x00010002
+#endif
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+#define NUM_INT 0x31
+#define NUM_EXC 0x14
+
+.text
+.global _start
+_start:
+	jmp real_start
+
+.align 4
+
+multiboot_header:
+	/* magic */
+	.int MULTIBOOT_HEADER_MAGIC
+	/* flags */
+	.int MULTIBOOT_HEADER_FLAGS
+	/* checksum */
+	.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+
+#if !defined(__ELF__) || 1
+	/* header_addr */
+	.int multiboot_header
+	/* load_addr */
+	.int _start
+	/* load_end_addr */
+	.int __bss_start
+	/* bss_end_addr */
+	.int __bss_end
+	/* entry_addr */
+	.int real_start
+#endif
+
+real_start:
+	cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+	jne 0f
+	movl %ebx, (_multiboot_info)
+0:
+	/* setup isr stub descriptors in the idt */
+	movl $_isr, %esi
+	movl $_idt, %edi
+	movl $NUM_INT, %ecx
+	
+.Lloop:
+	movl %esi, %ebx
+	movw %bx, (%edi)		/* low word in IDT(n).low */
+	shrl $16, %ebx
+	movw %bx, 6(%edi)		/* high word in IDT(n).high */
+	
+	addl $isr_stub_len, %esi/* index the next ISR stub */
+	addl $8, %edi			/* index the next IDT entry */
+	
+	loop .Lloop
+	
+	lidt _idtr
+	xorl %eax, %eax
+	movl %eax, %cr3
+
+	lgdt _gdtr
+		
+	movw $datasel, %ax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %fs
+	movw %ax, %ss
+	movw %ax, %gs
+	movw %ax, %ss
+	
+	movl $_kstack, %esp
+	
+	/* zero the bss section */
+	movl $__bss_start, %edi	/* starting address of the bss */
+	movl $__bss_end, %ecx	/* find the length of the bss in bytes */
+	subl %edi, %ecx
+	shrl $2, %ecx			/* convert to 32 bit words, since the bss is aligned anyway */
+2:
+	movl $0, (%edi)
+	addl $4, %edi
+	loop 2b
+	
+	/* call the main module */
+	call kmain
+	
+0:							/* just sit around waiting for interrupts */
+	hlt						/* interrupts will unhalt the processor */
+	pause
+	jmp 0b					/* so jump back to halt to conserve power */
+
+/* interrupt service routine stubs */
+_isr:
+
+.set i, 0
+.rept NUM_INT
+
+.set isr_stub_start, .
+
+.if i == 8 || (i >= 10 && i <= 14) || i == 17
+	nop						/* error code pushed by exception */
+	nop						/* 2 nops are the same length as push byte */
+	pushl $i				/* interrupt number */
+	jmp interrupt_common
+.else
+	pushl $0				/* fill in error code in iframe */
+	pushl $i				/* interrupt number */
+	jmp interrupt_common
+.endif
+
+/* figure out the length of a single isr stub (usually 6 or 9 bytes) */
+.set isr_stub_len, . - isr_stub_start
+
+.set i, i + 1
+.endr
+
+/* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
+.fill 256
+
+interrupt_common:
+	pushl %gs				/* save segment registers */
+	pushl %fs
+	pushl %es
+	pushl %ds
+	pusha					/* save general purpose registers */
+	movl $datasel, %eax		/* put known good value in segment registers */
+	movl %eax, %gs
+	movl %eax, %fs
+	movl %eax, %es
+	movl %eax, %ds
+	movl %esp, %eax			/* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
+	pushl %eax
+	movl %esp, %eax			/* store pointer to iframe, using same method */
+	pushl %eax
+	
+	incl critical_section_count
+
+	call platform_irq
+	
+	cmpl $0,%eax
+	je 0f
+	call thread_preempt
+
+0:
+	decl critical_section_count
+
+	popl %eax				/* drop pointer to iframe */
+	popl %eax				/* restore task_esp, stack switch can occur here if task_esp is modified */
+	movl %eax, %esp
+	popa					/* restore general purpose registers */
+	popl %ds				/* restore segment registers */
+	popl %es
+	popl %fs
+	popl %gs
+	addl $8, %esp			/* drop exception number and error code */
+	iret
+
+.data
+.align 4
+
+/* define the heap end as read-write data containing the default end of the
+ * heap. dynamic memory length discovery can update this value during init.
+ * other archs can define this statically based on the memory layout of the
+ * platform.
+ */
+.global _heap_end
+_heap_end:
+	.int 4096*1024	/* default to 4MB total */
+
+.global _multiboot_info
+_multiboot_info:
+	.int 0
+
+.global _gdtr
+_gdtr:
+	.short _gdt_end - _gdt - 1
+	.int _gdt
+
+.global _gdt
+_gdt:
+	.int 0
+	.int 0
+
+/* ring 0 descriptors */
+.set codesel, . - _gdt
+_code_gde:
+	.short 0xffff			/* limit 15:00 */
+	.short 0x0000			/* base 15:00 */
+	.byte  0x00				/* base 23:16 */
+	.byte  0b10011010		/* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
+	.byte  0b11001111		/* G(1) D(1) 0 0 limit 19:16 */
+	.byte  0x0				/* base 31:24 */
+	
+.set datasel, . - _gdt
+_data_gde:
+	.short 0xffff			/* limit 15:00 */
+	.short 0x0000			/* base 15:00 */
+	.byte  0x00				/* base 23:16 */
+	.byte  0b10010010		/* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
+	.byte  0b11001111		/* G(1) B(1) 0 0 limit 19:16 */
+	.byte  0x0				/* base 31:24 */
+	
+.set videosel, . - _gdt
+_video_gde:
+	.short 0xffff			/* limit 15:00 */
+	.short 0x8000			/* base 15:00 */
+	.byte  0x0b				/* base 23:16 */
+	.byte  0b10010010		/* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
+	.byte  0b11001111		/* G(1) B(1) 0 0 limit 19:16 */
+	.byte  0x0				/* base 31:24 */
+	
+.if 1
+/* ring 3 descriptors */
+.set user_codesel, . - _gdt
+_user_code_gde:
+	.short 0xffff			/* limit 15:00 */
+	.short 0x0000			/* base 15:00 */
+	.byte  0x00				/* base 23:16 */
+	.byte  0b11111010		/* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
+	.byte  0b11001111		/* G(1) D(1) 0 0 limit 19:16 */
+	.byte  0x0				/* base 31:24 */
+	
+.set user_datasel, . - _gdt
+_user_data_gde:
+	.short 0xffff			/* limit 15:00 */
+	.short 0x0000			/* base 15:00 */
+	.byte  0x00				/* base 23:16 */
+	.byte  0b11110010		/* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
+	.byte  0b11001111		/* G(1) B(1) 0 0 limit 19:16 */
+	.byte  0x0				/* base 31:24 */
+.endif
+
+/* TSS descriptor */
+.if 1
+.set tsssel, . - _gdt
+_tss_gde:
+	.short 0				/* limit 15:00 */
+	.short 0				/* base 15:00 */
+	.byte  0				/* base 23:16 */
+	.byte  0xe9				/* P(1) DPL(11) 0 10 B(0) 1 */
+	.byte  0x00				/* G(0) 0 0 AVL(0) limit 19:16 */
+	.short 0				/* base 31:24 */
+.endif
+
+.global _gdt_end
+_gdt_end:
+
+.global _idtr
+_idtr:
+	.short _idt_end - _idt - 1	/* IDT limit */
+	.int _idt
+
+/* interrupt descriptor table (IDT) */
+.global _idt
+_idt:
+
+.set i, 0
+.rept NUM_INT-1
+	.short 0				/* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
+	.short codesel			/* selector */
+	.byte  0
+	.byte  0x8e				/* present, ring 0, 32-bit interrupt gate */
+	.short 0				/* high 16 bits of ISR offset (_isr#i / 65536) */
+	
+.set i, i + 1
+.endr
+
+/* syscall int (ring 3) */
+_idt30:
+	.short 0				/* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
+	.short codesel			/* selector */
+	.byte  0
+	.byte  0xee				/* present, ring 3, 32-bit interrupt gate */
+	.short 0				/* high 16 bits of ISR offset (_isr#i / 65536) */
+
+.global _idt_end
+_idt_end:
+
+.bss
+.align 4096
+
+.global _kstack
+.fill 4096
+_kstack:
diff --git a/arch/x86/descriptor.c b/arch/x86/descriptor.c
new file mode 100644
index 0000000..27ee37e
--- /dev/null
+++ b/arch/x86/descriptor.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <compiler.h>
+#include <arch/x86/descriptor.h>
+
+/* not the best way to do this, but easy for now */
+typedef struct {
+	uint16_t limit_15_0;
+	uint16_t base_15_0;
+	uint8_t base_23_16;
+	
+	uint8_t type : 4;
+	uint8_t s : 1;
+	uint8_t dpl : 2;
+	uint8_t p : 1;
+	
+	uint8_t limit_19_16 : 4;
+	uint8_t avl : 1;
+	uint8_t reserved_0 : 1;
+	uint8_t d_b : 1;
+	uint8_t g : 1;
+	
+	uint8_t base_31_24;
+} __PACKED seg_desc_t;
+
+extern seg_desc_t _gdt[];
+
+void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
+	uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits)
+{
+	// convert selector into index
+	uint16_t index = sel >> 3;
+
+	_gdt[index].limit_15_0 = limit & 0x0000ffff;
+	_gdt[index].limit_19_16 = (limit & 0x000f0000) >> 16;
+
+	_gdt[index].base_15_0 = ((uint32_t) base) & 0x0000ffff;
+	_gdt[index].base_23_16 = (((uint32_t) base) & 0x00ff0000) >> 16;
+	_gdt[index].base_31_24 = ((uint32_t) base) >> 24;
+
+	_gdt[index].type = type & 0x0f;	// segment type
+	_gdt[index].p = present != 0;	// present
+	_gdt[index].dpl = ring & 0x03;	// descriptor privilege level
+	_gdt[index].g = gran != 0;		// granularity
+	_gdt[index].s = sys != 0;		// system / non-system
+	_gdt[index].d_b = bits != 0;	// 16 / 32 bit
+}
diff --git a/arch/x86/faults.c b/arch/x86/faults.c
new file mode 100644
index 0000000..3d4c8d2
--- /dev/null
+++ b/arch/x86/faults.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch/x86.h>
+#include <kernel/thread.h>
+
+static void dump_fault_frame(struct x86_iframe *frame)
+{
+	dprintf(CRITICAL, " CS:     %04x EIP: %08x EFL: %08x CR2: %08x\n",
+		frame->cs, frame->eip, frame->eflags, x86_get_cr2());
+	dprintf(CRITICAL, "EAX: %08x ECX: %08x EDX: %08x EBX: %08x\n",
+		frame->eax, frame->ecx, frame->edx, frame->ebx);
+	dprintf(CRITICAL, "ESP: %08x EBP: %08x ESI: %08x EDI: %08x\n",
+		frame->esp, frame->ebp, frame->esi, frame->edi);
+	dprintf(CRITICAL, " DS:     %04x  ES:     %04x  FS:     %04x  GS:     %04x\n",
+		frame->ds, frame->es, frame->fs, frame->gs);
+
+	// dump the bottom of the current stack
+	addr_t stack = (addr_t) frame; //(addr_t) (((uint32_t *) frame) + (sizeof(struct x86_iframe) / sizeof(uint32_t) - 1));
+
+	if (stack != 0) {
+		dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
+		hexdump((void *)stack, 192);
+	}
+}
+
+static void exception_die(struct x86_iframe *frame, const char *msg)
+{
+	inc_critical_section();
+	dprintf(CRITICAL, msg);
+	dump_fault_frame(frame);
+	
+	for (;;) {
+		x86_cli();
+		x86_hlt();
+	}
+}
+
+void x86_syscall_handler(struct x86_iframe *frame)
+{
+	exception_die(frame, "unhandled syscall, halting\n");
+}
+
+void x86_gpf_handler(struct x86_iframe *frame)
+{
+	exception_die(frame, "unhandled gpf, halting\n");	
+}
+
+void x86_invop_handler(struct x86_iframe *frame)
+{
+	exception_die(frame, "unhandled invalid op, halting\n");	
+}
+
+void x86_unhandled_exception(struct x86_iframe *frame)
+{
+	exception_die(frame, "unhandled exception, halting\n");	
+}
diff --git a/arch/x86/include/arch/arch_thread.h b/arch/x86/include/arch/arch_thread.h
new file mode 100644
index 0000000..9347bcd
--- /dev/null
+++ b/arch/x86/include/arch/arch_thread.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __X86_ARCH_THREAD_H
+#define __X86_ARCH_THREAD_H
+
+struct arch_thread {
+	vaddr_t esp;
+	
+	// TODO: fpu context
+};
+
+#endif
+
diff --git a/arch/x86/include/arch/defines.h b/arch/x86/include/arch/defines.h
new file mode 100644
index 0000000..814fcc9
--- /dev/null
+++ b/arch/x86/include/arch/defines.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_CPU_H
+#define __ARCH_CPU_H
+
+#define PAGE_SIZE 4096
+
+// TODO: define to resolve to platform setup discovered value
+#define CACHE_LINE 32
+
+#endif
+
diff --git a/arch/x86/include/arch/x86.h b/arch/x86/include/arch/x86.h
new file mode 100644
index 0000000..4cf65d9
--- /dev/null
+++ b/arch/x86/include/arch/x86.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_X86_H
+#define __ARCH_X86_H
+
+#include <compiler.h>
+#include <sys/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void x86_mmu_init(void);
+
+struct x86_iframe {
+	uint32_t pivot;										// stack switch pivot
+	uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;	// pushed by common handler using pusha
+	uint32_t ds, es, fs, gs;							// pushed by common handler
+	uint32_t vector;									// pushed by stub
+	uint32_t err_code;									// pushed by interrupt or stub
+	uint32_t eip, cs, eflags;							// pushed by interrupt
+	uint32_t user_esp, user_ss;							// pushed by interrupt if priv change occurs
+};
+
+/*
+ * x86 TSS structure
+ */
+typedef struct {
+	uint16_t	backlink, __blh;
+	uint32_t	esp0;
+	uint16_t	ss0, __ss0h;
+	uint32_t	esp1;
+	uint16_t	ss1, __ss1h;
+	uint32_t	esp2;
+	uint16_t	ss2, __ss2h;
+	uint32_t	cr3;
+	uint32_t	eip;
+	uint32_t	eflags;
+	uint32_t	eax, ecx, edx, ebx;
+	uint32_t	esp, ebp, esi, edi;
+	uint16_t	es, __esh;
+	uint16_t	cs, __csh;
+	uint16_t	ss, __ssh;
+	uint16_t	ds, __dsh;
+	uint16_t	fs, __fsh;
+	uint16_t	gs, __gsh;
+	uint16_t	ldt, __ldth;
+	uint16_t	trace, bitmap;
+	
+	uint8_t tss_bitmap[8192];
+} __PACKED tss_t;
+
+#define X86_CR0_PE		0x00000001 /* protected mode enable */
+#define X86_CR0_MP		0x00000002 /* monitor coprocessor */
+#define X86_CR0_EM		0x00000004 /* emulation */
+#define X86_CR0_TS		0x00000008 /* task switched */
+#define X86_CR0_WP		0x00010000 /* supervisor write protect */
+#define X86_CR0_NW		0x20000000 /* not write-through */
+#define X86_CR0_CD		0x40000000 /* cache disable */
+#define X86_CR0_PG		0x80000000 /* enable paging */
+
+static inline void set_in_cr0(uint32_t mask) {
+	__asm__ __volatile__ (
+		"movl %%cr0,%%eax	\n\t"
+		"orl %0,%%eax		\n\t"
+		"movl %%eax,%%cr0	\n\t"
+		: : "irg" (mask)
+		:"ax");
+}
+
+static inline void clear_in_cr0(uint32_t mask) {
+	__asm__ __volatile__ (
+		"movl %%cr0, %%eax	\n\t"
+		"andl %0, %%eax		\n\t"
+		"movl %%eax, %%cr0	\n\t"
+		: : "irg" (~mask)
+		: "ax");
+}
+
+static inline void x86_clts(void) {__asm__ __volatile__ ("clts"); }
+static inline void x86_hlt(void) {__asm__ __volatile__ ("hlt"); }
+static inline void x86_sti(void) {__asm__ __volatile__ ("sti"); }
+static inline void x86_cli(void) {__asm__ __volatile__ ("cli"); }
+static inline void x86_ltr(uint16_t sel) {
+	__asm__ __volatile__ ("ltr %%ax" :: "a" (sel));
+}
+
+static inline uint32_t x86_get_cr2(void) {
+	uint32_t rv;
+	
+	__asm__ __volatile__ (
+		"movl %%cr2, %0"
+		: "=r" (rv)
+	);
+	
+	return rv;
+}
+
+#define rdtsc(low,high) \
+     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscl(low) \
+     __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
+
+#define rdtscll(val) \
+     __asm__ __volatile__("rdtsc" : "=A" (val))
+
+static inline uint8_t inp(uint16_t _port) {
+    uint8_t rv;
+    __asm__ __volatile__ ("inb %1, %0"
+	  : "=a" (rv)
+	  : "d" (_port));
+    return(rv);
+}
+
+static inline uint16_t inpw (uint16_t _port) {
+    uint16_t rv;
+    __asm__ __volatile__ ("inw %1, %0"
+	  : "=a" (rv)
+	  : "d" (_port));
+    return(rv);
+}
+
+static inline uint32_t inpd(uint16_t _port) {
+    uint32_t rv;
+    __asm__ __volatile__ ("inl %1, %0"
+	  : "=a" (rv)
+	  : "d" (_port));
+    return(rv);
+}
+
+static inline void outp(uint16_t _port, uint8_t _data) {
+    __asm__ __volatile__ ("outb %1, %0"
+	  :
+	  : "d" (_port),
+	    "a" (_data));
+}
+
+static inline void outpw(uint16_t _port, uint16_t _data) {
+    __asm__ __volatile__ ("outw %1, %0"
+	  :
+	  : "d" (_port),
+	    "a" (_data));
+}
+
+static inline void outpd(uint16_t _port, uint32_t _data) {
+    __asm__ __volatile__ ("outl %1, %0"
+	  :
+	  : "d" (_port),
+	    "a" (_data));
+}
+
+static inline void inprep(uint16_t _port, uint8_t *_buffer, uint32_t _reads) {
+	__asm__ __volatile__ ("pushal \n\t"	
+		"pushfl \n\t"	
+		"cli \n\t"	
+		"cld \n\t"	
+		"rep insb \n\t"	
+		"popfl \n\t"	
+		"popal"	
+		:
+		: "d" (_port),
+		  "D" (_buffer),
+		  "c" (_reads));
+}
+
+static inline void outprep(uint16_t _port, uint8_t *_buffer, uint32_t _writes) {
+	__asm__ __volatile__ ("pushal \n\t"
+		"pushfl \n\t"
+		"cli \n\t"
+		"cld \n\t"
+		"rep outsb \n\t"
+		"popfl \n\t"
+		"popal"
+		:
+		: "d" (_port),
+		  "S" (_buffer),
+		  "c" (_writes));
+}
+
+static inline void inpwrep(uint16_t _port, uint16_t *_buffer, uint32_t _reads) {
+	__asm__ __volatile__ ("pushal \n\t"	
+		"pushfl \n\t"	
+		"cli \n\t"	
+		"cld \n\t"	
+		"rep insw \n\t"	
+		"popfl \n\t"	
+		"popal"	
+		:
+		: "d" (_port),
+		  "D" (_buffer),
+		  "c" (_reads));
+}
+
+static inline void outpwrep(uint16_t _port, uint16_t *_buffer,
+	uint32_t _writes) {
+	__asm__ __volatile__ ("pushal \n\t"
+		"pushfl \n\t"
+		"cli \n\t"
+		"cld \n\t"
+		"rep outsw \n\t"
+		"popfl \n\t"
+		"popal"
+		:
+		: "d" (_port),
+		  "S" (_buffer),
+		  "c" (_writes));
+}
+
+static inline void inpdrep(uint16_t _port, uint32_t *_buffer,
+	uint32_t _reads) {
+	__asm__ __volatile__ ("pushal \n\t"	
+		"pushfl \n\t"	
+		"cli \n\t"	
+		"cld \n\t"	
+		"rep insl \n\t"	
+		"popfl \n\t"	
+		"popal"	
+		:
+		: "d" (_port),
+		  "D" (_buffer),
+		  "c" (_reads));
+}
+
+static inline void outpdrep(uint16_t _port, uint32_t *_buffer,
+	uint32_t _writes) {
+	__asm__ __volatile__ ("pushal \n\t"
+		"pushfl \n\t"
+		"cli \n\t"
+		"cld \n\t"
+		"rep outsl \n\t"
+		"popfl \n\t"
+		"popal"
+		:
+		: "d" (_port),
+		  "S" (_buffer),
+		  "c" (_writes));
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/x86/include/arch/x86/descriptor.h b/arch/x86/include/arch/x86/descriptor.h
new file mode 100644
index 0000000..1b2580d
--- /dev/null
+++ b/arch/x86/include/arch/x86/descriptor.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_DESCRIPTOR_H
+#define __ARCH_DESCRIPTOR_H
+
+#include <sys/types.h>
+
+/*
+ * System Selectors
+ */
+#define CODE_SELECTOR	0x08
+#define DATA_SELECTOR	0x10
+#define VIDEO_SELECTOR	0x18
+#define TSS_SELECTOR	0x30
+
+#define USER_CODE_SELECTOR 0x23
+#define USER_DATA_SELECTOR 0x2b
+
+/*
+ * Descriptor Types
+ */
+#define SEG_TYPE_TSS		0x9
+#define SEG_TYPE_TSS_BUSY	0xb
+#define SEG_TYPE_TASK_GATE	0x5
+#define SEG_TYPE_INT_GATE	0xe		// 32 bit
+#define SEG_TYPE_DATA_RW	0x2
+#define SEG_TYPE_CODE_RW	0xa
+
+typedef uint16_t seg_sel_t;
+
+void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
+	uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits);
+
+#endif
diff --git a/arch/x86/include/arch/x86/mmu.h b/arch/x86/include/arch/x86/mmu.h
new file mode 100644
index 0000000..719710c
--- /dev/null
+++ b/arch/x86/include/arch/x86/mmu.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_ARM_MMU_H
+#define __ARCH_ARM_MMU_H
+
+#include <sys/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void arm_mmu_init(void);
+
+#define MMU_FLAG_CACHED 0x1
+#define MMU_FLAG_BUFFERED 0x2
+#define MMU_FLAG_READWRITE 0x4
+void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/x86/include/arch/x86/ops.h b/arch/x86/include/arch/x86/ops.h
new file mode 100644
index 0000000..d2bbc24
--- /dev/null
+++ b/arch/x86/include/arch/x86/ops.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_X86_OPS_H
+#define __ARHC_X86_OPS_H
+
+#if 0
+#include <compiler.h>
+
+#ifndef ASSEMBLY
+
+// override of some routines
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
+{
+	__asm__ __volatile__ ("sti");
+}
+
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
+{
+	__asm__ __volatile__ ("cli");
+}
+
+#endif
+#endif
+
+#endif
+
diff --git a/arch/x86/kernel.ld b/arch/x86/kernel.ld
new file mode 100644
index 0000000..1e3abba
--- /dev/null
+++ b/arch/x86/kernel.ld
@@ -0,0 +1,83 @@
+/*

+ * Copyright (c) 2009 Corey Tabaka

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining

+ * a copy of this software and associated documentation files

+ * (the "Software"), to deal in the Software without restriction,

+ * including without limitation the rights to use, copy, modify, merge,

+ * publish, distribute, sublicense, and/or sell copies of the Software,

+ * and to permit persons to whom the Software is furnished to do so,

+ * subject to the following conditions:

+ *

+ * The above copyright notice and this permission notice shall be

+ * included in all copies or substantial portions of the Software.

+ *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY

+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,

+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ */

+

+ENTRY(_start)

+SECTIONS

+{

+	.text 0x0200000 : {

+		*(.text)

+		*(SORT(.text$*))

+		*(.gnu.linkonce.t.*)

+		

+		__ctor_list = .;

+		*(SORT(.ctor*))

+		__ctor_end = .;

+		__dtor_list = .;

+		*(SORT(.dtor*))

+		__dtor_end = .;

+		

+		. = ALIGN(4096);

+	}

+	

+	__data_start = .;

+	.data		: { *(.data .data.* .gnu.linkonce.d.*) }

+	.stab		: { *(.stab) }

+	.stabst		: { *(.stabstr) }

+	

+	. = ALIGN(4096);

+	__data_end = .;

+	

+	.rdata		: {

+		*(.rdata)

+		*(SORT(.rdata$*))

+		*(.rodata*)

+		*(.gnu.linkonce.r.*)

+		__commands_start = .;

+		KEEP (*(.commands))

+		__commands_end = .;

+		. = ALIGN(4);

+		__apps_start = .;

+		KEEP (*(.apps))

+		__apps_end = .;

+		

+		. = ALIGN(4096);

+	}

+	

+	__bss_start = .;

+	.bss		: {

+		*(.bss*)

+		*(.gnu.linkonce.b.*)

+		*(COMMON)

+		

+		. = ALIGN(4096);

+	}

+	__bss_end = .;

+	

+	/*. += 0x2000;

+	_kstack = .;

+	. += 0x1000;*/

+	

+	_end = .;

+	

+	/DISCARD/ : { *(.comment .note .eh_frame) }

+}

diff --git a/arch/x86/mmu.c b/arch/x86/mmu.c
new file mode 100644
index 0000000..6cefe67
--- /dev/null
+++ b/arch/x86/mmu.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <sys/types.h>
+#include <compiler.h>
+#include <arch.h>
+#include <arch/x86.h>
+#include <arch/x86/mmu.h>
+
+void x86_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
+{
+	// TODO: stuff
+	//x86_invalidate_tlb();
+}
+
+void x86_mmu_init(void)
+{
+	// TODO: stuff
+}
+
+void arch_disable_mmu(void)
+{
+	// TODO: stuff
+}
diff --git a/arch/x86/ops.S b/arch/x86/ops.S
new file mode 100644
index 0000000..17c08ae
--- /dev/null
+++ b/arch/x86/ops.S
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+.text
+
+/* void arch_enable_ints(void); */
+FUNCTION(arch_enable_ints)
+	sti
+	ret
+
+/* void arch_disable_ints(void); */
+FUNCTION(arch_disable_ints)
+	cli
+	ret
+
+/* int atomic_swap(int *ptr, int val); */
+FUNCTION(atomic_swap)
+	movl 4(%esp), %edx
+	movl 8(%esp), %eax
+	xchgl %eax, (%edx)
+	ret
+
+/* int atomic_add(int *ptr, int val); */
+FUNCTION(atomic_add)
+	movl 4(%esp), %edx
+	movl 8(%esp), %eax
+	lock
+	xadd %eax, (%edx)
+	ret
+	
+/* int atomic_and(int *ptr, int val); */
+FUNCTION(atomic_and)
+	movl 4(%esp), %edx
+	movl (%edx), %eax
+0:
+	movl %eax, %ecx
+	andl 8(%esp), %ecx
+	lock
+	cmpxchgl %ecx, (%edx)
+	jnz 1f					/* static prediction: branch forward not taken */
+	ret
+1:
+	jmp 0b
+	
+	
+/* int atomic_or(int *ptr, int val); */
+FUNCTION(atomic_or)
+movl 4(%esp), %edx
+	movl (%edx), %eax
+0:
+	movl %eax, %ecx
+	orl 8(%esp), %ecx
+	lock
+	cmpxchgl %ecx, (%edx)
+	jnz 1f					/* static prediction: branch forward not taken */
+	ret
+1:
+	jmp 0b
+
+/* void arch_idle(); */
+FUNCTION(arch_idle)
+	hlt
+	ret
+
+/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
+FUNCTION(arch_switch_stacks_and_call)
+	movl 4(%esp), %eax
+	movl 8(%esp), %edx
+	movl %edx, %esp
+	call *%eax			/* perhaps this should be a jmp? it's not used anywhere so I don't know. */
diff --git a/arch/x86/rules.mk b/arch/x86/rules.mk
new file mode 100644
index 0000000..943ccd8
--- /dev/null
+++ b/arch/x86/rules.mk
@@ -0,0 +1,35 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+BOOTOBJS += \
+	$(LOCAL_DIR)/crt0.o
+
+OBJS += \
+	$(LOCAL_DIR)/arch.o \
+	$(LOCAL_DIR)/asm.o \
+	$(LOCAL_DIR)/cache.o \
+	$(LOCAL_DIR)/cache-ops.o \
+	$(LOCAL_DIR)/ops.o \
+	$(LOCAL_DIR)/thread.o \
+	$(LOCAL_DIR)/mmu.o \
+	$(LOCAL_DIR)/faults.o \
+	$(LOCAL_DIR)/descriptor.o
+
+# set the default toolchain to x86 elf and set a #define
+TOOLCHAIN_PREFIX ?= #x86-elf-
+
+LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -print-libgcc-file-name)
+#$(info LIBGCC = $(LIBGCC))
+
+# potentially generated files that should be cleaned out with clean make rule
+GENERATED += \
+	$(BUILDDIR)/kernel.ld
+
+# rules for generating the linker scripts
+
+$(BUILDDIR)/kernel.ld: $(LOCAL_DIR)/kernel.ld
+	@echo generating $@
+	@$(MKDIR)
+	$(NOECHO)cp $< $@
diff --git a/arch/x86/thread.c b/arch/x86/thread.c
new file mode 100644
index 0000000..f2c2f84
--- /dev/null
+++ b/arch/x86/thread.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <arch/x86.h>
+#include <arch/x86/descriptor.h>
+
+/*struct context_switch_frame {
+	uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+	uint32_t ds, es, fs, gs;
+	uint32_t eip, cs, eflags;
+};*/
+struct context_switch_frame {
+	uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+	uint32_t eflags;
+	uint32_t eip;
+};
+
+extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
+
+static void initial_thread_func(void) __NO_RETURN;
+static void initial_thread_func(void)
+{
+	int ret;
+
+//	dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
+//	dump_thread(current_thread);
+
+	/* exit the implicit critical section we're within */
+	exit_critical_section();
+
+	ret = current_thread->entry(current_thread->arg);
+
+//	dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
+
+	thread_exit(ret);
+}
+
+void arch_thread_initialize(thread_t *t)
+{
+	// create a default stack frame on the stack
+	vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
+
+	// make sure the top of the stack is 8 byte aligned for EABI compliance
+	stack_top = ROUNDDOWN(stack_top, 8);
+
+	struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
+	frame--;
+
+	// fill it in
+	memset(frame, 0, sizeof(*frame));
+	
+	frame->eip = (vaddr_t) &initial_thread_func;
+	frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
+	//frame->cs = CODE_SELECTOR;
+	//frame->fs = DATA_SELECTOR;
+	//frame->gs = DATA_SELECTOR;
+	//frame->es = DATA_SELECTOR;
+	//frame->ds = DATA_SELECTOR;
+	
+	// set the stack pointer
+	t->arch.esp = (vaddr_t)frame;
+}
+
+void arch_context_switch(thread_t *oldthread, thread_t *newthread)
+{
+	//dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
+	
+	__asm__ __volatile__ (
+		"pushl $1f			\n\t"
+		"pushf				\n\t"
+		"pusha				\n\t"
+		"movl %%esp,(%%edx)	\n\t"
+		"movl %%eax,%%esp	\n\t"
+		"popa				\n\t"
+		"popf				\n\t"
+		"ret				\n\t"
+		"1:					\n\t"
+		
+		:
+		: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
+	);
+	
+	/*__asm__ __volatile__ (
+		"pushf				\n\t"
+		"pushl %%cs			\n\t"
+		"pushl $1f			\n\t"
+		"pushl %%gs			\n\t"
+		"pushl %%fs			\n\t"
+		"pushl %%es			\n\t"
+		"pushl %%ds			\n\t"
+		"pusha				\n\t"
+		"movl %%esp,(%%edx)	\n\t"
+		"movl %%eax,%%esp	\n\t"
+		"popa				\n\t"
+		"popl %%ds			\n\t"
+		"popl %%es			\n\t"
+		"popl %%fs			\n\t"
+		"popl %%gs			\n\t"
+		"iret				\n\t"
+		"1:	"
+		:
+		: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
+	);*/
+}
+
diff --git a/include/endian.h b/include/endian.h
index 30623b2..34bef6e 100644
--- a/include/endian.h
+++ b/include/endian.h
@@ -40,6 +40,10 @@
 #define BYTE_ORDER LITTLE_ENDIAN
 #endif
 
+#if defined(__i386__) || defined(_X86_)
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
 #ifndef BYTE_ORDER
 #error "need to get the BYTE_ORDER define from somewhere"
 #endif
diff --git a/lib/heap/heap.c b/lib/heap/heap.c
index c67bc25..afcb975 100644
--- a/lib/heap/heap.c
+++ b/lib/heap/heap.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008 Travis Geiselbrecht
+ * Copyright (c) 2009 Corey Tabaka
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files
@@ -45,10 +46,10 @@
 extern int _end;
 
 // end of memory
-extern int _end_of_ram;
+extern int _heap_end;
 
 #define HEAP_START ((unsigned long)&_end)
-#define HEAP_LEN ((size_t)&_end_of_ram - (size_t)&_end)
+#define HEAP_LEN ((size_t)_heap_end - (size_t)&_end)
 #endif
 
 struct free_heap_chunk {
diff --git a/lib/libc/string/arch/x86/memcpy.S b/lib/libc/string/arch/x86/memcpy.S
new file mode 100644
index 0000000..a2a2a44
--- /dev/null
+++ b/lib/libc/string/arch/x86/memcpy.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+/* TODO: */
+
+.text
+.align 2
+
+/* void bcopy(const void *src, void *dest, size_t n); */
+FUNCTION(bcopy)
+	ret
+
+/* void *memcpy(void *dest, const void *src, size_t n); */
+FUNCTION(memmove)
+FUNCTION(memcpy)
+	ret
+
diff --git a/lib/libc/string/arch/x86/memset.S b/lib/libc/string/arch/x86/memset.S
new file mode 100644
index 0000000..b4bccc9
--- /dev/null
+++ b/lib/libc/string/arch/x86/memset.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+/* TODO: */
+
+.text
+.align 2
+
+/* void bzero(void *s, size_t n); */
+FUNCTION(bzero)
+	ret
+
+/* void *memset(void *s, int c, size_t n); */
+FUNCTION(memset)
+	ret
+
diff --git a/lib/libc/string/arch/x86/rules.mk b/lib/libc/string/arch/x86/rules.mk
new file mode 100644
index 0000000..b3a5aa9
--- /dev/null
+++ b/lib/libc/string/arch/x86/rules.mk
@@ -0,0 +1,11 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ASM_STRING_OPS := #bcopy bzero memcpy memmove memset
+
+OBJS += \
+	#$(LOCAL_DIR)/memcpy.o \
+	#$(LOCAL_DIR)/memset.o
+
+# filter out the C implementation
+C_STRING_OPS := $(filter-out $(ASM_STRING_OPS),$(C_STRING_OPS))
+
diff --git a/platform/x86/console.c b/platform/x86/console.c
new file mode 100644
index 0000000..0ce5527
--- /dev/null
+++ b/platform/x86/console.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <arch/x86.h>
+#include <platform/x86.h>
+#include <platform/console.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/* CGA values */
+#define CURSOR_START		0x0A
+#define CURSOR_END			0x0B
+#define VIDEO_ADDRESS_MSB	0x0C
+#define VIDEO_ADDRESS_LSB	0x0D
+#define CURSOR_POS_MSB		0x0E
+#define CURSOR_POS_LSB		0x0F
+
+/* curr settings */
+static unsigned char curr_x;
+static unsigned char curr_y;
+static unsigned char curr_start;
+static unsigned char curr_end;
+static unsigned char curr_attr;
+
+/* video page buffer */
+#define VPAGE_SIZE		2048
+#define PAGE_MAX		8
+
+static int active_page = 0;
+static int visual_page = 0;
+
+static int curs_x[PAGE_MAX];
+static int curs_y[PAGE_MAX];
+
+static struct {
+	int x1, y1, x2, y2;
+} view_window = {
+	0, 0, 79, 24
+};
+
+void platform_init_console(void)
+{
+	curr_save();
+	window(0, 0, 79, 24);
+	clear();
+	place(0, 0);
+}
+
+void set_visual_page(int page)
+{
+    unsigned short page_offset = page*VPAGE_SIZE;
+    visual_page = page;
+    
+    outp(CGA_INDEX_REG, VIDEO_ADDRESS_LSB);
+    outp(CGA_DATA_REG, page_offset & 0xFF);
+    outp(CGA_INDEX_REG, VIDEO_ADDRESS_MSB);
+    outp(CGA_DATA_REG, (page_offset >> 8) & 0xFF);
+}
+
+void set_active_page(int page)
+{
+    curs_x[active_page] = curr_x;
+    curs_y[active_page] = curr_y;
+    curr_x = curs_x[page];
+    curr_y = curs_y[page];
+    active_page = page;
+}
+
+int get_visual_page(void)
+{
+    return visual_page;
+}
+
+int get_active_page(void)
+{
+    return active_page;
+}
+
+void place(int x,int y)
+{
+    unsigned short cursor_word = x + y*80 + active_page*VPAGE_SIZE;
+    
+    /*
+     * program CGA using index reg, then data reg
+     */
+    outp(CGA_INDEX_REG, CURSOR_POS_LSB);
+    outp(CGA_DATA_REG, cursor_word & 0xFF);
+    outp(CGA_INDEX_REG, CURSOR_POS_MSB);
+    outp(CGA_DATA_REG, (cursor_word >> 8) & 0xFF);
+    
+    curr_x = x;
+    curr_y = y;
+}
+
+void cursor(int start,int end)
+{
+    outp(CGA_INDEX_REG, CURSOR_START);
+    outp(CGA_DATA_REG, start);
+    outp(CGA_INDEX_REG, CURSOR_END);
+    outp(CGA_DATA_REG, end);
+}
+
+void curr_save(void)
+{
+    /* grab some info from the bios data area (these should be defined in memmap.h */
+    curr_attr = *((unsigned char *)0xB8000 + 159);
+    curr_x = *((unsigned char *)0x00450);
+    curr_y = *((unsigned char *)0x00451);
+    curr_end = *((unsigned char *)0x00460);
+    curr_start = *((unsigned char *)0x00461);
+    active_page = visual_page = 0;
+}
+
+void curr_restore(void)
+{
+    *((unsigned char *)0x00450) = curr_x;
+    *((unsigned char *)0x00451) = curr_y;
+    
+    place(curr_x, curr_y);
+    cursor(curr_start, curr_end);
+}
+
+void window(int x1, int y1, int x2, int y2) {
+	view_window.x1 = x1;
+	view_window.y1 = y1;
+	view_window.x2 = x2;
+	view_window.y2 = y2;
+	
+	//place(x1, y1);
+}
+
+void _clear(char c,char attr,int x1,int y1,int x2,int y2)
+{
+	register int i,j;
+	unsigned short w = attr;
+	
+	w <<= 8; w |= c;
+	for (i = x1; i <= x2; i++) {
+		for (j = y1; j <= y2; j++) { 
+			*((unsigned short *)(0xB8000 + 2*i+160*j + 2*active_page*VPAGE_SIZE)) = w;
+	    }
+	}
+	
+	place(x1,y1);
+	curr_y = y1;
+	curr_x = x1;
+}
+
+void clear()
+{
+    _clear(' ', curr_attr, view_window.x1, view_window.y1, view_window.x2,
+    	view_window.y2);
+}
+
+void _scroll(char attr, int x1, int y1, int x2, int y2)
+{
+    register int x,y;
+    unsigned short xattr = attr << 8,w;
+    unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
+      
+    for (y = y1+1; y <= y2; y++) {
+		for (x = x1; x <= x2; x++) {
+			w = *((unsigned short *) (v + 2*(y*80+x)));
+			*((unsigned short *)(v + 2*((y-1)*80+x))) = w;
+		}
+	}
+	
+    for (x = x1; x <= x2; x++) {
+   		*((unsigned short *)(v + 2*((y-1)*80+x))) = xattr;
+   	}
+}
+
+void scroll(void)
+{
+    _scroll(curr_attr, view_window.x1, view_window.y1, view_window.x2,
+    	view_window.y2);
+}
+
+void cputc(char c)
+{
+    static unsigned short scan_x, x, y;
+    unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
+    x = curr_x;
+    y = curr_y;
+    
+    switch (c) {
+	case '\t':
+		x += 8;		
+		if (x >= view_window.x2+1) {
+			x = view_window.x1;
+			if (y == view_window.y2) {
+				scroll();
+			} else {
+				y++;
+			}
+		} else {
+			scan_x = 0;
+			
+			while ((scan_x+8) < x) {
+				scan_x += 8;
+			}
+			
+			x = scan_x;
+		}
+		break;
+		
+	case '\n':
+		x = view_window.x1;
+		if (y == view_window.y2) {
+			scroll();
+		} else {
+			y++;
+		}
+		break;
+		
+	case '\b':
+		x--;
+		*(v + 2*(x + y*80)) = ' ';
+		break;
+		
+	default:
+		*(v + 2*(x + y*80)) = c;
+		x++;
+    	
+    	if (x >= view_window.x2+1) {
+			x = view_window.x1;
+			if (y == view_window.y2) {
+				scroll();
+			} else {
+				y++;
+			}
+		}
+    }
+    
+    place(x, y);
+}
+
+void cputs(char *s)
+{
+    char c;
+    while (*s != '\0') {
+		c = *s++;
+		cputc(c);
+    }
+}
+
+void puts_xy(int x,int y,char attr,char *s)
+{
+    unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
+    while (*s != 0) {
+		*v = *s; s++; v++;
+		*v = attr; v++;
+    }
+}
+
+void putc_xy(int x, int y, char attr, char c)
+{
+    unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
+    *v = c; v++;
+    *v = attr;
+}
+
+int printf_xy(int x, int y, char attr, char *fmt, ...)
+{
+	char cbuf[200];
+	va_list parms;
+	int result;
+	
+	va_start(parms, fmt);
+	result = vsprintf(cbuf, fmt, parms);
+	va_end(parms);
+	
+	puts_xy(x, y, attr, cbuf);
+	
+	return result;
+}
diff --git a/platform/x86/debug.c b/platform/x86/debug.c
new file mode 100644
index 0000000..0bc4999
--- /dev/null
+++ b/platform/x86/debug.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <arch/x86.h>
+#include <platform/x86/memmap.h>
+#include <platform/console.h>
+#include <platform/keyboard.h>
+#include <platform/debug.h>
+
+void _dputc(char c)
+{
+	cputc(c);
+}
+
+int dgetc(char *c)
+{
+	return platform_read_key(c);
+}
+
+void debug_dump_regs(void)
+{
+}
+
+void platform_halt(void)
+{
+	for(;;) {
+		x86_cli();
+		x86_hlt();
+	}
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+}
+
+uint32_t debug_cycle_count()
+{
+	uint32_t timestamp;
+	rdtscl(timestamp);
+	
+	return timestamp;
+}
diff --git a/platform/x86/include/platform/console.h b/platform/x86/include/platform/console.h
new file mode 100644
index 0000000..3a1b802
--- /dev/null
+++ b/platform/x86/include/platform/console.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_CONSOLE_H
+#define __PLATFORM_CONSOLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void platform_init_console(void);
+
+void set_visual_page(int page);
+void set_active_page(int page);
+
+int get_visual_page(void);
+int get_active_page(void);
+
+void place(int x,int y);
+void cursor(int start, int end);
+
+void _clear(char c, char attr, int x1, int y1, int x2, int y2);
+void clear(void);
+
+void _scroll(char attr, int x1, int y1, int x2, int y2);
+void scroll(void);
+
+void curr_save(void);
+void curr_restore(void);
+
+void cputc(char c);
+void cputs(char *s);
+
+void window(int x1, int y1, int x2, int y2);
+
+void putc_xy(int x, int y, char attr, char c);
+void puts_xy(int x, int y, char attr, char *s);
+
+int printf_xy(int x, int y, char attr, char *fmt, ...) __PRINTFLIKE(4, 5);
+
+#define CURSOR_BLOCK()	cursor(0, 15);
+#define CURSOR_OFF()	cursor(16, 16);
+#define CURSOR_STD()	cursor(14, 15);
+
+/* text colors */
+#define BLACK			0
+#define BLUE			1
+#define GREEN			2
+#define CYAN			3
+#define RED				4
+#define MAGENTA			5
+#define BROWN			6
+#define LIGHTGRAY		7
+#define DARKGRAY		8
+#define LIGHTBLUE		9
+#define LIGHTGREEN		10
+#define LIGHTCYAN		11
+#define LIGHTRED		12
+#define LIGHTMAGENTA	13
+#define YELLOW 			14
+#define WHITE			15
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/platform/x86/include/platform/keyboard.h b/platform/x86/include/platform/keyboard.h
new file mode 100644
index 0000000..5464995
--- /dev/null
+++ b/platform/x86/include/platform/keyboard.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_KEYBOARD_H
+#define __PLATFORM_KEYBOARD_H
+
+void platform_init_keyboard(void);
+
+int platform_read_key(char *c);
+
+#endif
diff --git a/platform/x86/include/platform/multiboot.h b/platform/x86/include/platform/multiboot.h
new file mode 100644
index 0000000..f5d3310
--- /dev/null
+++ b/platform/x86/include/platform/multiboot.h
@@ -0,0 +1,137 @@
+/*

+ * Copyright (c) 2009 Corey Tabaka

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining

+ * a copy of this software and associated documentation files

+ * (the "Software"), to deal in the Software without restriction,

+ * including without limitation the rights to use, copy, modify, merge,

+ * publish, distribute, sublicense, and/or sell copies of the Software,

+ * and to permit persons to whom the Software is furnished to do so,

+ * subject to the following conditions:

+ *

+ * The above copyright notice and this permission notice shall be

+ * included in all copies or substantial portions of the Software.

+ *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY

+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,

+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ */

+#ifndef __PLATFORM_MULTIBOOT_H

+#define __PLATFORM_MULTIBOOT_H

+

+#include <sys/types.h>

+     

+/* magic number for multiboot header */

+#define MULTIBOOT_HEADER_MAGIC		0x1BADB002

+

+/* flags for multiboot header */

+#ifdef __ELF__

+#define MULTIBOOT_HEADER_FLAGS		0x00000003

+#else

+#define MULTIBOOT_HEADER_FLAGS		0x00010003

+#endif

+

+/* magic number passed by multiboot-compliant boot loaders */

+#define MULTIBOOT_BOOTLOADER_MAGIC	0x2BADB002

+

+#ifndef ASSEMBLY

+

+/* multiboot header */

+typedef struct multiboot_header

+{

+	uint32_t magic;

+	uint32_t flags;

+	uint32_t checksum;

+	uint32_t header_addr;

+	uint32_t load_addr;

+	uint32_t load_end_addr;

+	uint32_t bss_end_addr;

+	uint32_t entry_addr;

+} multiboot_header_t;

+

+/* symbol table for a.out */

+typedef struct aout_symbol_table

+{

+	uint32_t tabsize;

+	uint32_t strsize;

+	uint32_t addr;

+	uint32_t reserved;

+} aout_symbol_table_t;

+

+/* section header table for ELF */

+typedef struct elf_section_header_table

+{

+	uint32_t num;

+	uint32_t size;

+	uint32_t addr;

+	uint32_t shndx;

+} elf_section_header_table_t;

+

+/* multiboot info */

+typedef struct multiboot_info

+{

+	uint32_t flags;

+	uint32_t mem_lower;

+	uint32_t mem_upper;

+	uint32_t boot_device;

+	uint32_t cmdline;

+	uint32_t mods_count;

+	uint32_t mods_addr;

+	union

+	{

+		aout_symbol_table_t aout_sym;

+		elf_section_header_table_t elf_sec;

+	} u;

+	uint32_t mmap_length;

+	uint32_t mmap_addr;

+} multiboot_info_t;

+

+enum {

+	MB_INFO_MEM_SIZE	= 0x001,

+	MB_INFO_BOOT_DEV	= 0x002,

+	MB_INFO_CMD_LINE	= 0x004,

+	MB_INFO_MODS		= 0x008,

+	MB_INFO_SYMS		= 0x010,

+	MB_INFO_MMAP		= 0x020,

+	MB_INFO_DRIVES		= 0x040,

+	MB_INFO_CONFIG		= 0x080,

+	MB_INFO_BOOT_LOADER	= 0x100,

+	MB_INFO_APM_TABLE	= 0x200,

+	MB_INFO_VBE			= 0x400,

+};

+

+/* module structure */

+typedef struct module

+{

+	uint32_t mod_start;

+	uint32_t mod_end;

+	uint32_t string;

+	uint32_t reserved;

+} module_t;

+

+/* memory map - be careful that the offset 0 is base_addr_low without size */

+typedef struct memory_map

+{

+	uint32_t size;

+	uint32_t base_addr_low;

+	uint32_t base_addr_high;

+	uint32_t length_low;

+	uint32_t length_high;

+	uint32_t type;

+} memory_map_t;

+

+/* memory map entry types */

+enum {

+	MB_MMAP_TYPE_AVAILABLE		= 0x01,

+	MB_MMAP_TYPE_RESERVED		= 0x02,

+	MB_MMAP_TYPE_ACPI_RECLAIM	= 0x03,

+	MB_MMAP_TYPE_ACPI_NVS		= 0x04,

+};

+

+#endif

+

+#endif

diff --git a/platform/x86/include/platform/x86.h b/platform/x86/include/platform/x86.h
new file mode 100644
index 0000000..e4a1db1
--- /dev/null
+++ b/platform/x86/include/platform/x86.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_X86_H
+#define __PLATFORM_X86_H
+
+#include <platform/x86/memmap.h>
+#include <platform/x86/iomap.h>
+
+/* NOTE: keep arch/x86/crt0.S in sync with these definitions */
+
+/* interrupts */
+#define INT_VECTORS 0x31
+
+/* defined interrupts */
+#define INT_BASE			0x20
+#define INT_PIT				0x20
+#define INT_KEYBOARD		0x21
+#define INT_PIC2			0x22
+
+#define INT_BASE2			0x28
+#define INT_CMOSRTC			0x28
+#define INT_PS2MOUSE		0x2c
+#define INT_IDE0			0x2e
+#define INT_IDE1			0x2f
+
+/* exceptions */
+#define INT_DIVIDE_0		0x00
+#define INT_DEBUG_EX		0x01
+#define INT_INVALID_OP		0x06
+#define INT_DEV_NA_EX		0x07
+
+/* faults */
+#define INT_STACK_FAULT		0x0c
+#define INT_GP_FAULT		0x0d
+#define INT_PAGE_FAULT		0x0e
+
+/* APIC vectors */
+#define INT_APIC_TIMER		0x22
+
+#define INT_SYSCALL			0x30
+
+/* PIC remap bases */
+#define PIC1_BASE 0x20
+#define PIC2_BASE 0x28
+
+#endif
+
diff --git a/platform/x86/include/platform/x86/iomap.h b/platform/x86/include/platform/x86/iomap.h
new file mode 100644
index 0000000..fe75964
--- /dev/null
+++ b/platform/x86/include/platform/x86/iomap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __IOMAP_H
+#define __IOMAP_H
+
+/* i8253/i8254 programmable interval timer registers */
+#define I8253_CONTROL_REG	0x43
+#define I8253_DATA_REG		0x40
+
+/* i8042 keyboard controller registers */
+#define I8042_COMMAND_REG	0x64
+#define I8042_STATUS_REG	0x64
+#define I8042_DATA_REG		0x60
+
+/* CGA registers */
+#define CGA_INDEX_REG		0x3D4
+#define CGA_DATA_REG		0x3D5
+
+#endif
diff --git a/platform/x86/include/platform/x86/memmap.h b/platform/x86/include/platform/x86/memmap.h
new file mode 100644
index 0000000..ab39f35
--- /dev/null
+++ b/platform/x86/include/platform/x86/memmap.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __MEMMAP_H
+#define __MEMMAP_H
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+
+
+#if 0
+
+#define MEMBANK_SIZE (4*1024*1024)
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+/* memory map of our generic arm system */
+// XXX make more dynamic
+#define MAINMEM_BASE 0x0
+#define MAINMEM_SIZE (MEMBANK_SIZE)
+
+/* peripherals are all mapped here */
+#define PERIPHERAL_BASE   (0xf0000000)
+
+/* system info */
+#define SYSINFO_REGS_BASE (PERIPHERAL_BASE)
+#define SYSINFO_REGS_SIZE MEMBANK_SIZE
+#define SYSINFO_FEATURES  (SYSINFO_REGS_BASE + 0)
+#define SYSINFO_FEATURE_DISPLAY 0x00000001
+#define SYSINFO_FEATURE_CONSOLE 0x00000002
+#define SYSINFO_FEATURE_NETWORK 0x00000004
+
+    /* a write to this register latches the current emulator system time, so the next two regs can be read atomically */
+#define SYSINFO_TIME_LATCH (SYSINFO_REGS_BASE + 4)
+    /* gettimeofday() style time values */
+#define SYSINFO_TIME_SECS  (SYSINFO_REGS_BASE + 8)
+#define SYSINFO_TIME_USECS (SYSINFO_REGS_BASE + 12)
+
+/* display */
+#define DISPLAY_BASE      (SYSINFO_REGS_BASE + SYSINFO_REGS_SIZE)
+#define DISPLAY_SIZE      MEMBANK_SIZE
+#define DISPLAY_FRAMEBUFFER DISPLAY_BASE
+#define DISPLAY_REGS_BASE (DISPLAY_BASE + DISPLAY_SIZE)
+#define DISPLAY_REGS_SIZE MEMBANK_SIZE
+	/* no display regs for now */
+
+/* console (keyboard controller */
+#define CONSOLE_REGS_BASE (DISPLAY_REGS_BASE + DISPLAY_REGS_SIZE)
+#define CONSOLE_REGS_SIZE MEMBANK_SIZE
+#define KYBD_STAT         (CONSOLE_REGS_BASE + 0)
+#define KYBD_DATA         (CONSOLE_REGS_BASE + 4)
+
+/* programmable timer */
+#define PIT_REGS_BASE     (CONSOLE_REGS_BASE + CONSOLE_REGS_SIZE)
+#define PIT_REGS_SIZE     MEMBANK_SIZE
+#define PIT_STATUS        (PIT_REGS_BASE + 0) // status bit
+#define PIT_CLEAR         (PIT_REGS_BASE + 4) // a nonzero write clears any pending timer
+#define PIT_CLEAR_INT     (PIT_REGS_BASE + 8) // a nonzero write clears the pending interrupt
+#define PIT_INTERVAL      (PIT_REGS_BASE + 12) // set the countdown interval, and what the interval is reset to if periodic
+#define PIT_START_ONESHOT (PIT_REGS_BASE + 16) // a nonzero write starts a oneshot countdown
+#define PIT_START_PERIODIC (PIT_REGS_BASE + 20) // a nonzero write starts a periodic countdown
+
+#define PIT_STATUS_ACTIVE    0x1
+#define PIT_STATUS_INT_PEND  0x2
+
+/* interrupt controller */
+#define PIC_REGS_BASE     (PIT_REGS_BASE + PIT_REGS_SIZE)
+#define PIC_REGS_SIZE     MEMBANK_SIZE
+
+    /* Current vector mask, read-only */
+#define PIC_MASK          (PIC_REGS_BASE + 0)
+    /* Mask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_MASK_LATCH    (PIC_REGS_BASE + 4)
+	/* Unmask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_UNMASK_LATCH  (PIC_REGS_BASE + 8)
+	/* each bit corresponds to the current status of the interrupt line */
+#define PIC_STAT          (PIC_REGS_BASE + 12)
+	/* one bit set for the highest priority non-masked active interrupt */
+#define PIC_CURRENT_BIT   (PIC_REGS_BASE + 16)
+	/* holds the current interrupt number of the highest priority non-masked active interrupt, 
+	 * or 0xffffffff if no interrupt is active
+	 */
+#define PIC_CURRENT_NUM   (PIC_REGS_BASE + 20)
+
+	/* interrupt map */
+#define INT_PIT      0
+#define INT_KEYBOARD 1
+#define INT_NET      2
+#define PIC_MAX_INT 32
+
+/* debug interface */
+#define DEBUG_REGS_BASE (PIC_REGS_BASE + PIC_REGS_SIZE)
+#define DEBUG_REGS_SIZE MEMBANK_SIZE
+#define DEBUG_STDOUT (DEBUG_REGS_BASE + 0) /* writes to this register are sent through to stdout */
+#define DEBUG_STDIN  (DEBUG_REGS_BASE + 0) /* reads from this register return the contents of stdin
+                                            * or -1 if no data is pending */
+#define DEBUG_REGDUMP (DEBUG_REGS_BASE + 4) /* writes to this register cause the emulator to dump registers */
+#define DEBUG_HALT    (DEBUG_REGS_BASE + 8) /* writes to this register will halt the emulator */
+
+#define DEBUG_MEMDUMPADDR (DEBUG_REGS_BASE + 12)      /* set the base address of memory to dump */
+#define DEBUG_MEMDUMPLEN  (DEBUG_REGS_BASE + 16)      /* set the length of memory to dump */
+#define DEBUG_MEMDUMP_BYTE  (DEBUG_REGS_BASE + 20)    /* trigger a memory dump in byte format */
+#define DEBUG_MEMDUMP_HALFWORD (DEBUG_REGS_BASE + 24) /* trigger a memory dump in halfword format */
+#define DEBUG_MEMDUMP_WORD (DEBUG_REGS_BASE + 28)     /* trigger a memory dump in word format */
+
+/* lets you set the trace level of the various subsystems from within the emulator */
+/* only works on emulator builds that support dynamic trace levels */
+#define DEBUG_SET_TRACELEVEL_CPU (DEBUG_REGS_BASE + 32)
+#define DEBUG_SET_TRACELEVEL_UOP (DEBUG_REGS_BASE + 36)
+#define DEBUG_SET_TRACELEVEL_SYS (DEBUG_REGS_BASE + 40)
+#define DEBUG_SET_TRACELEVEL_MMU (DEBUG_REGS_BASE + 44)
+
+#define DEBUG_CYCLE_COUNT (DEBUG_REGS_BASE + 48)
+#define DEBUG_INS_COUNT (DEBUG_REGS_BASE + 52)
+
+/* network interface */
+#define NET_REGS_BASE (DEBUG_REGS_BASE + DEBUG_REGS_SIZE)
+#define NET_REGS_SIZE MEMBANK_SIZE
+
+#define NET_BUF_LEN 2048
+#define NET_IN_BUF_COUNT 32
+
+#define NET_HEAD	(NET_REGS_BASE + 0)		/* current next buffer the hardware will write to */
+#define NET_TAIL	(NET_REGS_BASE + 4)		/* currently selected input buffer */
+#define NET_SEND	(NET_REGS_BASE + 8)		/* writes to this register sends whatever is in the out buf */
+#define NET_SEND_LEN (NET_REGS_BASE + 12)	/* length of packet to send */
+#define NET_OUT_BUF (NET_REGS_BASE + NET_BUF_LEN)
+
+#define NET_IN_BUF_LEN (NET_REGS_BASE + 16)	/* length of the currently selected in buffer, via tail register */
+#define NET_IN_BUF	(NET_REGS_BASE + NET_BUF_LEN*2)
+
+#endif // if 0
+
+#endif
diff --git a/platform/x86/interrupts.c b/platform/x86/interrupts.c
new file mode 100644
index 0000000..fa598d0
--- /dev/null
+++ b/platform/x86/interrupts.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/x86.h>
+#include "platform_p.h"
+#include <platform/x86.h>
+
+void x86_gpf_handler(struct x86_iframe *frame);
+void x86_invop_handler(struct x86_iframe *frame);
+void x86_unhandled_exception(struct x86_iframe *frame);
+
+#define PIC1 0x20
+#define PIC2 0xA0
+
+#define ICW1 0x11
+#define ICW4 0x01
+
+struct int_handler_struct {
+	int_handler handler;
+	void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+/*
+ * Cached IRQ mask (enabled/disabled)
+ */
+static uint8_t irqMask[2];
+
+/*
+ * init the PICs and remap them
+ */
+static void map(uint32_t pic1, uint32_t pic2)
+{
+	/* send ICW1 */
+	outp(PIC1, ICW1);
+	outp(PIC2, ICW1);
+
+	/* send ICW2 */
+	outp(PIC1 + 1, pic1);	/* remap */
+	outp(PIC2 + 1, pic2);	/*  pics */
+
+	/* send ICW3 */
+	outp(PIC1 + 1, 4);	/* IRQ2 -> connection to slave */
+	outp(PIC2 + 1, 2);
+
+	/* send ICW4 */
+	outp(PIC1 + 1, 5);
+	outp(PIC2 + 1, 1);
+
+	/* disable all IRQs */
+	outp(PIC1 + 1, 0xff);
+	outp(PIC2 + 1, 0xff);
+	
+	irqMask[0] = 0xff;
+	irqMask[1] = 0xff;
+}
+
+static void enable(unsigned int vector, bool enable)
+{
+	if (vector >= PIC1_BASE && vector < PIC1_BASE + 8) {
+		vector -= PIC1_BASE;
+		
+		uint8_t bit = 1 << vector;
+		
+		if (enable && (irqMask[0] & bit)) {
+			irqMask[0] = inp(PIC1 + 1);
+			irqMask[0] &= ~bit;
+			outp(PIC1 + 1, irqMask[0]);
+			irqMask[0] = inp(PIC1 + 1);
+		} else if (!enable && !(irqMask[0] & bit)) {
+			irqMask[0] = inp(PIC1 + 1);
+			irqMask[0] |= bit;
+			outp(PIC1 + 1, irqMask[0]);
+			irqMask[0] = inp(PIC1 + 1);
+		}
+	} else if (vector >= PIC2_BASE && vector < PIC2_BASE + 8) {
+		vector -= PIC2_BASE;
+		
+		uint8_t bit = 1 << vector;
+		
+		if (enable && (irqMask[1] & bit)) {
+			irqMask[1] = inp(PIC2 + 1);
+			irqMask[1] &= ~bit;
+			outp(PIC2 + 1, irqMask[1]);
+			irqMask[1] = inp(PIC2 + 1);
+		} else if (!enable && !(irqMask[1] & bit)) {
+			irqMask[1] = inp(PIC2 + 1);
+			irqMask[1] |= bit;
+			outp(PIC2 + 1, irqMask[1]);
+			irqMask[1] = inp(PIC2 + 1);
+		}
+		
+		bit = 1 << (INT_PIC2 - PIC1_BASE);
+		
+		if (irqMask[1] != 0xff && (irqMask[0] & bit)) {
+			irqMask[0] = inp(PIC1 + 1);
+			irqMask[0] &= ~bit;
+			outp(PIC1 + 1, irqMask[0]);
+			irqMask[0] = inp(PIC1 + 1);
+		} else if (irqMask[1] == 0 && !(irqMask[0] & bit)) {
+			irqMask[0] = inp(PIC1 + 1);
+			irqMask[0] |= bit;
+			outp(PIC1 + 1, irqMask[0]);
+			irqMask[0] = inp(PIC1 + 1);
+		}
+	} else {
+		//dprintf(DEBUG, "Invalid PIC interrupt: %02x\n", vector);
+	}
+}
+
+void issueEOI(unsigned int vector)
+{
+	if (vector >= PIC1_BASE && vector <= PIC1_BASE + 7) {
+		outp(PIC1, 0x20);
+	} else if (vector >= PIC2_BASE && vector <= PIC2_BASE + 7) {
+		outp(PIC2, 0x20);
+		outp(PIC1, 0x20);	// must issue both for the second PIC
+	}
+}
+
+void platform_init_interrupts(void)
+{
+	// rebase the PIC out of the way of processor exceptions
+	map(PIC1_BASE, PIC2_BASE);
+}
+
+status_t mask_interrupt(unsigned int vector)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf(DEBUG, "%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	enable(vector, false);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+
+void platform_mask_irqs(void)
+{
+	irqMask[0] = inp(PIC1 + 1);
+	irqMask[1] = inp(PIC2 + 1);
+	
+	outp(PIC1 + 1, 0xff);
+	outp(PIC2 + 1, 0xff);
+	
+	irqMask[0] = inp(PIC1 + 1);
+	irqMask[1] = inp(PIC2 + 1);
+}
+
+status_t unmask_interrupt(unsigned int vector)
+{
+	if (vector >= INT_VECTORS)
+		return ERR_INVALID_ARGS;
+
+//	dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+	enter_critical_section();
+
+	enable(vector, true);
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct x86_iframe *frame)
+{
+	// get the current vector
+	unsigned int vector = frame->vector;
+
+#if THREAD_STATS
+	thread_stats.interrupts++;
+#endif
+	
+	// deliver the interrupt	
+	enum handler_return ret = INT_NO_RESCHEDULE;
+	
+	switch (vector) {
+		case INT_GP_FAULT:
+			x86_gpf_handler(frame);
+			break;
+		
+		case INT_INVALID_OP:
+			x86_invop_handler(frame);
+			break;
+		
+		case INT_DIVIDE_0:
+		case INT_DEBUG_EX:
+		case INT_DEV_NA_EX:
+		case INT_PAGE_FAULT:
+		case INT_STACK_FAULT:
+		case 3:
+			x86_unhandled_exception(frame);
+			break;
+		
+		default:
+			if (int_handler_table[vector].handler)
+				ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+	}
+
+	// ack the interrupt
+	issueEOI(vector);
+
+	return ret;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+	if (vector >= INT_VECTORS)
+		panic("register_int_handler: vector out of range %d\n", vector);
+
+	enter_critical_section();
+
+	int_handler_table[vector].arg = arg;
+	int_handler_table[vector].handler = handler;
+
+	exit_critical_section();
+}
+
+
diff --git a/platform/x86/keyboard.c b/platform/x86/keyboard.c
new file mode 100644
index 0000000..bb057b6
--- /dev/null
+++ b/platform/x86/keyboard.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/console.h>
+#include <platform/timer.h>
+#include <platform/x86.h>
+#include "platform_p.h"
+#include <arch/x86.h>
+
+static inline int i8042_read_data(void)
+{
+	return inp(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+	return inp(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+	outp(I8042_DATA_REG, val);
+}
+
+static inline void i8042_write_command(int val)
+{
+	outp(I8042_COMMAND_REG, val);
+}
+
+/*
+ * timeout in milliseconds
+ */
+#define I8042_CTL_TIMEOUT	500
+
+/*
+ * status register bits
+ */
+#define I8042_STR_PARITY	0x80
+#define I8042_STR_TIMEOUT	0x40
+#define I8042_STR_AUXDATA	0x20
+#define I8042_STR_KEYLOCK	0x10
+#define I8042_STR_CMDDAT	0x08
+#define I8042_STR_MUXERR	0x04
+#define I8042_STR_IBF		0x02
+#define	I8042_STR_OBF		0x01
+
+/*
+ * control register bits
+ */
+#define I8042_CTR_KBDINT	0x01
+#define I8042_CTR_AUXINT	0x02
+#define I8042_CTR_IGNKEYLK	0x08
+#define I8042_CTR_KBDDIS	0x10
+#define I8042_CTR_AUXDIS	0x20
+#define I8042_CTR_XLATE		0x40
+
+/*
+ * commands
+ */
+#define I8042_CMD_CTL_RCTR	0x0120
+#define I8042_CMD_CTL_WCTR	0x1060
+#define I8042_CMD_CTL_TEST	0x01aa
+
+#define I8042_CMD_KBD_DIS	0x00ad
+#define I8042_CMD_KBD_EN	0x00ae
+#define I8042_CMD_KBD_TEST	0x01ab
+#define I8042_CMD_KBD_MODE	0x01f0
+
+/*
+ * used for flushing buffers. the i8042 internal buffer shoudn't exceed this.
+ */
+#define I8042_BUFFER_LENGTH	32
+
+static inline void delay(time_t delay) {
+	bigtime_t start = current_time();
+	
+	while (start + delay > current_time());
+}
+
+/* scancodes we want to do something with that don't translate via table */
+#define SCANCODE_LSHIFT 0x2a
+#define SCANCODE_RSHIFT 0x36
+
+/* scancode translation tables */
+static const int KeyCodeSingleLower[] = {
+// 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+  -1,  -1, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', // 0
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\n',  -1, 'a', 's', // 1
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',  -1,'\\', 'z', 'x', 'c', 'v', // 2
+ 'b', 'n', 'm', ',', '.', '/',  -1, '*',  -1, ' ',  -1,  -1,  -1,  -1,  -1,  -1, // 3
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 4
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 5
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 6
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 7
+};
+
+static const int KeyCodeMultiLower[] = {
+// 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 0
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 1
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 2
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 3
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 4
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 5
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 6
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 7
+};
+
+static const int KeyCodeSingleUpper[] = {
+// 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+  -1,  -1, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', // 0
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\n',  -1, 'A', 'S', // 1
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',  -1, '|', 'Z', 'X', 'C', 'V', // 2
+ 'B', 'N', 'M', '<', '>', '?',  -1, '*',  -1, ' ',  -1,  -1,  -1,  -1,  -1,  -1, // 3
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 4
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 5
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 6
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 7
+};
+
+static const int KeyCodeMultiUpper[] = {
+// 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 0
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 1
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 2
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 3
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 4
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 5
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 6
+  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, // 7
+};
+
+/*
+ * state key flags
+ */
+static bool key_lshift;
+static bool key_rshift;
+
+/*
+ * key buffer
+ */
+#define KEY_BUFFER_LEN 10
+
+static uint8_t key_buffer[KEY_BUFFER_LEN];
+static int key_buffer_in_ptr, key_buffer_out_ptr;
+
+static int inq(uint8_t data) {
+	int temp;
+
+	temp = key_buffer_in_ptr + 1;
+	if (temp >= KEY_BUFFER_LEN) {
+		temp = 0;
+	}
+	
+	// if in_ptr reaches out_ptr, the queue is full
+	if (temp == key_buffer_out_ptr) {
+		return -1;
+	}
+	
+	key_buffer[key_buffer_in_ptr] = data;
+	key_buffer_in_ptr = temp;
+	
+	return 0;
+}
+
+static int deq(void) {
+	int rv;
+	
+	// if out_ptr reaches in_ptr, the queue is empty
+	if (key_buffer_out_ptr == key_buffer_in_ptr) {
+		return -1;
+	}
+	
+	rv = key_buffer[key_buffer_out_ptr];
+	key_buffer_out_ptr++;
+	
+	if (key_buffer_out_ptr >= KEY_BUFFER_LEN) {
+		key_buffer_out_ptr = 0;
+	}
+	
+	return rv;
+}
+
+static void i8042_process_scode(uint8_t scode, unsigned int flags)
+{
+	static int lastCode = 0;
+	int keyCode;
+	uint8_t keyUpBit;
+	
+	bool multi = lastCode == 0xe0;
+	
+	// save the key up event bit
+	keyUpBit = scode & 0x80;
+	scode &= 0x7f;
+	
+	if (scode == SCANCODE_LSHIFT) {
+		key_lshift = !keyUpBit;
+	}
+	
+	if (scode == SCANCODE_RSHIFT) {
+		key_rshift = !keyUpBit;
+	}
+	
+	if (key_lshift || key_rshift) {
+		keyCode = multi ? KeyCodeMultiUpper[scode] : KeyCodeSingleUpper[scode];
+	} else {
+		keyCode = multi ? KeyCodeMultiLower[scode] : KeyCodeSingleLower[scode];
+	}
+	
+	/*printf_xy(71, 3, BLUE, "%02x%02x %c %c%c", multi ? lastCode : 0, scode,
+		keyCode != -1 ? (char) keyCode : ' ', key_lshift ? 'L' : ' ',
+		key_rshift ? 'R' : ' ');*/
+	
+	if (keyCode != -1 && !keyUpBit) {
+		inq(keyCode);
+	}
+	
+	// update the last received code
+	lastCode = scode;
+}
+
+static int i8042_wait_read(void)
+{
+	int i = 0;
+	while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) {
+		delay(1);
+		i++;
+	}
+	return -(i == I8042_CTL_TIMEOUT);
+}
+
+static int i8042_wait_write(void)
+{
+	int i = 0;
+	while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) {
+		delay(1);
+		i++;
+	}
+	return -(i == I8042_CTL_TIMEOUT);
+}
+
+static int i8042_flush(void)
+{
+	unsigned char data;
+	int i = 0;
+
+	//enter_critical_section();
+
+	while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_LENGTH)) {
+		delay(1);
+		data = i8042_read_data();
+	}
+
+	//exit_critical_section();
+
+	return i;
+}
+
+static int i8042_command(uint8_t *param, int command)
+{
+	int retval = 0, i = 0;
+
+	//enter_critical_section();
+
+	retval = i8042_wait_write();
+	if (!retval) {
+		i8042_write_command(command & 0xff);
+	}
+
+	if (!retval) {
+		for (i = 0; i < ((command >> 12) & 0xf); i++) {
+			if ((retval = i8042_wait_write())) {
+				break;
+			}
+			
+			i8042_write_data(param[i]);
+		}
+	}
+
+	if (!retval) {
+		for (i = 0; i < ((command & 0xf0) >> 8); i++) {
+			if ((retval = i8042_wait_read())) {
+				break;
+			}
+			
+			if (i8042_read_status() & I8042_STR_AUXDATA) {
+				param[i] = ~i8042_read_data();
+			} else {
+				param[i] = i8042_read_data();
+			}
+		}
+	}
+
+	//exit_critical_section();
+
+	return retval;
+}
+
+static enum handler_return i8042_interrupt(void *arg)
+{
+	uint8_t str, data = 0;
+
+	//enter_critical_section();
+	str = i8042_read_status();
+	if (str & I8042_STR_OBF) {
+		data = i8042_read_data();
+	}
+	//exit_critical_section();
+
+	if (str & I8042_STR_OBF) {
+		i8042_process_scode(data,
+			((str & I8042_STR_PARITY) ? I8042_STR_PARITY : 0) |
+			((str & I8042_STR_TIMEOUT) ? I8042_STR_TIMEOUT : 0));
+	}
+	
+	return INT_NO_RESCHEDULE;
+}
+
+int platform_read_key(char *c)
+{
+	int data;
+	
+	enter_critical_section();
+	data = deq();
+	
+	if (data != -1) {
+		*c = (char) data;
+	}
+	exit_critical_section();
+	
+	return data == -1 ? -1 : 0;
+}
+
+void platform_init_keyboard(void)
+{
+	uint8_t ctr;
+	
+	// clear in case of reinit
+	key_buffer_in_ptr = key_buffer_out_ptr = 0;
+	
+	i8042_flush();
+	
+	if (i8042_command(&ctr, I8042_CMD_CTL_RCTR)) {
+		dprintf(DEBUG, "Failed to read CTR while initializing i8042\n");
+		return;
+	}
+	
+	// turn on translation
+	ctr |= I8042_CTR_XLATE;
+	
+	// enable keyboard and keyboard irq
+	ctr &= ~I8042_CTR_KBDDIS;
+	ctr |= I8042_CTR_KBDINT;
+	
+	if (i8042_command(&ctr, I8042_CMD_CTL_WCTR)) {
+		dprintf(DEBUG, "Failed to write CTR while initializing i8042\n");
+		return;
+	}
+	
+	register_int_handler(INT_KEYBOARD, &i8042_interrupt, NULL);
+	unmask_interrupt(INT_KEYBOARD);
+	
+	i8042_interrupt(NULL);
+}
diff --git a/platform/x86/platform.c b/platform/x86/platform.c
new file mode 100644
index 0000000..5d76237
--- /dev/null
+++ b/platform/x86/platform.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <arch/x86/mmu.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/x86.h>
+#include <platform/multiboot.h>
+#include <platform/console.h>
+#include <platform/keyboard.h>
+
+extern multiboot_info_t *_multiboot_info;
+extern unsigned int _heap_end;
+
+void platform_init_mmu_mappings(void)
+{
+	/* do some memory map initialization */
+}
+
+
+void platform_init_multiboot_info(void)
+{
+	unsigned int i;
+	
+	if (_multiboot_info) {
+		if (_multiboot_info->flags & MB_INFO_MEM_SIZE) {
+			_heap_end = _multiboot_info->mem_upper * 1024;
+		}
+		
+		if (_multiboot_info->flags & MB_INFO_MMAP) {
+			memory_map_t *mmap = (memory_map_t *) (_multiboot_info->mmap_addr - 4);
+			
+			dprintf(DEBUG, "mmap length: %u\n", _multiboot_info->mmap_length);
+			
+			for (i=0; i < _multiboot_info->mmap_length / sizeof(memory_map_t); i++) {
+				dprintf(DEBUG, "base=%08x, length=%08x, type=%02x\n",
+					mmap[i].base_addr_low, mmap[i].length_low, mmap[i].type);
+				
+				if (mmap[i].type == MB_MMAP_TYPE_AVAILABLE && mmap[i].base_addr_low >= _heap_end) {
+					_heap_end = mmap[i].base_addr_low + mmap[i].length_low;
+				} else if (mmap[i].type != MB_MMAP_TYPE_AVAILABLE && mmap[i].base_addr_low >= _heap_end) {
+					/* 
+					 * break on first memory hole above default heap end for now.
+					 * later we can add facilities for adding free chunks to the
+					 * heap for each segregated memory region.
+					 */
+					 break;
+				}
+			}
+		}
+	}
+}
+
+void platform_early_init(void)
+{
+	/* update the heap end so we can take advantage of more ram */
+	platform_init_multiboot_info();
+	
+	/* get the text console working */
+	platform_init_console();
+	
+	/* initialize the interrupt controller */
+	platform_init_interrupts();
+
+	/* initialize the timer */
+	platform_init_timer();
+}
+
+void platform_init(void)
+{
+	platform_init_keyboard();
+	
+}
+
diff --git a/platform/x86/platform_p.h b/platform/x86/platform_p.h
new file mode 100644
index 0000000..b8c2d95
--- /dev/null
+++ b/platform/x86/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/x86/rules.mk b/platform/x86/rules.mk
new file mode 100644
index 0000000..bedf6c2
--- /dev/null
+++ b/platform/x86/rules.mk
@@ -0,0 +1,22 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := x86
+CPU := generic
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+OBJS += \
+	$(LOCAL_DIR)/interrupts.o \
+	$(LOCAL_DIR)/platform.o \
+	$(LOCAL_DIR)/timer.o \
+	$(LOCAL_DIR)/debug.o \
+	$(LOCAL_DIR)/console.o \
+	$(LOCAL_DIR)/keyboard.o
+
+MEMBASE := 0x0
+MEMSIZE := 0x400000	# 4MB
+
+LINKER_SCRIPT += \
+	$(BUILDDIR)/kernel.ld
+
diff --git a/platform/x86/timer.c b/platform/x86/timer.c
new file mode 100644
index 0000000..2684ab5
--- /dev/null
+++ b/platform/x86/timer.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/console.h>
+#include <platform/timer.h>
+#include <platform/x86.h>
+#include "platform_p.h"
+#include <arch/x86.h>
+
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+static uint64_t next_trigger_time;
+static uint64_t next_trigger_delta;
+
+static uint64_t timer_delta_time;
+static uint64_t timer_current_time;
+
+static uint16_t divisor;
+
+#define INTERNAL_FREQ 1193182ULL
+#define INTERNAL_FREQ_3X 3579546ULL
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+	enter_critical_section();
+
+	t_callback = callback;
+	callback_arg = arg;
+	
+	next_trigger_delta = (uint64_t) interval << 32;
+	next_trigger_time = timer_current_time + next_trigger_delta;
+
+	exit_critical_section();
+
+	return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+	time_t time;
+	
+	enter_critical_section();
+	time = (time_t) (timer_current_time >> 32);
+	exit_critical_section();
+	
+	return time;
+}
+
+bigtime_t current_time_hires(void)
+{
+	bigtime_t time;
+	
+	enter_critical_section();
+	time = (bigtime_t) ((timer_current_time >> 22) * 1000) >> 10;
+	exit_critical_section();
+	
+	return time;
+}
+static enum handler_return os_timer_tick(void *arg)
+{
+	uint64_t delta;
+	
+	timer_current_time += timer_delta_time;
+	
+	time_t time = current_time();
+	//bigtime_t btime = current_time_hires();
+	//printf_xy(71, 0, WHITE, "%08u", (uint32_t) time);
+	//printf_xy(63, 1, WHITE, "%016llu", (uint64_t) btime);
+	
+	if (t_callback && timer_current_time >= next_trigger_time) {
+		delta = timer_current_time - next_trigger_time;
+		next_trigger_time = timer_current_time + next_trigger_delta - delta;
+		
+		return t_callback(callback_arg, time);
+	} else {
+		return INT_NO_RESCHEDULE;
+	}
+}
+
+static void set_pit_frequency(uint32_t frequency)
+{
+	uint32_t count, remainder;
+	
+	/* figure out the correct divisor for the desired frequency */
+	if (frequency <= 18) {
+		count = 0xffff;
+	} else if (frequency >= INTERNAL_FREQ) {
+		count = 1;
+	} else {
+		count = INTERNAL_FREQ_3X / frequency;
+		remainder = INTERNAL_FREQ_3X % frequency;
+		
+		if (remainder >= INTERNAL_FREQ_3X / 2) {
+			count += 1;
+		}
+		
+		count /= 3;
+		remainder = count % 3;
+		
+		if (remainder >= 1) {
+			count += 1;
+		}
+	}
+		
+	divisor = count & 0xffff;
+	
+	/*
+	 * funky math that i don't feel like explaining. essentially 32.32 fixed
+	 * point representation of the configured timer delta.
+	 */
+	timer_delta_time = (3685982306ULL * count) >> 10;
+	
+	//dprintf(DEBUG, "set_pit_frequency: dt=%016llx\n", timer_delta_time);
+	//dprintf(DEBUG, "set_pit_frequency: divisor=%04x\n", divisor);
+	
+	/*
+	 * setup the Programmable Interval Timer
+	 * timer 0, mode 2, binary counter, LSB followed by MSB
+	 */
+	outp(I8253_CONTROL_REG, 0x34);
+	outp(I8253_DATA_REG, divisor & 0xff); // LSB
+	outp(I8253_DATA_REG, divisor >> 8); // MSB
+}
+
+void platform_init_timer(void)
+{
+	timer_current_time = 0;
+	
+	set_pit_frequency(1000); // ~1ms granularity
+
+	register_int_handler(INT_PIT, &os_timer_tick, NULL);
+	unmask_interrupt(INT_PIT);
+}
+
+void platform_halt_timers(void)
+{
+	mask_interrupt(INT_PIT);
+}
+
diff --git a/project/x86-test.mk b/project/x86-test.mk
new file mode 100644
index 0000000..4952260
--- /dev/null
+++ b/project/x86-test.mk
@@ -0,0 +1,18 @@
+# top level project rules for the x86-test project
+#
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+TARGET := x86
+#DEFINES += \
+#	USE_UNDERSCORE=1
+MODULES += \
+	app/tests \
+	app/shell
+
+# extra rules to copy the x86.conf file to the build dir
+#$(BUILDDIR)/x86.conf: $(LOCAL_DIR)/x86.conf
+#	@echo copy $< to $@
+#	$(NOECHO)cp $< $@
+
+#EXTRA_BUILDDEPS += $(BUILDDIR)/x86.conf
+#GENERATED += $(BUILDDIR)/x86.conf
diff --git a/target/x86/rules.mk b/target/x86/rules.mk
new file mode 100644
index 0000000..3f9b072
--- /dev/null
+++ b/target/x86/rules.mk
@@ -0,0 +1,6 @@
+# mostly null target configuration for x86, since there's only one real
+# implementation.
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+PLATFORM := x86
+