Index: Makefile
===================================================================
--- Makefile	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ Makefile	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -113,5 +113,4 @@
 	generic/src/syscall/syscall.c \
 	generic/src/mm/buddy.c \
-	generic/src/mm/heap.c \
 	generic/src/mm/frame.c \
 	generic/src/mm/page.c \
Index: arch/amd64/include/types.h
===================================================================
--- arch/amd64/include/types.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/amd64/include/types.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -40,4 +40,5 @@
 
 typedef __u64 __address;
+typedef __u64 pfn_t;
 
 /* Flags of processor (return value of interrupts_disable()) */
Index: arch/amd64/src/mm/page.c
===================================================================
--- arch/amd64/src/mm/page.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/amd64/src/mm/page.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -45,5 +45,5 @@
 	if (config.cpu_active == 1) {
 		page_mapping_operations = &pt_mapping_operations;
-	
+		
 		/*
 		 * PA2KA(identity) mapping for all frames.
@@ -52,5 +52,4 @@
 			page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, PAGE_CACHEABLE | PAGE_EXEC);
 		}
-
 		exc_register(14, "page_fault", (iroutine)page_fault);
 		write_cr3((__address) AS_KERNEL->page_table);
Index: arch/amd64/src/pm.c
===================================================================
--- arch/amd64/src/pm.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/amd64/src/pm.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -38,5 +38,5 @@
 
 #include <memstr.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <debug.h>
 
Index: arch/ia32/include/types.h
===================================================================
--- arch/ia32/include/types.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/ia32/include/types.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -40,4 +40,5 @@
 
 typedef __u32 __address;
+typedef __u32 pfn_t;
 
 typedef __u32 ipl_t;
Index: arch/ia32/src/mm/frame.c
===================================================================
--- arch/ia32/src/mm/frame.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/ia32/src/mm/frame.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -36,4 +36,10 @@
 #include <debug.h>
 #include <align.h>
+#include <macros.h>
+
+#include <print.h>
+#include <console/cmd.h>
+#include <console/kconsole.h>
+
 
 size_t hardcoded_unmapped_ktext_size = 0;
@@ -42,32 +48,88 @@
 __address last_frame = 0;
 
+static void init_e820_memory(pfn_t minconf)
+{
+	int i;
+	pfn_t start, size,conf;
+
+	for (i = 0; i < e820counter; i++) {
+		if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
+			start = ADDR2PFN(ALIGN_UP(e820table[i].base_address,
+						  FRAME_SIZE));
+			size = SIZE2PFN(ALIGN_DOWN(e820table[i].size,
+						   FRAME_SIZE));
+			if (minconf < start || minconf >= start+size)
+				conf = start;
+			else
+				conf = minconf;
+			zone_create(start,size, conf, 0);
+			if (last_frame < ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE))
+				last_frame = ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
+		}			
+	}
+}
+
+static int cmd_e820mem(cmd_arg_t *argv);
+static cmd_info_t e820_info = {
+	.name = "e820list",
+	.description = "List e820 memory.",
+	.func = cmd_e820mem,
+	.argc = 0
+};
+
+static char *e820names[] = { "invalid", "available", "reserved",
+			     "acpi", "nvs", "unusable" };
+
+
+static int cmd_e820mem(cmd_arg_t *argv)
+{
+	int i;
+	char *name;
+
+	for (i = 0; i < e820counter; i++) {
+		if (e820table[i].type <= MEMMAP_MEMORY_UNUSABLE)
+			name = e820names[e820table[i].type];
+		else
+			name = "invalid";
+		printf("%P %dB %s\n", e820table[i].base_address, 
+		       e820table[i].size,
+		       name);
+	}			
+	return 0;
+}
+
+
 void frame_arch_init(void)
 {
-	__u8 i;
-	
+	static pfn_t minconf;
+
 	if (config.cpu_active == 1) {
+		cmd_initialize(&e820_info);
+		cmd_register(&e820_info);
+
+
+		minconf = 1;
+#ifdef CONFIG_SMP
+		minconf = max(minconf,
+			      ADDR2PFN(AP_BOOT_OFFSET+hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size));
+#endif
+#ifdef CONFIG_SIMICS_FIX
+		minconf = max(minconf, ADDR2PFN(0x10000));
+#endif
+		init_e820_memory(minconf);
 
 		/* Reserve frame 0 (BIOS data) */
-		frame_region_not_free(0, FRAME_SIZE);
+		frame_mark_unavailable(0, 1);
 		
 #ifdef CONFIG_SMP
 		/* Reserve AP real mode bootstrap memory */
-		frame_region_not_free(AP_BOOT_OFFSET, hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size);
+		frame_mark_unavailable(AP_BOOT_OFFSET >> FRAME_WIDTH, 
+				       (hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size) >> FRAME_WIDTH);
 		
 #ifdef CONFIG_SIMICS_FIX
 		/* Don't know why, but this addresses help */
-		frame_region_not_free(0xf000,FRAME_SIZE);
-		frame_region_not_free(0xe000,FRAME_SIZE);
-		frame_region_not_free(0xd000,FRAME_SIZE);
+		frame_mark_unavailable(0xd000 >> FRAME_WIDTH,3);
 #endif
 #endif
-		
-		for (i = 0; i < e820counter; i++) {
-			if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
-				zone_create_in_region(e820table[i].base_address, e820table[i].size & ~(FRAME_SIZE-1));
-				if (last_frame < ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE))
-					last_frame = ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
-			}			
-		}
 	}
 }
Index: arch/ia32/src/pm.c
===================================================================
--- arch/ia32/src/pm.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/ia32/src/pm.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -36,5 +36,5 @@
 #include <panic.h>
 #include <arch/mm/page.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <memstr.h>
 #include <arch/boot/boot.h>
Index: arch/ia32/src/smp/smp.c
===================================================================
--- arch/ia32/src/smp/smp.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/ia32/src/smp/smp.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -44,5 +44,5 @@
 #include <mm/frame.h>
 #include <mm/page.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <mm/as.h>
 #include <print.h>
Index: arch/mips32/Makefile.inc
===================================================================
--- arch/mips32/Makefile.inc	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/mips32/Makefile.inc	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -74,4 +74,6 @@
 	KERNEL_LOAD_ADDRESS = 0x88002000
 	CFLAGS += -EB -DBIG_ENDIAN -DHAVE_FPU -march=r4600
+	INIT_ADDRESS = 0
+	INIT_SIZE = 0
 endif
 ifeq ($(MIPS_MACHINE),lgxemul)
Index: arch/mips32/include/types.h
===================================================================
--- arch/mips32/include/types.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/mips32/include/types.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -52,3 +52,5 @@
 typedef union pte pte_t;
 
+typedef __u32 pfn_t;
+
 #endif
Index: arch/mips32/src/drivers/arc.c
===================================================================
--- arch/mips32/src/drivers/arc.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/mips32/src/drivers/arc.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -304,5 +304,8 @@
 
 			total += basesize;
-			zone_create_in_region(base, basesize);
+			
+			zone_create(ADDR2PFN(base),
+				    SIZE2PFN(ALIGN_DOWN(basesize,FRAME_SIZE)),
+				    ADDR2PFN(base),0);
 		}
 		desc = arc_entry->getmemorydescriptor(desc);
Index: arch/mips32/src/mips32.c
===================================================================
--- arch/mips32/src/mips32.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/mips32/src/mips32.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -96,11 +96,11 @@
 	arc_print_memory_map();
 	arc_print_devices();
+	/* Setup usermode...*/
+//	config.init_addr = INIT_ADDRESS;
+//	config.init_size = INIT_SIZE;
 }
 
 void arch_post_mm_init(void)
 {
-	/* Setup usermode...*/
-	config.init_addr = INIT_ADDRESS;
-	config.init_size = INIT_SIZE;
 }
 
Index: arch/mips32/src/mm/frame.c
===================================================================
--- arch/mips32/src/mm/frame.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ arch/mips32/src/mm/frame.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -44,11 +44,8 @@
 void frame_arch_init(void)
 {
-	/* Blacklist first 4KB, exception vector */
-	frame_region_not_free(0, FRAME_SIZE);
-
 	if (arc_enabled())
 		arc_frame_init();
-	else
-		zone_create_in_region(KA2PA(KERNEL_LOAD_ADDRESS),
-				      (config.memory_size & ~(FRAME_SIZE-1)));
+	else {
+		zone_create(1, (config.memory_size >> PAGE_WIDTH)-1,1,0);
+	}
 }
Index: contrib/conf/msim.conf
===================================================================
--- contrib/conf/msim.conf	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ contrib/conf/msim.conf	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -5,5 +5,5 @@
 add dcpu mips1
 
-add rwm	firstmem        0x0             128k	load "/dev/zero"
+add rwm	firstmem        0x0             1M	load "/dev/zero"
 add rwm mainmem		0x00100000	16M	load "kernel.bin"
 add rom startmem	0x1fc00000	1k	load "load.bin" 
Index: genarch/src/acpi/matd.c
===================================================================
--- genarch/src/acpi/matd.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ genarch/src/acpi/matd.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -37,5 +37,5 @@
 #include <config.h>
 #include <print.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <memstr.h>
 #include <sort.h>
@@ -145,5 +145,5 @@
 
 	/* create madt apic entries index array */
