Index: kernel/arch/arm32/src/mm/frame.c
===================================================================
--- kernel/arch/arm32/src/mm/frame.c	(revision 8bdcffa853c11b32f7445df1a38ecc63fec8d0e3)
+++ kernel/arch/arm32/src/mm/frame.c	(revision c6f1908ecbced40d641beac151a51af7725f49d0)
@@ -41,22 +41,24 @@
 #include <macros.h>
 
+// TODO: remove me
 /** Address of the last frame in the memory. */
 uintptr_t last_frame = 0;
 
-/** Creates memory zones. */
+/** Create low memory zones. */
 void frame_low_arch_init(void)
 {
-	uintptr_t mem_start, mem_size;
-	uintptr_t first_frame;
-	uintptr_t num_frames;
+	uintptr_t mem_start, mem_end, mem_size;
 
 	machine_get_memory_extents(&mem_start, &mem_size);
-	first_frame = ALIGN_UP(mem_start, FRAME_SIZE);
+	// TODO: remove me
 	last_frame = ALIGN_DOWN(mem_start + mem_size, FRAME_SIZE);
-	num_frames = (last_frame - first_frame) >> FRAME_WIDTH;
 	
-	/* All memory as one zone */
-	zone_create(first_frame >> FRAME_WIDTH, num_frames,
-	    BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0);
+	mem_start = ALIGN_UP(mem_start, FRAME_SIZE);
+	mem_end = min(ALIGN_DOWN(mem_start + mem_size, FRAME_SIZE),
+	    config.identity_size);
+
+	zone_create(ADDR2PFN(mem_start), SIZE2FRAMES(mem_end - mem_start),
+	    BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES,
+	    ZONE_AVAILABLE | ZONE_LOWMEM);
 	
 	/* blacklist boot page table */
@@ -67,6 +69,24 @@
 }
 
+/** Create high memory zones. */
 void frame_high_arch_init(void)
 {
+	uintptr_t mem_start, mem_end, mem_size;
+	size_t frames;
+	uintptr_t conf;
+
+	machine_get_memory_extents(&mem_start, &mem_size);
+
+	mem_end = ALIGN_DOWN(mem_start + mem_size, FRAME_SIZE);
+	if (mem_end <= config.identity_size) {
+		/* There is no high memory to init. */
+		return;
+	}
+
+	frames = SIZE2FRAMES(mem_end - config.identity_size);
+	conf = zone_external_conf_alloc(frames);
+
+	zone_create(ADDR2PFN(config.identity_size), frames, conf,
+	    ZONE_AVAILABLE);
 }
 
