Index: arch/ia32/_link.ld
===================================================================
--- arch/ia32/_link.ld	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/_link.ld	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -18,15 +18,16 @@
 		*(K_TEXT_START_2);
 		unmapped_ktext_end = .;
+		
 		unmapped_kdata_start = .;
 		*(K_DATA_START);
 		unmapped_kdata_end = .;
 	}
-
-	.mapped (0x80100000+SIZEOF(.unmapped)+0x8000) : AT (0x8000+SIZEOF(.unmapped)) { 
+	
+	.mapped (0x80100000+0x8000+SIZEOF(.unmapped)): AT (0x8000+SIZEOF(.unmapped)) { 
 		ktext_start = .;
 		*(BOOT_DATA)
 		*(.text);
 		ktext_end = .;
-
+		
 		kdata_start = .;
 		*(.data);		/* initialized data */
@@ -39,4 +40,8 @@
 		hardcoded_kdata_size = .;
 		LONG(kdata_end - kdata_start + (unmapped_kdata_end - unmapped_kdata_start));
+		hardcoded_unmapped_ktext_size = .;
+		LONG(unmapped_ktext_end - unmapped_ktext_start);
+		hardcoded_unmapped_kdata_size = .;
+		LONG(unmapped_kdata_end - unmapped_kdata_start);
 		*(.bss);		/* uninitialized static variables */
 		*(K_DATA_END);
@@ -45,5 +50,5 @@
 	
 	_hardcoded_kernel_size = (ktext_end - ktext_start) + (unmapped_ktext_end - unmapped_ktext_start) + (kdata_end - kdata_start) + (unmapped_kdata_end - unmapped_kdata_start);
-
+	
 	_map_address = 0x80100000;
 	e820table_boot = e820table - _map_address;
Index: arch/ia32/include/boot/boot.h
===================================================================
--- arch/ia32/include/boot/boot.h	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/include/boot/boot.h	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -30,5 +30,7 @@
 #define __ia32_BOOT_H__
 
-#define BOOT_OFFSET	0x100000
+#define BOOTSTRAP_OFFSET			0x8000
+#define BOOT_OFFSET					0x100000
+
 #define MULTIBOOT_HEADER_MAGIC		0x1BADB002
 #define MULTIBOOT_HEADER_FLAGS		0x00010003
Index: arch/ia32/src/boot/boot.S
===================================================================
--- arch/ia32/src/boot/boot.S	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/src/boot/boot.S	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -32,4 +32,7 @@
 .global kernel_image_start
 
+KTEXT=8
+KDATA=16
+
 .code16
 #
@@ -45,16 +48,16 @@
 	xorw %ax, %ax
 	movw %ax, %ds
-	movw %ax, %ss			# initialize stack segment register
-	movl $0x7c00, %esp		# initialize stack pointer
+	movw %ax, %ss							# initialize stack segment register
+	movl $BOOTSTRAP_OFFSET - 0x400, %esp	# initialize stack pointer
 	
 	call memmap_arch_init
 	
-	lgdt gdtr			# initialize Global Descriptor Table register
+	lgdt bsp_bootstrap_gdtr					# initialize Global Descriptor Table register
 	
 	movl %cr0, %eax
 	orl $0x1, %eax
-	movl %eax, %cr0			# switch to protected mode
+	movl %eax, %cr0							# switch to protected mode
 	
-	jmpl $8, $boot_image_start
+	jmpl $KTEXT, $boot_image_start
 	
 .code32
@@ -71,5 +74,5 @@
 	
 boot_image_start:
-	movw $16, %ax
+	movw $KDATA, %ax
 	movw %ax, %es
 	movw %ax, %gs
@@ -85,6 +88,6 @@
 	outb %al, $0x60
 	
-	movl $0x8000, %esi
-	movl $0x8000 + BOOT_OFFSET, %edi
+	movl $BOOTSTRAP_OFFSET, %esi
+	movl $BOOTSTRAP_OFFSET + BOOT_OFFSET, %edi
 	movl $_hardcoded_kernel_size, %ecx
 	cld
@@ -94,19 +97,19 @@
 	
 multiboot_image_start:
-	movl $0x7c00, %esp		# initialize stack pointer
+	movl BOOTSTRAP_OFFSET - 0x400, %esp		# initialize stack pointer
 	
-	lgdt gdtr
+	lgdt gdtr								# initialize Global Descriptor Table register
 
-	movw $16, %ax
+	movw $KDATA, %ax
 	movw %ax, %es
 	movw %ax, %gs
 	movw %ax, %fs
-	movw %ax, %ds			# kernel data + stack
+	movw %ax, %ds							# kernel data + stack
 	movw %ax, %ss
 	
-	call map_kernel			# map kernel and turn paging on
+	call map_kernel							# map kernel and turn paging on
 	
 protected:
-	call main_bsp			# never returns
+	call main_bsp		# never returns
 
 	cli
Index: arch/ia32/src/ia32.c
===================================================================
--- arch/ia32/src/ia32.c	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/src/ia32.c	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -58,5 +58,5 @@
 	if (config.cpu_active == 1) {
 		bios_init();
-		i8042_init();	/* a20 bit */
+		i8042_init();	/* keyboard controller */
 		i8259_init();	/* PIC */
 		i8254_init();	/* hard clock */
Index: arch/ia32/src/mm/frame.c
===================================================================
--- arch/ia32/src/mm/frame.c	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/src/mm/frame.c	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -31,7 +31,9 @@
 #include <mm/vm.h>
 #include <config.h>
+#include <arch/boot/boot.h>
 #include <arch/boot/memmap.h>
 
-#include <print.h>
+size_t hardcoded_unmapped_ktext_size = 0;
+size_t hardcoded_unmapped_kdata_size = 0;
 
 void frame_arch_init(void)
@@ -40,11 +42,13 @@
 	
 	if (config.cpu_active == 1) {
+		/* Reserve the NULL frame */
 		frame_not_free(0x0);
-
+		
+		/* Reserve well-known memory regions */
 		frame_region_not_free(0xa0000,0xff000);
 		frame_region_not_free(0xfec00000,0xffffffff);
 		
-		/* This is a nasty hack, which should be fixed soon */
-		frame_region_not_free(0x0, 0xfffff);
+		/* Reserve real mode bootstrap memory */
+		frame_region_not_free(BOOTSTRAP_OFFSET, BOOTSTRAP_OFFSET + hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size);
 		
 		for (i=e820counter;i>0;i--) {
Index: arch/ia32/src/pm.c
===================================================================
--- arch/ia32/src/pm.c	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/src/pm.c	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -71,5 +71,7 @@
 
 /* gdtr is changed by kmp before next CPU is initialized */
-struct ptr_16_32 gdtr __attribute__ ((section ("K_DATA_START"))) = { .limit = sizeof(gdt), .base = KA2PA((__address) gdt - BOOT_OFFSET) };
+struct ptr_16_32 bsp_bootstrap_gdtr __attribute__ ((section ("K_DATA_START"))) = { .limit = sizeof(gdt), .base = KA2PA((__address) gdt - BOOT_OFFSET) };
+struct ptr_16_32 ap_bootstrap_gdtr __attribute__ ((section ("K_DATA_START"))) = { .limit = sizeof(gdt), .base = KA2PA((__address) gdt) };
+struct ptr_16_32 gdtr = { .limit = sizeof(gdt), .base = KA2PA((__address) gdt) };
 struct ptr_16_32 idtr __attribute__ ((section ("K_DATA_START"))) = { .limit = sizeof(idt), .base = KA2PA((__address) idt) };
 
@@ -171,5 +173,5 @@
 	 * Update addresses in GDT and IDT to their virtual counterparts.
 	 */
-	gdtr.base = KA2PA(gdtr.base);
+	gdtr.base = (__address) gdt;
 	idtr.base = (__address) idt;
 	__asm__ volatile ("lgdt %0\n" : : "m" (gdtr));
Index: arch/ia32/src/smp/ap.S
===================================================================
--- arch/ia32/src/smp/ap.S	(revision 2f08a55d1a22c7eb9b7ef8e5958444279c506fc7)
+++ arch/ia32/src/smp/ap.S	(revision f6297e0db360cfc4702b1de07398872a26b9229b)
@@ -48,26 +48,32 @@
 .code16
 	cli
-	xorw %ax,%ax
-	movw %ax,%ds
+	xorw %ax, %ax
+	movw %ax, %ds
 
-	lgdt gdtr			# initialize Global Descriptor Table register
+	lgdt ap_bootstrap_gdtr	# initialize Global Descriptor Table register
 	
-	movl %cr0,%eax
-	orl $1,%eax
-	movl %eax,%cr0			# switch to protected mode
-	jmpl $KTEXT,$jump_to_kernel
+	movl %cr0, %eax
+	orl $1, %eax
+	movl %eax, %cr0			# switch to protected mode
+	jmpl $KTEXT, $jump_to_kernel
+	
 jump_to_kernel:
 .code32
-	movw $KDATA,%ax
-	movw %ax,%ds
-	movw %ax,%es
-	movw %ax,%ss
-	movl $(ctx-0x80000000),%eax	# KA2PA((__address) &ctx)
-	movl (%eax),%esp
-	subl $0x80000000,%esp		# KA2PA(ctx.sp)
+	movw $KDATA, %ax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %ss
+	movl $(ctx-0x80000000), %eax	# KA2PA((__address) &ctx)
+	movl (%eax), %esp
+	subl $0x80000000, %esp			# KA2PA(ctx.sp)
 
-	call map_kernel			# map kernel and turn paging on
+	call map_kernel					# map kernel and turn paging on
+	
+	movb $0xd1, %al					# enable A20 using the keyboard controller
+	outb %al, $0x64
+	movb $0xdf, %al
+	outb %al, $0x60
 
-	jmpl $KTEXT,$main_ap
+	jmpl $KTEXT, $main_ap
 
 #endif /* __SMP__ */