-	madt_entries_index = (struct madt_apic_header * *) early_malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *));
+	madt_entries_index = (struct madt_apic_header * *) malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *));
 
 	__u32 index = 0;
Index: genarch/src/mm/as_pt.c
===================================================================
--- genarch/src/mm/as_pt.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ genarch/src/mm/as_pt.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -57,5 +57,5 @@
 	ipl_t ipl;
 
-	dst_ptl0 = (pte_t *) frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC);
+	dst_ptl0 = (pte_t *) PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC)));
 
 	if (flags & FLAG_AS_KERNEL) {
Index: genarch/src/mm/page_pt.c
===================================================================
--- genarch/src/mm/page_pt.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ genarch/src/mm/page_pt.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -66,5 +66,5 @@
 
 	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
-		newpt = frame_alloc(ONE_FRAME, FRAME_KA);
+		newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
 		memsetb(newpt, PAGE_SIZE, 0);
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
@@ -75,5 +75,5 @@
 
 	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
-		newpt = frame_alloc(ONE_FRAME, FRAME_KA);
+		newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
 		memsetb(newpt, PAGE_SIZE, 0);
 		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
@@ -84,5 +84,5 @@
 
 	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
-		newpt = frame_alloc(ONE_FRAME, FRAME_KA);
+		newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
 		memsetb(newpt, PAGE_SIZE, 0);
 		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
Index: generic/include/mm/buddy.h
===================================================================
--- generic/include/mm/buddy.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/include/mm/buddy.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -43,4 +43,7 @@
 	__u8 (*get_order)(buddy_system_t *, link_t *);			/**< Return order of block passed as argument. */
 	void (*mark_busy)(buddy_system_t *, link_t *);			/**< Mark block as busy */
+	void (*mark_available)(buddy_system_t *, link_t *);			/**< Mark block as busy */
+	/** Find parent of block that has given order  */
+	link_t *(* find_block)(buddy_system_t *, link_t *, __u8);
 };
 
@@ -52,9 +55,13 @@
 };
 
-extern buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op, void *data);
+extern void buddy_system_create(buddy_system_t *b,
+				__u8 max_order, 
+				buddy_system_operations_t *op, void *data);
 extern link_t *buddy_system_alloc(buddy_system_t *b, __u8 i);
 extern bool buddy_system_can_alloc(buddy_system_t *b, __u8 order);
 extern void buddy_system_free(buddy_system_t *b, link_t *block);
 extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size);
+extern size_t buddy_conf_size(int max_order);
+extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block);
 
 #endif
Index: generic/include/mm/frame.h
===================================================================
--- generic/include/mm/frame.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/include/mm/frame.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -36,7 +36,12 @@
 #include <synch/spinlock.h>
 #include <mm/buddy.h>
-#include <mm/slab.h>
+#include <arch/mm/page.h>
 
 #define ONE_FRAME	0
+
+#define ZONES_MAX       16      /**< Maximum number of zones in system */
+
+#define ZONE_JOIN       0x1  /**< If possible, merge with neighberhood zones */
+
 
 #define FRAME_KA		0x1	/* skip frames conflicting with user address space */
@@ -49,16 +54,39 @@
 #define FRAME_ERROR		2	/* frame_alloc return status */
 
-#define FRAME2ADDR(zone, frame)			((zone)->base + (((frame) - (zone)->frames) << FRAME_WIDTH))
-#define ADDR2FRAME(zone, addr)			(&((zone)->frames[(((addr) - (zone)->base) >> FRAME_WIDTH)]))
-#define FRAME_INDEX(zone, frame)		((index_t)((frame) - (zone)->frames))
-#define FRAME_INDEX_ABS(zone, frame)		(((index_t)((frame) - (zone)->frames)) + (zone)->base_index)
-#define FRAME_INDEX_VALID(zone, index)		(((index) >= 0) && ((index) < ((zone)->free_count + (zone)->busy_count)))
+/* Return true if the interlvals overlap */
+static inline int overlaps(__address s1,__address e1, __address s2, __address e2)
+{
+	if (s1 >= s2 && s1 < e2)
+		return 1;
+	if (e1 >= s2 && e1 < e2)
+		return 1;
+	if ((s1 < s2) && (e1 >= e2))
+		return 1;
+	return 0;
+}
+
+static inline __address PFN2ADDR(pfn_t frame)
+{
+	return (__address)(frame << PAGE_WIDTH);
+}
+
+static inline pfn_t ADDR2PFN(__address addr)
+{
+	return (pfn_t)(addr >> PAGE_WIDTH);
+}
+
+static inline pfn_t SIZE2PFN(__address size)
+{
+	if (!size)
+		return 0;
+	return (pfn_t)((size-1) >> PAGE_WIDTH)+1;
+}
+
 #define IS_BUDDY_ORDER_OK(index, order)		((~(((__native) -1) << (order)) & (index)) == 0)
-#define IS_BUDDY_LEFT_BLOCK(zone, frame)	(((FRAME_INDEX((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
-#define IS_BUDDY_RIGHT_BLOCK(zone, frame)	(((FRAME_INDEX((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
-#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame)	(((FRAME_INDEX_ABS((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
-#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame)	(((FRAME_INDEX_ABS((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
+#define IS_BUDDY_LEFT_BLOCK(zone, frame)	(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
+#define IS_BUDDY_RIGHT_BLOCK(zone, frame)	(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
+#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame)	(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
+#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame)	(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
 
-#define ZONE_BLACKLIST_SIZE	8
 
 #define frame_alloc(order, flags)				frame_alloc_generic(order, flags, NULL, NULL)
@@ -66,68 +94,14 @@
 #define frame_alloc_rc_zone(order, flags, status, zone)		frame_alloc_generic(order, flags, status, zone)
 
-struct zone {
-	link_t link;		/**< link to previous and next zone */
-
-	SPINLOCK_DECLARE(lock);	/**< this lock protects everything below */
-	__address base;		/**< physical address of the first frame in the frames array */
-	index_t base_index;	/**< frame index offset of the zone base */
-	frame_t *frames;	/**< array of frame_t structures in this zone */
-	count_t free_count;	/**< number of free frame_t structures */
-	count_t busy_count;	/**< number of busy frame_t structures */
-	
-	buddy_system_t * buddy_system; /**< buddy system for the zone */
-	int flags;
-};
-
-struct frame {
-	count_t refcount;	/**< tracking of shared frames  */
-	__u8 buddy_order;	/**< buddy system block order */
-	link_t buddy_link;	/**< link to the next free block inside one order */
-	void *parent;           /**< If allocated by slab, this points there */
-};
-
-struct region {
-	__address base;
-	size_t size;
-};
-
-extern region_t zone_blacklist[];
-extern count_t zone_blacklist_count;
-extern void frame_region_not_free(__address base, size_t size);
-extern void zone_create_in_region(__address base, size_t size);
-
-extern spinlock_t zone_head_lock;	/**< this lock protects zone_head list */
-extern link_t zone_head;		/**< list of all zones in the system */
-
-extern zone_t *zone_create(__address start, size_t size, int flags);
-extern void zone_attach(zone_t *zone);
-
 extern void frame_init(void);
-extern void frame_initialize(frame_t *frame, zone_t *zone);
-
-__address frame_alloc_generic(__u8 order, int flags, int * status, zone_t **pzone);
-
-
+__address frame_alloc_generic(__u8 order, int flags, int * status, int *pzone);
 extern void frame_free(__address addr);
 
-zone_t * get_zone_by_frame(frame_t * frame);
+extern void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags);
 
-/*
- * Buddy system operations
- */
-link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * buddy);
-link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block);
-link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * buddy_l, link_t * buddy_r);
-void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order);
-__u8 zone_buddy_get_order(buddy_system_t *b, link_t * block);
-void zone_buddy_mark_busy(buddy_system_t *b, link_t * block);
-extern frame_t * frame_addr2frame(__address addr);
-
-/*
- * TODO: Implement the following functions.
- */
-extern frame_t *frame_reference(frame_t *frame);
-extern void frame_release(frame_t *frame);
-
+void * frame_get_parent(pfn_t frame, int hint);
+void frame_set_parent(pfn_t frame, void *data, int hint);
+void frame_mark_unavailable(pfn_t start, pfn_t count);
+__address zone_conf_size(pfn_t start, pfn_t count);
 
 /*
@@ -135,5 +109,5 @@
  */
 extern void zone_print_list(void);
-extern void zone_print_one(__address base);
+void zone_print_one(int znum);
 
 #endif
Index: neric/include/mm/heap.h
===================================================================
--- generic/include/mm/heap.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (C) 2001-2004 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HEAP_H__
-#define __HEAP_H__
-
-#include <arch/types.h>
-#include <typedefs.h>
-#include <mm/slab.h>
-
-//#define malloc(size)		early_malloc(size)
-//#define free(ptr)		early_free(ptr)
-#define malloc(size)		kalloc(size,0)
-#define free(ptr)		kfree(ptr)
-
-struct chunk {
-	int used;
-	chunk_t *next;
-	chunk_t *prev;
-	__u32 size;
-	__native data[0];
-};
-
-extern void early_heap_init(__address heap, size_t size);
-
-extern void *early_malloc(size_t size) __attribute__ ((malloc));
-extern void early_free(void *ptr);
-
-#endif
Index: generic/include/mm/slab.h
===================================================================
--- generic/include/mm/slab.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/include/mm/slab.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -33,4 +33,5 @@
 #include <synch/spinlock.h>
 #include <arch/atomic.h>
