Index: kernel/arch/ia32/src/mm/frame.c
===================================================================
--- kernel/arch/ia32/src/mm/frame.c	(revision ddcc8a0d63f8ff64bcff9151c6d65b103343d22c)
+++ kernel/arch/ia32/src/mm/frame.c	(revision 9d4e1704695fcf4bdd0d097a2dc12155e07a840f)
@@ -46,13 +46,11 @@
 #include <print.h>
 
-#define PHYSMEM_LIMIT32  UINT64_C(0x07c000000)
-#define PHYSMEM_LIMIT64  UINT64_C(0x200000000)
-
 size_t hardcoded_unmapped_ktext_size = 0;
 size_t hardcoded_unmapped_kdata_size = 0;
 
+// XXX: remove me
 uintptr_t last_frame = 0;
 
-static void init_e820_memory(pfn_t minconf)
+static void init_e820_memory(pfn_t minconf, bool low)
 {
 	unsigned int i;
@@ -61,52 +59,19 @@
 		uint64_t base = e820table[i].base_address;
 		uint64_t size = e820table[i].size;
+		uintptr_t limit = config.identity_size;
 		
-#ifdef __32_BITS__
-		/*
-		 * XXX FIXME:
-		 *
-		 * Ignore zones which start above PHYSMEM_LIMIT32
-		 * or clip zones which go beyond PHYSMEM_LIMIT32.
-		 *
-		 * The PHYSMEM_LIMIT32 (2 GB - 64 MB) is a rather
-		 * arbitrary constant which allows to have at
-		 * least 64 MB in the kernel address space to
-		 * map hardware resources.
-		 *
-		 * The kernel uses fixed 1:1 identity mapping
-		 * of the physical memory with 2:2 GB split.
-		 * This is a severe limitation of the current
-		 * kernel memory management.
-		 *
-		 */
-		
-		if (base > PHYSMEM_LIMIT32)
-			continue;
-		
-		if (base + size > PHYSMEM_LIMIT32)
-			size = PHYSMEM_LIMIT32 - base;
-#endif
-		
-#ifdef __64_BITS__
-		/*
-		 * XXX FIXME:
-		 *
-		 * Ignore zones which start above PHYSMEM_LIMIT64
-		 * or clip zones which go beyond PHYSMEM_LIMIT64.
-		 *
-		 * The PHYSMEM_LIMIT64 (8 GB) is the size of the
-		 * fixed 1:1 identically mapped physical memory
-		 * accessible during the bootstrap process.
-		 * This is a severe limitation of the current
-		 * kernel memory management.
-		 *
-		 */
-		
-		if (base > PHYSMEM_LIMIT64)
-			continue;
-		
-		if (base + size > PHYSMEM_LIMIT64)
-			size = PHYSMEM_LIMIT64 - base;
-#endif
+		if (low) {
+			if (base > limit)
+				continue;
+			if (base + size > limit)
+				size = limit - base;
+		} else {
+			if (base + size <= limit)
+				continue;
+			if (base <= limit) {
+				size -= limit - base;
+				base = limit;
+			}
+		}
 		
 		if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
@@ -116,18 +81,25 @@
 			    FRAME_SIZE);
 			
+			size_t count = SIZE2FRAMES(new_size);
 			pfn_t pfn = ADDR2PFN(new_base);
-			size_t count = SIZE2FRAMES(new_size);
+			pfn_t conf;
 			
-			pfn_t conf;
-			if ((minconf < pfn) || (minconf >= pfn + count))
-				conf = pfn;
-			else
-				conf = minconf;
+			if (low) {
+				if ((minconf < pfn) || (minconf >= pfn + count))
+					conf = pfn;
+				else
+					conf = minconf;
+				zone_create(pfn, count, conf,
+				    ZONE_AVAILABLE | ZONE_LOWMEM);
+			} else {
+				printf("count=%lld\n", (long long int) count);
+				conf = zone_external_conf_alloc(count);
+				zone_create(pfn, count, conf,
+				    ZONE_AVAILABLE | ZONE_HIGHMEM);
+			}
 			
-			zone_create(pfn, count, conf, ZONE_AVAILABLE);
-			
-			// XXX this has to be removed
-			if (last_frame < ALIGN_UP(new_base + new_size, FRAME_SIZE))
-				last_frame = ALIGN_UP(new_base + new_size, FRAME_SIZE);
+			// XXX: remove me
+			if (last_frame < new_base + new_size)
+				last_frame = new_base + new_size;
 		} else if ((e820table[i].type == MEMMAP_MEMORY_ACPI) ||
 		    (e820table[i].type == MEMMAP_MEMORY_NVS)) {
@@ -192,5 +164,5 @@
 #endif
 		
-		init_e820_memory(minconf);
+		init_e820_memory(minconf, true);
 		
 		/* Reserve frame 0 (BIOS data) */
@@ -208,4 +180,6 @@
 void frame_high_arch_init(void)
 {
+	if (config.cpu_active == 1)
+		init_e820_memory(0, false);
 }
 
Index: kernel/arch/ia32/src/mm/page.c
===================================================================
--- kernel/arch/ia32/src/mm/page.c	(revision ddcc8a0d63f8ff64bcff9151c6d65b103343d22c)
+++ kernel/arch/ia32/src/mm/page.c	(revision 9d4e1704695fcf4bdd0d097a2dc12155e07a840f)
@@ -49,4 +49,5 @@
 #include <print.h>
 #include <interrupt.h>
+#include <macros.h>
 
 void page_arch_init(void)
@@ -55,23 +56,29 @@
 	int flags;
 	
-	if (config.cpu_active == 1) {
-		page_mapping_operations = &pt_mapping_operations;
+	if (config.cpu_active > 1) {
+		/* Fast path for non-boot CPUs */
+		write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
+		paging_on();
+		return;
+	}
+
+	page_mapping_operations = &pt_mapping_operations;
 	
-		/*
-		 * PA2KA(identity) mapping for all frames until last_frame.
-		 */
-		page_table_lock(AS_KERNEL, true);
-		for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
-			flags = PAGE_CACHEABLE | PAGE_WRITE;
-			if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size))
-				flags |= PAGE_GLOBAL;
-			page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
-		}
-		page_table_unlock(AS_KERNEL, true);
+	/*
+	 * PA2KA(identity) mapping for all frames until last_frame.
+	 */
+	page_table_lock(AS_KERNEL, true);
+	for (cur = 0; cur < min(config.identity_size, last_frame);
+	    cur += FRAME_SIZE) {
+		flags = PAGE_CACHEABLE | PAGE_WRITE;
+		if ((PA2KA(cur) >= config.base) && (PA2KA(cur) <
+		    config.base + config.kernel_size))
+			flags |= PAGE_GLOBAL;
+		page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
+	}
+	page_table_unlock(AS_KERNEL, true);
 		
-		exc_register(14, "page_fault", true, (iroutine_t) page_fault);
-		write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
-	} else
-		write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
+	exc_register(14, "page_fault", true, (iroutine_t) page_fault);
+	write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
 	
 	paging_on();