+#include <mm/frame.h>
 
 /** Minimum size to be allocated by malloc */
@@ -127,3 +128,5 @@
 extern void * kalloc(unsigned int size, int flags);
 extern void kfree(void *obj);
+#define malloc(x)  kalloc(x, FRAME_ATOMIC)
+#define free(x)    kfree(x)
 #endif
Index: generic/include/proc/thread.h
===================================================================
--- generic/include/proc/thread.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/include/proc/thread.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -112,5 +112,4 @@
 
 	__u8 *kstack;				/**< Thread's kernel stack. */
-	__u8 *ustack;				/**< Thread's user stack. */
 };
 
Index: generic/include/typedefs.h
===================================================================
--- generic/include/typedefs.h	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/include/typedefs.h	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -67,8 +67,4 @@
 typedef struct buddy_system_operations buddy_system_operations_t;
 
-typedef struct zone zone_t;
-typedef struct frame frame_t;
-typedef struct region region_t;
-
 typedef enum as_area_type as_area_type_t;
 typedef struct as_area as_area_t;
Index: generic/src/adt/hash_table.c
===================================================================
--- generic/src/adt/hash_table.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/adt/hash_table.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -36,5 +36,5 @@
 #include <arch/types.h>
 #include <debug.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <memstr.h>
 
Index: generic/src/cpu/cpu.c
===================================================================
--- generic/src/cpu/cpu.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/cpu/cpu.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,5 @@
 #include <arch.h>
 #include <arch/cpu.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <mm/page.h>
 #include <mm/frame.h>
@@ -62,5 +62,5 @@
 
 		for (i=0; i < config.cpu_count; i++) {
-			cpus[i].stack = (__u8 *) frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC);
+			cpus[i].stack = (__u8 *) PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC)));
 			
 			cpus[i].id = i;
Index: generic/src/lib/sort.c
===================================================================
--- generic/src/lib/sort.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/lib/sort.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -27,5 +27,5 @@
  */
 
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <memstr.h>
 #include <sort.h>
Index: generic/src/main/main.c
===================================================================
--- generic/src/main/main.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/main/main.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -44,5 +44,4 @@
 #include <interrupt.h>
 #include <arch/mm/memory_init.h>
-#include <mm/heap.h>
 #include <mm/frame.h>
 #include <mm/page.h>
@@ -104,4 +103,6 @@
 void main_bsp(void)
 {
+	__address stackaddr;
+
 	config.cpu_count = 1;
 	config.cpu_active = 1;
@@ -112,17 +113,20 @@
 	config.init_size = init_size;
 	
-	if (init_size > 0)
-		config.heap_addr = init_addr + init_size;
-	else
-		config.heap_addr = hardcoded_load_address + hardcoded_ktext_size + hardcoded_kdata_size;
-	
-	config.heap_size = CONFIG_HEAP_SIZE + (config.memory_size / FRAME_SIZE) * sizeof(frame_t);
-	
-	config.kernel_size = ALIGN_UP(config.heap_addr - hardcoded_load_address + config.heap_size, PAGE_SIZE);
-	config.heap_delta = config.kernel_size - (config.heap_addr - hardcoded_load_address + config.heap_size);
-	config.kernel_size = config.kernel_size + CONFIG_STACK_SIZE;
+	config.kernel_size = ALIGN_UP(hardcoded_ktext_size + hardcoded_kdata_size, PAGE_SIZE);
+	stackaddr = config.base + config.kernel_size;
+	/* Avoid placing kernel on top of init */
+	if (overlaps(stackaddr,stackaddr+CONFIG_STACK_SIZE,
+		     config.init_addr, config.init_addr+config.init_size)) {
+		
+		stackaddr = ALIGN_UP(config.init_addr+config.init_size,
+				     CONFIG_STACK_SIZE);
+		config.init_size = ALIGN_UP(config.init_size,CONFIG_STACK_SIZE) + CONFIG_STACK_SIZE;
+	} else {
+		config.kernel_size += CONFIG_STACK_SIZE;
+	}
 	
 	context_save(&ctx);
-	context_set(&ctx, FADDR(main_bsp_separated_stack), config.base + config.kernel_size - CONFIG_STACK_SIZE, CONFIG_STACK_SIZE);
+	context_set(&ctx, FADDR(main_bsp_separated_stack), 
+		    stackaddr, CONFIG_STACK_SIZE);
 	context_restore(&ctx);
 	/* not reached */
@@ -141,5 +145,4 @@
 	
 	the_initialize(THE);
-	
 	/*
 	 * kconsole data structures must be initialized very early
@@ -159,5 +162,5 @@
 	 */	
 	arch_pre_mm_init();
-	early_heap_init(config.heap_addr, config.heap_size + config.heap_delta);
+	/* Initialize at least 1 memory segment big enough for slab to work */
 	frame_init();
 	slab_cache_init();
@@ -165,6 +168,5 @@
 	page_init();
 	tlb_init();
-	arch_post_mm_init();
-
+	arch_post_mm_init();	
 	version_print();
 
@@ -179,9 +181,7 @@
 	printf("config.memory_size=%dM\n", config.memory_size/(1024*1024));
 	printf("config.cpu_count=%d\n", config.cpu_count);
-
 	cpu_init();
 
 	calibrate_delay_loop();
-
 	timeout_init();
 	scheduler_init();
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/mm/as.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -37,6 +37,6 @@
 #include <mm/page.h>
 #include <mm/frame.h>
+#include <mm/slab.h>
 #include <mm/tlb.h>
-#include <mm/heap.h>
 #include <arch/mm/page.h>
 #include <genarch/mm/page_pt.h>
@@ -254,5 +254,5 @@
 	 *   the different causes
 	 */
-	frame = frame_alloc(ONE_FRAME, 0);
+	frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
 	memsetb(PA2KA(frame), FRAME_SIZE, 0);
 	
Index: generic/src/mm/buddy.c
===================================================================
--- generic/src/mm/buddy.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/mm/buddy.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -29,5 +29,4 @@
 #include <mm/buddy.h>
 #include <mm/frame.h>
-#include <mm/heap.h>
 #include <arch/types.h>
 #include <typedefs.h>
@@ -36,8 +35,16 @@
 #include <print.h>
 
+/** Return size needed for the buddy configuration data */
+size_t buddy_conf_size(int max_order)
+{
+	return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
+}
+
+
 /** Create buddy system
  *
  * Allocate memory for and initialize new buddy system.
  *
+ * @param b Preallocated buddy system control data
  * @param max_order The biggest allocable size will be 2^max_order.
  * @param op Operations for new buddy system.
@@ -46,7 +53,9 @@
  * @return New buddy system.
  */
-buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op, void *data)
-{
-	buddy_system_t *b;
+void buddy_system_create(buddy_system_t *b,
+			 __u8 max_order, 
+			 buddy_system_operations_t *op, 
+			 void *data)
+{
 	int i;
 
@@ -61,27 +70,14 @@
 
 	/*
-	 * Allocate memory for structure describing the whole buddy system.
-	 */	
-	b = (buddy_system_t *) early_malloc(sizeof(buddy_system_t));
-	
-	if (b) {
-		/*
-		 * Allocate memory for all orders this buddy system will work with.
-		 */
-		b->order = (link_t *) early_malloc((max_order + 1) * sizeof(link_t));
-		if (!b->order) {
-			early_free(b);
-			return NULL;
-		}
-	
-		for (i = 0; i <= max_order; i++)
-			list_initialize(&b->order[i]);
-	
-		b->max_order = max_order;
-		b->op = op;
-		b->data = data;
-	}
-	
-	return b;
+	 * Use memory after our own structure
+	 */
+	b->order = (link_t *) (&b[1]);
+	
+	for (i = 0; i <= max_order; i++)
+		list_initialize(&b->order[i]);
+
+	b->max_order = max_order;
+	b->op = op;
+	b->data = data;
 }
 
@@ -113,4 +109,40 @@
 	return false;
 	
+}
+
+/** Allocate PARTICULAR block from buddy system
+ *
+ * @ return Block of data or NULL if no such block was found
+ */
+link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block)
+{
+	link_t *left,*right, *tmp;
+	__u8 order;
+
+	left = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
+	ASSERT(left);
+	list_remove(left);
+	while (1) {
+		if (! b->op->get_order(b,left)) {
+			b->op->mark_busy(b, left);
+			return left;
+		}
+		
+		order = b->op->get_order(b, left);
+
+		right = b->op->bisect(b, left);
+		b->op->set_order(b, left, order-1);
+		b->op->set_order(b, right, order-1);
+
+		tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
+
+		if (tmp == right) {
+			right = left;
+			left = tmp;
+		}
+		b->op->mark_busy(b, left);
+		buddy_system_free(b, right);
+		b->op->mark_available(b, left);
+	}
 }
 
@@ -138,5 +170,4 @@
 		return res;
 	}
-	
 	/*
 	 * If order i is already the maximal order,
@@ -168,6 +199,6 @@
 	
 	/*
-	 * Return the other half to buddy system.
-	 * PROBLEM!!!! WILL FIND OTHER PART AS BUDDY AND LINK TOGETHER
+	 * Return the other half to buddy system. Mark the first part
+	 * full, so that it won't coalsce again.
 	 */
 	b->op->mark_busy(b, res);
Index: generic/src/mm/frame.c
===================================================================
--- generic/src/mm/frame.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/mm/frame.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -28,7 +28,16 @@
  */
 
+/*
+ * Locking order
+ *
+ * In order to access particular zone, the process must first lock
+ * the zones.lock, then lock the zone and then unlock the zones.lock.
+ * This insures, that we can fiddle with the zones in runtime without
+ * affecting the processes. 
+ *
+ */
+
 #include <typedefs.h>
 #include <arch/types.h>
-#include <mm/heap.h>
 #include <mm/frame.h>
 #include <mm/as.h>
@@ -41,15 +50,330 @@
 #include <print.h>
 #include <align.h>
-
-SPINLOCK_INITIALIZE(zone_head_lock);	/**< this lock protects zone_head list */
-LIST_INITIALIZE(zone_head);            	/**< list of all zones in the system */
-
-/** Blacklist containing non-available areas of memory.
- *
- * This blacklist is used to exclude frames that cannot be allocated
- * (e.g. kernel memory) from available memory map.
- */
-region_t zone_blacklist[ZONE_BLACKLIST_SIZE];
-count_t zone_blacklist_count = 0;
+#include <mm/slab.h>
+
+typedef struct {
+	count_t refcount;	/**< tracking of shared frames  */
+	__u8 buddy_order;	/**< buddy system block order */
+	link_t buddy_link;	/**< link to the next free block inside one order */
+	void *parent;           /**< If allocated by slab, this points there */
+}frame_t;
+
+typedef struct {
+	SPINLOCK_DECLARE(lock);	/**< this lock protects everything below */
+	pfn_t base;	/**< frame_no of the first frame in the frames array */
+	pfn_t count;          /**< Size of zone */
+
+	frame_t *frames;	/**< array of frame_t structures in this zone */
+	count_t free_count;	/**< number of free frame_t structures */
+	count_t busy_count;	/**< number of busy frame_t structures */
+	
+	buddy_system_t * buddy_system; /**< buddy system for the zone */
+	int flags;
+}zone_t;
+
+/*
+ * The zoneinfo.lock must be locked when accessing zoneinfo structure.
+ * Some of the attributes in zone_t structures are 'read-only'
+ */
+
+struct {
+	SPINLOCK_DECLARE(lock);
+	int count;
+	zone_t *info[ZONES_MAX];
+}zones;
+
+
+/*********************************/
+/* Helper functions */
+static inline index_t frame_index(zone_t *zone, frame_t *frame)
+{
+	return (index_t)(frame - zone->frames);
+}
+static inline index_t frame_index_abs(zone_t *zone, frame_t *frame)
+{
+	return (index_t)(frame - zone->frames) + zone->base;
+}
+static inline int frame_index_valid(zone_t *zone, index_t index)
+{
+	return index >= 0 && index < zone->count;
+}
+
+/** Compute pfn_t from frame_t pointer & zone pointer */
+static pfn_t make_frame_index(zone_t *zone, frame_t *frame)
+{
+	return frame - zone->frames;
+}
+
+/** Initialize frame structure
+ *
+ * Initialize frame structure.
+ *
+ * @param frame Frame structure to be initialized.
+ */
+static void frame_initialize(frame_t *frame)
+{
+	frame->refcount = 1;
+	frame->buddy_order = 0;
+}
+
+/*************************************/
+/* Zoneinfo functions */
+
+/**
+ * Insert-sort zone into zones list
+ */
+static void zones_add_zone(zone_t *zone)
+{
+	int i;
+
+	spinlock_lock(&zones.lock);
+	/* Try to merge */
+	if (zone->flags & ZONE_JOIN) {
+		for (i=0; i < zones.count; i++) {
+			spinlock_lock(&zones.info[i]->lock);
+			
+			/* Join forward, join backward */
+			panic("Not implemented");
+
+			spinlock_unlock(&zones.info[i]->lock);
+		}
+		spinlock_unlock(&zones.lock);
+	} else {
+		if (zones.count+1 == ZONES_MAX)
+			panic("Maximum zone(%d) count exceeded.", ZONES_MAX);
+		zones.info[zones.count++] = zone;
+	}
+	spinlock_unlock(&zones.lock);
+}
+
+/**
+ * Try to find a zone where can we find the frame
+ *
+ * @param hint Start searching in zone 'hint'
+ * @param lock Lock zone if true
+ *
+ * Assume interrupts disable
+ */
+static zone_t * find_zone_and_lock(pfn_t frame, int *pzone)
+{
+	int i;
+	int hint = pzone ? *pzone : 0;
+	zone_t *z;
+	
+	spinlock_lock(&zones.lock);
+
+	if (hint >= zones.count || hint < 0)
+		hint = 0;
+	
+	i = hint;
+	do {
+		z = zones.info[i];
+		spinlock_lock(&z->lock);
+		if (z->base <= frame && z->base + z->count > frame) {
+			spinlock_unlock(&zones.lock); /* Unlock the global lock */
+			if (pzone)
+				*pzone = i;
+			return z;
+		}
+		spinlock_unlock(&z->lock);
+
+		i++;
+		if (i >= zones.count)
+			i = 0;
+	} while(i != hint);
+
+	spinlock_unlock(&zones.lock);
+	return NULL;
+}
+
+/**
+ * Find AND LOCK zone that can allocate order frames
+ *
+ * Assume interrupts are disabled!!
+ *
+ * @param pzone Pointer to preferred zone or NULL, on return contains zone number
+ */
+static zone_t * find_free_zone_lock(__u8 order, int *pzone)
+{
+	int i;
+	zone_t *z;
+	int hint = pzone ? *pzone : 0;
+	
+	spinlock_lock(&zones.lock);
+	if (hint >= zones.count)
+		hint = 0;
+	i = hint;
+	do {
+		z = zones.info[i];
+		
+		spinlock_lock(&z->lock);
+
+		/* Check if the zone has 2^order frames area available  */
+		if (buddy_system_can_alloc(z->buddy_system, order)) {
+			spinlock_unlock(&zones.lock);
+			if (pzone)
+				*pzone = i;
+			return z;
+		}
+		spinlock_unlock(&z->lock);
+		if (++i >= zones.count)
+			i = 0;
+	} while(i != hint);
+	spinlock_unlock(&zones.lock);
+	return NULL;
+}
+
+/********************************************/
+/* Buddy system functions */
+
+/** Buddy system find_block implementation
+ *
+ * Find block that is parent of current list.
+ * That means go to lower addresses, until such block is found
+ *
+ * @param order - Order of parent must be different then this parameter!!
+ */
+static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
+				     __u8 order)
+{
+	frame_t * frame;
+	zone_t * zone;
+	index_t index;
+	
+	frame = list_get_instance(child, frame_t, buddy_link);
+	zone = (zone_t *) b->data;
+
+	index = frame_index(zone, frame);
+	do {
+		if (zone->frames[index].buddy_order != order) {
+			return &zone->frames[index].buddy_link;
+		}
+	} while(index-- > 0);
+	return NULL;
+}
+
+				     
+
+/** Buddy system find_buddy implementation
+ *
+ * @param b Buddy system.
+ * @param block Block for which buddy should be found
+ *
+ * @return Buddy for given block if found
+ */
+static link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) 
+{
+	frame_t * frame;
+	zone_t * zone;
+	index_t index;
+	bool is_left, is_right;
+
+	frame = list_get_instance(block, frame_t, buddy_link);
+	zone = (zone_t *) b->data;
+	ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), frame->buddy_order));
+	
+	is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
+	is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
+
+	ASSERT(is_left ^ is_right);
+	if (is_left) {
+		index = (frame_index(zone, frame)) + (1 << frame->buddy_order);
+	} else { // if (is_right)
+		index = (frame_index(zone, frame)) - (1 << frame->buddy_order);
+	}
+	
+
+	if (frame_index_valid(zone, index)) {
+		if (zone->frames[index].buddy_order == frame->buddy_order && 
+		    zone->frames[index].refcount == 0) {
+			return &zone->frames[index].buddy_link;
+		}
+	}
+
+	return NULL;	
+}
+
+/** Buddy system bisect implementation
+ *
+ * @param b Buddy system.
+ * @param block Block to bisect
+ *
+ * @return right block
+ */
+static link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) {
+	frame_t * frame_l, * frame_r;
+
+	frame_l = list_get_instance(block, frame_t, buddy_link);
+	frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
+	
+	return &frame_r->buddy_link;
+}
+
+/** Buddy system coalesce implementation
+ *
+ * @param b Buddy system.
+ * @param block_1 First block
+ * @param block_2 First block's buddy
+ *
+ * @return Coalesced block (actually block that represents lower address)
+ */
+static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, 
+				    link_t * block_2) {
+	frame_t *frame1, *frame2;
+	
+	frame1 = list_get_instance(block_1, frame_t, buddy_link);
+	frame2 = list_get_instance(block_2, frame_t, buddy_link);
+	
+	return frame1 < frame2 ? block_1 : block_2;
+}
+
+/** Buddy system set_order implementation
+ *
+ * @param b Buddy system.
+ * @param block Buddy system block
+ * @param order Order to set
+ */
+static void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) {
+	frame_t * frame;
+	frame = list_get_instance(block, frame_t, buddy_link);
+	frame->buddy_order = order;
+}
+
+/** Buddy system get_order implementation
+ *
+ * @param b Buddy system.
+ * @param block Buddy system block
+ *
+ * @return Order of block
+ */
+static __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) {
+	frame_t * frame;
+	frame = list_get_instance(block, frame_t, buddy_link);
+	return frame->buddy_order;
+}
+
+/** Buddy system mark_busy implementation
+ *
+ * @param b Buddy system
+ * @param block Buddy system block
+ *
+ */
+static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
+	frame_t * frame;
+	frame = list_get_instance(block, frame_t, buddy_link);
+	frame->refcount = 1;
+}
+
+/** Buddy system mark_available implementation
+ *
+ * @param b Buddy system
+ * @param block Buddy system block
+ *
+ */
+static void zone_buddy_mark_available(buddy_system_t *b, link_t * block) {
+	frame_t * frame;
+	frame = list_get_instance(block, frame_t, buddy_link);
+	frame->refcount = 0;
+}
 
 static struct buddy_system_operations  zone_buddy_system_operations = {
@@ -60,43 +384,225 @@
 	.get_order = zone_buddy_get_order,
 	.mark_busy = zone_buddy_mark_busy,
+	.mark_available = zone_buddy_mark_available,
+	.find_block = zone_buddy_find_block
 };
 
-/** Initialize physical memory management
- *
- * Initialize physical memory managemnt.
- */
-void frame_init(void)
-{
-	if (config.cpu_active == 1) {
-		frame_region_not_free(KA2PA(config.base), config.kernel_size);
-		if (config.init_size > 0)
-			frame_region_not_free(KA2PA(config.init_addr), config.init_size);
-	}
-
-	frame_arch_init();
-}
-
-/**
- * Find AND LOCK zone that can allocate order frames
- *
- * Assume zone_head_lock is locked.
- */
-static zone_t * find_free_zone(__u8 order)
-{
-	link_t *cur;
+/*************************************/
+/* Zone functions */
+
+/** Allocate frame in particular zone
+ *
+ * Assume zone is locked
+ *
+ * @return Frame index in zone
+ */
+static pfn_t zone_frame_alloc(zone_t *zone,__u8 order, int flags, int *status)
+{
+	pfn_t v;
+	link_t *tmp;
+	frame_t *frame;
+
+	/* Allocate frames from zone buddy system */
+	tmp = buddy_system_alloc(zone->buddy_system, order);
+	
+	ASSERT(tmp);
+	
+	/* Update zone information. */
+	zone->free_count -= (1 << order);
+	zone->busy_count += (1 << order);
+
+	/* Frame will be actually a first frame of the block. */
+	frame = list_get_instance(tmp, frame_t, buddy_link);
+	
+	/* get frame address */
+	v = make_frame_index(zone, frame);
+	return v;
+}
+
+/** Free frame from zone
+ *
+ * Assume zone is locked
+ */
+static void zone_frame_free(zone_t *zone, pfn_t frame_idx)
+{
+	frame_t *frame;
+	__u8 order;
+
+	frame = &zone->frames[frame_idx];
+	
+	/* remember frame order */
+	order = frame->buddy_order;
+
+	ASSERT(frame->refcount);
+
+	if (!--frame->refcount) {
+		buddy_system_free(zone->buddy_system, &frame->buddy_link);
+	}
+
+	/* Update zone information. */
+	zone->free_count += (1 << order);
+	zone->busy_count -= (1 << order);
+}
+
+/** Return frame from zone */
+static frame_t * zone_get_frame(zone_t *zone, pfn_t frame_idx)
+{
+	ASSERT(frame_idx < zone->count);
+	return &zone->frames[frame_idx];
+}
+
+/** Mark frame in zone unavailable to allocation */
+static void zone_mark_unavailable(zone_t *zone, pfn_t frame_idx)
+{
+	frame_t *frame;
+	link_t *link;
+
+	frame = zone_get_frame(zone, frame_idx);
+	link = buddy_system_alloc_block(zone->buddy_system, 
+					&frame->buddy_link);
+	ASSERT(link);
+	zone->free_count--;
+}
+
+/** Create frame zone
+ *
+ * Create new frame zone.
+ *
+ * @param start Physical address of the first frame within the zone.
+ * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
+ * @param conffram Address of configuration frame
+ * @param flags Zone flags.
+ *
+ * @return Initialized zone.
+ */
+static zone_t * zone_construct(pfn_t start, pfn_t count, 
+			       zone_t *z, int flags)
+{
+	int i;
+	__u8 max_order;
+
+	spinlock_initialize(&z->lock, "zone_lock");
+	z->base = start;
+	z->count = count;
+	z->flags = flags;
+	z->free_count = count;
+	z->busy_count = 0;
+
+	/*
+	 * Compute order for buddy system, initialize
+	 */
+	for (max_order = 0; count >> max_order; max_order++)
+		;
+	z->buddy_system = (buddy_system_t *)&z[1];
+	
+	buddy_system_create(z->buddy_system, max_order, 
+			    &zone_buddy_system_operations, 
+			    (void *) z);
+	
+	/* Allocate frames _after_ the conframe */
+	/* Check sizes */
+	z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order));
+
+	for (i = 0; i<count; i++) {
+		frame_initialize(&z->frames[i]);
+	}
+	/* Stuffing frames */
+	for (i = 0; i < count; i++) {
+		z->frames[i].refcount = 0;
+		buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);
+	}
+	return z;
+}
+
+
+/** Compute configuration data size for zone */
+__address zone_conf_size(pfn_t start, pfn_t count)
+{
+	int size = sizeof(zone_t) + count*sizeof(frame_t);
+	int max_order;
+
+	for (max_order = 0; count >> max_order; max_order++)
+		;
+	size += buddy_conf_size(max_order);
+	return size;
+}
+
+/** Create and add zone to system
+ *
+ * @param confframe Where configuration frame is supposed to be.
+ *                  Always check, that we will not disturb kernel pages
+ *                  the kernel and possibly init. 
+ *                  If confframe is given _outside_ this zone, it is expected,
+ *                  that the area is already marked BUSY and big enough
+ *                  to contain zone_conf_size() amount of data
+ */
+void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags)
+{
 	zone_t *z;
-
-	for (cur = zone_head.next; cur != &zone_head;cur = cur->next) {
-		z = list_get_instance(cur, zone_t, link);
-		
-		spinlock_lock(&z->lock);
-		
-		/* Check if the zone has 2^order frames area available  */
-		if (buddy_system_can_alloc(z->buddy_system, order))
-			return z;
-		
-		spinlock_unlock(&z->lock);
-	}
-	return NULL;
+	__address addr,endaddr;
+	pfn_t confcount;
+	int i;
+
+	/* Theoretically we could have here 0, practically make sure
+	 * nobody tries to do that. If some platform requires, remove
+	 * the assert
+	 */
+	ASSERT(confframe);
+	/* If conframe is supposed to be inside our zone, then make sure
+	 * it does not span kernel & init
+	 */
+	confcount = SIZE2PFN(zone_conf_size(start,count));
+	if (confframe >= start && confframe < start+count) {
+		for (;confframe < start+count;confframe++) {
+			addr = PFN2ADDR(confframe);
+			endaddr =  PFN2ADDR (confframe + confcount);
+			if (overlaps(addr, endaddr, KA2PA(config.base),
+				     KA2PA(config.base+config.kernel_size)))
+				continue;
+			if (config.init_addr)
+				if (overlaps(addr,endaddr, 
+					     KA2PA(config.init_addr),
+					     KA2PA(config.init_addr+config.init_size)))
+					continue;
+			break;
+		}
+		if (confframe >= start+count)
+			panic("Cannot find configuration data for zone.");
+	}
+
+	z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags);
+	zones_add_zone(z);
+	
+	/* If confdata in zone, mark as unavailable */
+	if (confframe >= start && confframe < start+count)
+		for (i=confframe; i<confframe+confcount; i++) {
+			zone_mark_unavailable(z, i - z->base);
+		}
+}
+
+/***************************************/
+/* Frame functions */
+
+/** Set parent of frame */
+void frame_set_parent(pfn_t pfn, void *data, int hint)
+{
+	zone_t *zone = find_zone_and_lock(pfn, &hint);
+
+	ASSERT(zone);
+
+	zone_get_frame(zone, pfn-zone->base)->parent = data;
+	spinlock_unlock(&zone->lock);
+}
+
+void * frame_get_parent(pfn_t pfn, int hint)
+{
+	zone_t *zone = find_zone_and_lock(pfn, &hint);
+	void *res;
+
+	ASSERT(zone);
+	res = zone_get_frame(zone, pfn - zone->base)->parent;
+	
+	spinlock_unlock(&zone->lock);
+	return res;
 }
 
@@ -105,52 +611,33 @@
  * @param flags Flags for host zone selection and address processing.
  * @param order Allocate exactly 2^order frames.
- * @param pzone Pointer to preferred zone pointer, on output it changes
- *              to the zone that the frame was really allocated to
+ * @param pzone Preferred zone
  *
  * @return Allocated frame.
  */
-__address frame_alloc_generic(__u8 order, int flags, int * status, zone_t **pzone) 
+pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone) 
 {
 	ipl_t ipl;
-	link_t *tmp;
-	zone_t *zone = NULL;
-	frame_t *frame = NULL;
 	int freed;
-	__address v;
+	pfn_t v;
+	zone_t *zone;
 	
 loop:
 	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
-
 	/*
 	 * First, find suitable frame zone.
 	 */
-	if (pzone && *pzone) {
-		spinlock_lock(&(*pzone)->lock);
-		if (!buddy_system_can_alloc((*pzone)->buddy_system, order))
-			spinlock_unlock(&(*pzone)->lock);
-		else
-			zone = *pzone;
-	}
-	if (!zone) {
-		zone = find_free_zone(order);
-		/* If no memory, reclaim some slab memory,
-		   if it does not help, reclaim all */
-		if (!zone && !(flags & FRAME_NO_RECLAIM)) {
-			spinlock_unlock(&zone_head_lock);
-			freed = slab_reclaim(0);
-			spinlock_lock(&zone_head_lock);
+	zone = find_free_zone_lock(order,pzone);
+	/* If no memory, reclaim some slab memory,
+	   if it does not help, reclaim all */
+	if (!zone && !(flags & FRAME_NO_RECLAIM)) {
+		freed = slab_reclaim(0);
+		if (freed)
+			zone = find_free_zone_lock(order,pzone);
+		if (!zone) {
+			freed = slab_reclaim(SLAB_RECLAIM_ALL);
 			if (freed)
-				zone = find_free_zone(order);
-			if (!zone) {
-				spinlock_unlock(&zone_head_lock);
-				freed = slab_reclaim(SLAB_RECLAIM_ALL);
-				spinlock_lock(&zone_head_lock);
-				if (freed)
-					zone = find_free_zone(order);
-			}
-		}
-	}
-
+				zone = find_free_zone_lock(order,pzone);
+		}
+	}
 	if (!zone) {
 		if (flags & FRAME_PANIC)
@@ -160,10 +647,10 @@
 		 * TODO: Sleep until frames are available again.
 		 */
-		spinlock_unlock(&zone_head_lock);
 		interrupts_restore(ipl);
 
 		if (flags & FRAME_ATOMIC) {
 			ASSERT(status != NULL);
-			*status = FRAME_NO_MEMORY;
+			if (status)
+				*status = FRAME_NO_MEMORY;
 			return NULL;
 		}
@@ -172,95 +659,14 @@
 		goto loop;
 	}
-		
-	/* Allocate frames from zone buddy system */
-	tmp = buddy_system_alloc(zone->buddy_system, order);
-	
-	ASSERT(tmp);
-	
-	/* Update zone information. */
-	zone->free_count -= (1 << order);
-	zone->busy_count += (1 << order);
-
-	/* Frame will be actually a first frame of the block. */
-	frame = list_get_instance(tmp, frame_t, buddy_link);
-	
-	/* get frame address */
-	v = FRAME2ADDR(zone, frame);
+	v = zone_frame_alloc(zone,order,flags,status);
+	v += zone->base;
 
 	spinlock_unlock(&zone->lock);
-	spinlock_unlock(&zone_head_lock);
 	interrupts_restore(ipl);
 
-	ASSERT(v == ALIGN_UP(v, FRAME_SIZE << order));
-
-	if (flags & FRAME_KA)
-		v = PA2KA(v);
-	
 	if (status)
 		*status = FRAME_OK;
-
-	if (pzone)
-		*pzone = zone;
 	return v;
 }
-
-/** Convert address to zone pointer
- *
- * Assume zone_head_lock is held
- *
- * @param addr Physical address
- * @param lock If true, lock the zone
- */
-static zone_t * addr2zone(__address addr, int lock)
-{
-	link_t *cur;
-	zone_t *z = NULL;
-
-	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
-		z = list_get_instance(cur, zone_t, link);
-		
-		spinlock_lock(&z->lock);
-		
-		/*
-		 * Check if addr belongs to z.
-		 */
-		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
-			if (!lock)
-				spinlock_unlock(&z->lock);
-			return z;
-		}
-
-		spinlock_unlock(&z->lock);
-	}
-
-	panic("Cannot find addr2zone: 0x%X", addr);
-}
-
-/** Return frame_t structure corresponding to address
- *
- * 
- */
-frame_t * frame_addr2frame(__address addr)
-{
-	ipl_t ipl;
-	frame_t *frame;
-	zone_t *zone;
-
-	if (IS_KA(addr))
-		addr = KA2PA(addr);
-
-	/* Disable interrupts to avoid deadlocks with interrupt handlers */
-	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
-	
-	zone = addr2zone(addr,0);
-	frame = ADDR2FRAME(zone, addr);
-
-	spinlock_unlock(&zone_head_lock);
-	interrupts_restore(ipl);
-
-	return frame;
-}
-
 
 /** Free a frame.
@@ -270,317 +676,66 @@
  * If it drops to zero, move the frame structure to free list.
  *
- * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
- */
-void frame_free(__address addr)
+ * @param frame Frame no to be freed.
+ */
+void frame_free(pfn_t pfn)
 {
 	ipl_t ipl;
 	zone_t *zone;
-	frame_t *frame;
-	int order;
-	
-	ASSERT(addr % FRAME_SIZE == 0);
-	
-	if (IS_KA(addr))
-		addr = KA2PA(addr);
 
 	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
 	
 	/*
 	 * First, find host frame zone for addr.
 	 */
-	zone = addr2zone(addr, 1); /* This locks the zone automatically */
-	
-	frame = ADDR2FRAME(zone, addr);
-	
-	/* remember frame order */
-	order = frame->buddy_order;
-
-	ASSERT(frame->refcount);
-
-	if (!--frame->refcount) {
-		buddy_system_free(zone->buddy_system, &frame->buddy_link);
-	}
-
-	/* Update zone information. */
-	zone->free_count += (1 << order);
-	zone->busy_count -= (1 << order);
+	zone = find_zone_and_lock(pfn,NULL);
+	ASSERT(zone);
+	
+	zone_frame_free(zone, pfn-zone->base);
 	
 	spinlock_unlock(&zone->lock);
-	spinlock_unlock(&zone_head_lock);
 	interrupts_restore(ipl);
 }
 
-/** Mark frame region not free.
- *
- * Mark frame region not free.
- *
- * @param base Base address of non-available region.
- * @param size Size of non-available region.
- */
-void frame_region_not_free(__address base, size_t size)
-{
-	index_t index;
-	index = zone_blacklist_count++;
-
-	/* Force base to the nearest lower address frame boundary. */
-	base = ALIGN_DOWN(base, FRAME_SIZE);
-	/* Align size to frame boundary. */
-	size = ALIGN_UP(size, FRAME_SIZE);
-
-	ASSERT(index < ZONE_BLACKLIST_SIZE);
-	zone_blacklist[index].base = base;
-	zone_blacklist[index].size = size;
-}
-
-/** Create frame zones in region of available memory.
- *
- * Avoid any black listed areas of non-available memory.
- * Assume that the black listed areas cannot overlap
- * one another or cross available memory region boundaries.
- *
- * @param base Base address of available memory region.
- * @param size Size of the region.
- */
-void zone_create_in_region(__address base, size_t size) {
+
+
+/** Mark given range unavailable in frame zones */
+void frame_mark_unavailable(pfn_t start, pfn_t count)
+{
 	int i;
-	zone_t * z;
-	__address s;
-	size_t sz;
-	
-	ASSERT(base % FRAME_SIZE == 0);
-	ASSERT(size % FRAME_SIZE == 0);
-	
-	if (!size)
-		return;
-
-	for (i = 0; i < zone_blacklist_count; i++) {
-		if (zone_blacklist[i].base >= base && zone_blacklist[i].base < base + size) {
-			s = base; sz = zone_blacklist[i].base - base;
-			ASSERT(base != s || sz != size);
-			zone_create_in_region(s, sz);
-			
-			s = zone_blacklist[i].base + zone_blacklist[i].size;
-			sz = (base + size) - (zone_blacklist[i].base + zone_blacklist[i].size);
-			ASSERT(base != s || sz != size);
-			zone_create_in_region(s, sz);
-			return;
-		
-		}
-	}
-	
-	z = zone_create(base, size, 0);
-
-	if (!z) {
-		panic("Cannot allocate zone (base=%P, size=%d).\n", base, size);
-	}
-	
-	zone_attach(z);
-}
-
-
-/** Create frame zone
- *
- * Create new frame zone.
- *
- * @param start Physical address of the first frame within the zone.
- * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
- * @param flags Zone flags.
- *
- * @return Initialized zone.
- */
-zone_t * zone_create(__address start, size_t size, int flags)
-{
-	zone_t *z;
-	count_t cnt;
-	int i;
-	__u8 max_order;
-
-	ASSERT(start % FRAME_SIZE == 0);
-	ASSERT(size % FRAME_SIZE == 0);
-	
-	cnt = size / FRAME_SIZE;
-	
-	z = (zone_t *) early_malloc(sizeof(zone_t));
-	if (z) {
-		link_initialize(&z->link);
-		spinlock_initialize(&z->lock, "zone_lock");
-	
-		z->base = start;
-		z->base_index = start / FRAME_SIZE;
-		
-		z->flags = flags;
-
-		z->free_count = cnt;
-		z->busy_count = 0;
-		
-		z->frames = (frame_t *) early_malloc(cnt * sizeof(frame_t));
-		if (!z->frames) {
-			early_free(z);
-			return NULL;
-		}
-		
-		for (i = 0; i<cnt; i++) {
-			frame_initialize(&z->frames[i], z);
-		}
-		
-		/*
-		 * Create buddy system for the zone
-		 */
-		for (max_order = 0; cnt >> max_order; max_order++)
-			;
-		z->buddy_system = buddy_system_create(max_order, &zone_buddy_system_operations, (void *) z);
-		
-		/* Stuffing frames */
-		for (i = 0; i<cnt; i++) {
-			z->frames[i].refcount = 0;
-			buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);	
-		}
-		
-	}
-	return z;
-}
-
-/** Attach frame zone
- *
- * Attach frame zone to zone list.
- *
- * @param zone Zone to be attached.
- */
-void zone_attach(zone_t *zone)
-{
-	ipl_t ipl;
-	
-	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
-	
-	list_append(&zone->link, &zone_head);
-	
-	spinlock_unlock(&zone_head_lock);
-	interrupts_restore(ipl);
-}
-
-/** Initialize frame structure
- *
- * Initialize frame structure.
- *
- * @param frame Frame structure to be initialized.
- * @param zone Host frame zone.
- */
-void frame_initialize(frame_t *frame, zone_t *zone)
-{
-	frame->refcount = 1;
-	frame->buddy_order = 0;
-}
-
-
-/** Buddy system find_buddy implementation
- *
- * @param b Buddy system.
- * @param block Block for which buddy should be found
- *
- * @return Buddy for given block if found
- */
-link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) {
-	frame_t * frame;
-	zone_t * zone;
-	index_t index;
-	bool is_left, is_right;
-
-	frame = list_get_instance(block, frame_t, buddy_link);
-	zone = (zone_t *) b->data;
-	ASSERT(IS_BUDDY_ORDER_OK(FRAME_INDEX_ABS(zone, frame), frame->buddy_order));
-	
-	
-	is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
-	is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
-	
-	ASSERT(is_left ^ is_right);
-	
-	if (is_left) {
-		index = (FRAME_INDEX(zone, frame)) + (1 << frame->buddy_order);
-	} else { // if (is_right)
-		index = (FRAME_INDEX(zone, frame)) - (1 << frame->buddy_order);
-	}
-	
-	if (FRAME_INDEX_VALID(zone, index)) {
-		if (	zone->frames[index].buddy_order == frame->buddy_order && 
-			zone->frames[index].refcount == 0) {
-			return &zone->frames[index].buddy_link;
-		}
-	}
-	
-	return NULL;	
-}
-
-/** Buddy system bisect implementation
- *
- * @param b Buddy system.
- * @param block Block to bisect
- *
- * @return right block
- */
-link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) {
-	frame_t * frame_l, * frame_r;
-
-	frame_l = list_get_instance(block, frame_t, buddy_link);
-	frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
-	
-	return &frame_r->buddy_link;
-}
-
-/** Buddy system coalesce implementation
- *
- * @param b Buddy system.
- * @param block_1 First block
- * @param block_2 First block's buddy
- *
- * @return Coalesced block (actually block that represents lower address)
- */
-link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, link_t * block_2) {
-	frame_t * frame1, * frame2;
-	
-	frame1 = list_get_instance(block_1, frame_t, buddy_link);
-	frame2 = list_get_instance(block_2, frame_t, buddy_link);
-	
-	return frame1 < frame2 ? block_1 : block_2;
-}
-
-/** Buddy system set_order implementation
- *
- * @param b Buddy system.
- * @param block Buddy system block
- * @param order Order to set
- */
-void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) {
-	frame_t * frame;
-	frame = list_get_instance(block, frame_t, buddy_link);
-	frame->buddy_order = order;
-}
-
-/** Buddy system get_order implementation
- *
- * @param b Buddy system.
- * @param block Buddy system block
- *
- * @return Order of block
- */
-__u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) {
-	frame_t * frame;
-	frame = list_get_instance(block, frame_t, buddy_link);
-	return frame->buddy_order;
-}
-
-/** Buddy system mark_busy implementation
- *
- * @param b Buddy system
- * @param block Buddy system block
- *
- */
-void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
-	frame_t * frame;
-	frame = list_get_instance(block, frame_t, buddy_link);
-	frame->refcount = 1;
-}
+	zone_t *zone;
+	int prefzone = 0;
+
+	for (i=0; i<count; i++) {
+		zone = find_zone_and_lock(start+i,&prefzone);
+		if (!zone) /* PFN not found */
+			continue;
+		zone_mark_unavailable(zone, start+i-zone->base);
+
+		spinlock_unlock(&zone->lock);
+	}
+}
+
+/** Initialize physical memory management
+ *
+ * Initialize physical memory managemnt.
+ */
+void frame_init(void)
+{
+	if (config.cpu_active == 1) {
+		zones.count = 0;
+		spinlock_initialize(&zones.lock,"zones_glob_lock");
+	}
+	/* Tell the architecture to create some memory */
+	frame_arch_init();
+	if (config.cpu_active == 1) {
+		frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
+				       SIZE2PFN(config.kernel_size));
+		if (config.init_size > 0)
+			frame_mark_unavailable(ADDR2PFN(KA2PA(config.init_addr)),
+					       SIZE2PFN(config.init_size));
+	}
+}
+
+
 
 /** Prints list of zones
@@ -589,18 +744,19 @@
 void zone_print_list(void) {
 	zone_t *zone = NULL;
-	link_t *cur;
+	int i;
 	ipl_t ipl;
 
 	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
+	spinlock_lock(&zones.lock);
 	printf("Base address\tFree Frames\tBusy Frames\n");
 	printf("------------\t-----------\t-----------\n");
-	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
-		zone = list_get_instance(cur, zone_t, link);
+	for (i=0;i<zones.count;i++) {
+		zone = zones.info[i];
 		spinlock_lock(&zone->lock);
-		printf("%L\t%d\t\t%d\n",zone->base, zone->free_count, zone->busy_count);
+		printf("%L\t%d\t\t%d\n",PFN2ADDR(zone->base), 
+		       zone->free_count, zone->busy_count);
 		spinlock_unlock(&zone->lock);
 	}
-	spinlock_unlock(&zone_head_lock);
+	spinlock_unlock(&zones.lock);
 	interrupts_restore(ipl);
 }
@@ -610,31 +766,24 @@
  * @param base Zone base address
  */
-void zone_print_one(__address base) {
-	zone_t *zone = NULL, *z	;
-	link_t *cur;
+void zone_print_one(int znum) {
+	zone_t *zone = NULL;
 	ipl_t ipl;
 
 	ipl = interrupts_disable();
-	spinlock_lock(&zone_head_lock);
-	
-	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
-		z = list_get_instance(cur, zone_t, link);
-		if (base == z->base) { 
-			zone = z;
-			break;
-		}
-	}
-	
-	if (!zone) {
-		spinlock_unlock(&zone_head_lock);
+	spinlock_lock(&zones.lock);
+	
+	if (znum >= zones.count || znum < 0) {
+		printf("Zone number out of bounds.\n");
+		spinlock_unlock(&zones.lock);
 		interrupts_restore(ipl);
-		printf("No zone with address %X\n", base);
 		return;
 	}
+	
+	zone = zones.info[znum];
 	
 	spinlock_lock(&zone->lock);
 	printf("Memory zone information\n\n");
-	printf("Zone base address: %P\n", zone->base);
-	printf("Zone size: %d frames (%dK)\n", zone->free_count + zone->busy_count, ((zone->free_count + zone->busy_count) * FRAME_SIZE) >> 10);
+	printf("Zone base address: %P\n", PFN2ADDR(zone->base));
+	printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10);
 	printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10);
 	printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10);
@@ -644,5 +793,5 @@
 	
 	spinlock_unlock(&zone->lock);
-	spinlock_unlock(&zone_head_lock);
+	spinlock_unlock(&zones.lock);
 	interrupts_restore(ipl);
 }
Index: neric/src/mm/heap.c
===================================================================
--- generic/src/mm/heap.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ 	(revision )
@@ -1,157 +1,0 @@
-/*
- * Copyright (C) 2001-2004 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <mm/heap.h>
-#include <synch/spinlock.h>
-#include <func.h>
-#include <memstr.h>
-#include <panic.h>
-#include <arch/types.h>
-#include <arch/asm.h>
-#include <arch.h>
-#include <align.h>
-
-/*
- * First-fit algorithm.
- * Simple, but hopefully correct.
- * Chunks being freed are tested for mergability with their neighbours.
- */
-
-static chunk_t *chunk0;
-SPINLOCK_INITIALIZE(heaplock);
-
-void early_heap_init(__address heap, size_t size)
-{
-	memsetb(heap, size, 0);
-	chunk0 = (chunk_t *) heap;
-	chunk0->used = 0;
-	chunk0->size = size - sizeof(chunk_t);
-	chunk0->next = NULL;
-	chunk0->prev = NULL;
-}
-
-/*
- * Uses first-fit algorithm.
- */
-void *early_malloc(size_t size)
-{
-	ipl_t ipl;
-	chunk_t *x, *y, *z;
-
-	if (size == 0)
-		panic("zero-size allocation request");
-		
-	size = ALIGN_UP(size, sizeof(__native));
-
-	x = chunk0;
-	ipl = interrupts_disable();
-	spinlock_lock(&heaplock);		
-	while (x) {
-		if (x->used || x->size < size) {
-			x = x->next;
-			continue;
-		}
-		
-		x->used = 1;
-    
-		/*
-		 * If the chunk exactly matches required size or if truncating
-		 * it would not provide enough space for storing a new chunk
-		 * header plus at least one byte of data, we are finished.
-		 */
-		if (x->size < size + sizeof(chunk_t) + 1) {
-			spinlock_unlock(&heaplock);
-			interrupts_restore(ipl);
-			return &x->data[0];
-		}
-
-		/*
-		 * Truncate x and create a new chunk.
-		 */
-		y = (chunk_t *) (((__address) x) + size + sizeof(chunk_t));
-		y->used = 0;
-		y->size = x->size - size - sizeof(chunk_t);
-		y->prev = x;
-		y->next = NULL;
-		
-		z = x->next;
-		if (z) {
-			z->prev = y;
-			y->next = z;
-		}
-		
-		x->size = size;
-		x->next = y;
-		spinlock_unlock(&heaplock);
-		interrupts_restore(ipl);
-
-		return &x->data[0];
-	}
-	spinlock_unlock(&heaplock);
-	interrupts_restore(ipl);
-	return NULL;
-}
-
-void early_free(void *ptr)
-{
-	ipl_t ipl;
-	chunk_t *x, *y, *z;
-
-	if (!ptr)
-		panic("free on NULL");
-
-
-	y = (chunk_t *) (((__u8 *) ptr) - sizeof(chunk_t));
-	if (y->used != 1)
-		panic("freeing unused/damaged chunk");
-
-	ipl = interrupts_disable();
-	spinlock_lock(&heaplock);
-	x = y->prev;
-	z = y->next;
-	/* merge x and y */
-	if (x && !x->used) {
-		x->size += y->size + sizeof(chunk_t);
-		x->next = z;
-		if (z)
-			z->prev = x;
-		y = x;
-	}
-	/* merge y and z or merge (x merged with y) and z */
-	if (z && !z->used) {
-		y->size += z->size + sizeof(chunk_t);
-		y->next = z->next;
-		if (z->next)  {
-			/* y is either y or x */
-			z->next->prev = y;
-		}
-	}
-	y->used = 0;
-	spinlock_unlock(&heaplock);
-	interrupts_restore(ipl);
-}
Index: generic/src/mm/slab.c
===================================================================
--- generic/src/mm/slab.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/mm/slab.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -97,5 +97,4 @@
 #include <memstr.h>
 #include <align.h>
-#include <mm/heap.h>
 #include <mm/frame.h>
 #include <config.h>
@@ -155,9 +154,10 @@
 	size_t fsize;
 	int i;
-	zone_t *zone = NULL;
 	int status;
-	frame_t *frame;
-
-	data = (void *)frame_alloc_rc_zone(cache->order, FRAME_KA | flags, &status, &zone);
+	pfn_t pfn;
+	int zone=0;
+	
+	pfn = frame_alloc_rc_zone(cache->order, FRAME_KA | flags, &status, &zone);
+	data = (void *) PA2KA(PFN2ADDR(pfn));
 	if (status != FRAME_OK) {
 		return NULL;
@@ -166,5 +166,5 @@
 		slab = slab_alloc(slab_extern_cache, flags);
 		if (!slab) {
-			frame_free((__address)data);
+			frame_free(ADDR2PFN(KA2PA(data)));
 			return NULL;
 		}
@@ -175,9 +175,6 @@
 		
 	/* Fill in slab structures */
-	/* TODO: some better way of accessing the frame */
-	for (i=0; i < (1 << cache->order); i++) {
-		frame = ADDR2FRAME(zone, KA2PA((__address)(data+i*PAGE_SIZE)));
-		frame->parent = slab;
-	}
+	for (i=0; i < (1 << cache->order); i++)
+		frame_set_parent(pfn+i, slab, zone);
 
 	slab->start = data;
@@ -200,5 +197,5 @@
 static count_t slab_space_free(slab_cache_t *cache, slab_t *slab)
 {
-	frame_free((__address)slab->start);
+	frame_free(ADDR2PFN(KA2PA(slab->start)));
 	if (! (cache->flags & SLAB_CACHE_SLINSIDE))
 		slab_free(slab_extern_cache, slab);
@@ -212,8 +209,5 @@
 static slab_t * obj2slab(void *obj)
 {
-	frame_t *frame; 
-
-	frame = frame_addr2frame((__address)obj);
-	return (slab_t *)frame->parent;
+	return (slab_t *)frame_get_parent(ADDR2PFN(KA2PA(obj)), 0);
 }
 
@@ -726,6 +720,7 @@
 	ipl = interrupts_disable();
 
-	if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
+	if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) {
 		result = magazine_obj_get(cache);
+	}
 	if (!result)
 		result = slab_obj_create(cache, flags);
Index: generic/src/proc/scheduler.c
===================================================================
--- generic/src/proc/scheduler.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/proc/scheduler.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <mm/heap.h>
 #include <mm/frame.h>
 #include <mm/page.h>
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/proc/task.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,5 @@
 #include <proc/task.h>
 #include <mm/as.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 
 #include <synch/spinlock.h>
Index: generic/src/proc/thread.c
===================================================================
--- generic/src/proc/thread.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ generic/src/proc/thread.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <mm/heap.h>
 #include <mm/frame.h>
 #include <mm/page.h>
@@ -96,4 +95,5 @@
 {
 	thread_t *t = (thread_t *)obj;
+	pfn_t pfn;
 
 	spinlock_initialize(&t->lock, "thread_t_lock");
@@ -103,5 +103,6 @@
 	link_initialize(&t->threads_link);
 	
-	t->kstack = (__u8 *)frame_alloc(ONE_FRAME, FRAME_KA | kmflags);
+	pfn = frame_alloc(ONE_FRAME, FRAME_KA | kmflags);
+	t->kstack = (__u8 *)PA2KA(PFN2ADDR(pfn));
 	if (!t->kstack)
 		return -1;
@@ -115,5 +116,5 @@
 	thread_t *t = (thread_t *)obj;
 
-	frame_free((__address) t->kstack);
+	frame_free(ADDR2PFN(KA2PA(t->kstack)));
 	return 1; /* One page freed */
 }
@@ -194,7 +195,4 @@
 	spinlock_unlock(&t->cpu->lock);
 
-	if (t->ustack)
-		frame_free((__address) t->ustack);
-	
 	/*
 	 * Detach from the containing task.
@@ -229,5 +227,4 @@
 {
 	thread_t *t;
-	__address frame_us = NULL;
 
 	t = (thread_t *) slab_alloc(thread_slab, 0);
@@ -235,8 +232,4 @@
 		ipl_t ipl;
 	
-		if (THREAD_USER_STACK & flags) {
-			frame_us = frame_alloc(ONE_FRAME, FRAME_KA);
-		}
-
 		/* Not needed, but good for debugging */
 		memsetb((__address)t->kstack, THREAD_STACK_SIZE, 0);
@@ -247,6 +240,4 @@
 		spinlock_unlock(&tidlock);
 		interrupts_restore(ipl);
-		
-		t->ustack = (__u8 *) frame_us;
 		
 		context_save(&t->saved_context);
Index: test/mm/falloc1/test.c
===================================================================
--- test/mm/falloc1/test.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ test/mm/falloc1/test.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,5 @@
 #include <mm/page.h>
 #include <mm/frame.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <arch/mm/page.h>
 #include <arch/types.h>
@@ -56,5 +56,5 @@
 			allocated = 0;
 			for (i = 0; i < MAX_FRAMES >> order; i++) {
-				frames[allocated] = frame_alloc_rc(order, FRAME_ATOMIC | FRAME_KA, &status);
+				frames[allocated] = PA2KA(PFN2ADDR(frame_alloc_rc(order, FRAME_ATOMIC | FRAME_KA, &status)));
 				
 				if (ALIGN_UP(frames[allocated], FRAME_SIZE << order) != frames[allocated]) {
@@ -81,5 +81,5 @@
 			printf("Deallocating ... ");
 			for (i = 0; i < allocated; i++) {
-				frame_free(frames[i]);
+				frame_free(ADDR2PFN(KA2PA(frames[i])));
 			}
 			printf("done.\n");
Index: test/mm/falloc2/test.c
===================================================================
--- test/mm/falloc2/test.c	(revision eb1b8b6abe4db61ee3c0873c66e1e8043cace67b)
+++ test/mm/falloc2/test.c	(revision 085d973c11067c76c6bb3481033b2ba387555f4a)
@@ -30,5 +30,5 @@
 #include <mm/page.h>
 #include <mm/frame.h>
-#include <mm/heap.h>
+#include <mm/slab.h>
 #include <arch/mm/page.h>
 #include <arch/types.h>
@@ -64,5 +64,5 @@
 			allocated = 0;
 			for (i = 0; i < (MAX_FRAMES >> order); i++) {
-				frames[allocated] = frame_alloc_rc(order, FRAME_ATOMIC | FRAME_KA, &status);
+				frames[allocated] = PA2KA(PFN2ADDR(frame_alloc_rc(order, FRAME_ATOMIC | FRAME_KA, &status)));
 				if (status == 0) {
 					memsetb(frames[allocated], FRAME_SIZE << order, val);
@@ -82,5 +82,5 @@
 					}
 				}
-				frame_free(frames[i]);
+				frame_free(ADDR2PFN(KA2PA(frames[i])));
 			}
 			printf("Thread #%d (cpu%d): Finished run.\n", THREAD->tid, CPU->id);
