Index: kernel/generic/src/mm/buddy.c
===================================================================
--- kernel/generic/src/mm/buddy.c	(revision feeac0d8cd6e0ce736779bc5f1dc701c5cf42ba6)
+++ 	(revision )
@@ -1,284 +1,0 @@
-/*
- * Copyright (c) 2005 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.
- */
-
-/** @addtogroup genericmm
- * @{
- */
-
-/**
- * @file
- * @brief	Buddy allocator framework.
- *
- * This file contains buddy system allocator framework.
- * Specialized functions are needed for this abstract framework to be useful.
- */
-
-#include <mm/buddy.h>
-#include <mm/frame.h>
-#include <typedefs.h>
-#include <debug.h>
-#include <print.h>
-#include <macros.h>
-
-/** Return size needed for the buddy configuration data. */
-size_t buddy_conf_size(size_t 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.
- * @param data		Pointer to be used by implementation.
- *
- * @return		New buddy system.
- */
-void
-buddy_system_create(buddy_system_t *b, uint8_t max_order,
-    buddy_system_operations_t *op, void *data)
-{
-	int i;
-
-	ASSERT(max_order < BUDDY_SYSTEM_INNER_BLOCK);
-
-	ASSERT(op->find_buddy);
-	ASSERT(op->set_order);
-	ASSERT(op->get_order);
-	ASSERT(op->bisect);
-	ASSERT(op->coalesce);
-	ASSERT(op->mark_busy);
-
-	/*
-	 * Use memory after our own structure.
-	 */
-	b->order = (list_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;
-}
-
-/** Check if buddy system can allocate block.
- *
- * @param b		Buddy system pointer.
- * @param i		Size of the block (2^i).
- *
- * @return		True if block can be allocated.
- */
-bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i)
-{
-	uint8_t k;
-	
-	/*
-	 * If requested block is greater then maximal block
-	 * we know immediatly that we cannot satisfy the request.
-	 */
-	if (i > b->max_order)
-		return false;
-
-	/*
-	 * Check if any bigger or equal order has free elements
-	 */
-	for (k = i; k <= b->max_order; k++) {
-		if (!list_empty(&b->order[k])) {
-			return true;
-		}
-	}
-	
-	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;
-	uint8_t 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;
-		} 
-		ASSERT(tmp == left);
-		b->op->mark_busy(b, left);
-		buddy_system_free(b, right);
-		b->op->mark_available(b, left);
-	}
-}
-
-/** Allocate block from buddy system.
- *
- * @param b		Buddy system pointer.
- * @param i		Returned block will be 2^i big.
- *
- * @return		Block of data represented by link_t.
- */
-link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i)
-{
-	link_t *res, *hlp;
-
-	ASSERT(i <= b->max_order);
-
-	/*
-	 * If the list of order i is not empty,
-	 * the request can be immediatelly satisfied.
-	 */
-	res = list_first(&b->order[i]);
-	if (res != NULL) {
-		list_remove(res);
-		b->op->mark_busy(b, res);
-		return res;
-	}
-	/*
-	 * If order i is already the maximal order,
-	 * the request cannot be satisfied.
-	 */
-	if (i == b->max_order)
-		return NULL;
-
-	/*
-	 * Try to recursively satisfy the request from higher order lists.
-	 */	
-	hlp = buddy_system_alloc(b, i + 1);
-	
-	/*
-	 * The request could not be satisfied
-	 * from higher order lists.
-	 */
-	if (!hlp)
-		return NULL;
-		
-	res = hlp;
-	
-	/*
-	 * Bisect the block and set order of both of its parts to i.
-	 */
-	hlp = b->op->bisect(b, res);
-	b->op->set_order(b, res, i);
-	b->op->set_order(b, hlp, i);
-	
-	/*
-	 * Return the other half to buddy system. Mark the first part
-	 * full, so that it won't coalesce again.
-	 */
-	b->op->mark_busy(b, res);
-	buddy_system_free(b, hlp);
-	
-	return res;
-}
-
-/** Return block to buddy system.
- *
- * @param b		Buddy system pointer.
- * @param block		Block to return.
- */
-void buddy_system_free(buddy_system_t *b, link_t *block)
-{
-	link_t *buddy, *hlp;
-	uint8_t i;
-
-	/*
-	 * Determine block's order.
-	 */
-	i = b->op->get_order(b, block);
-
-	ASSERT(i <= b->max_order);
-
-	if (i != b->max_order) {
-		/*
-		 * See if there is any buddy in the list of order i.
-		 */
-		buddy = b->op->find_buddy(b, block);
-		if (buddy) {
-
-			ASSERT(b->op->get_order(b, buddy) == i);
-			/*
-			 * Remove buddy from the list of order i.
-			 */
-			list_remove(buddy);
-		
-			/*
-			 * Invalidate order of both block and buddy.
-			 */
-			b->op->set_order(b, block, BUDDY_SYSTEM_INNER_BLOCK);
-			b->op->set_order(b, buddy, BUDDY_SYSTEM_INNER_BLOCK);
-		
-			/*
-			 * Coalesce block and buddy into one block.
-			 */
-			hlp = b->op->coalesce(b, block, buddy);
-
-			/*
-			 * Set order of the coalesced block to i + 1.
-			 */
-			b->op->set_order(b, hlp, i + 1);
-
-			/*
-			 * Recursively add the coalesced block to the list of
-			 * order i + 1.
-			 */
-			buddy_system_free(b, hlp);
-			return;
-		}
-	}
-
-	/*
-	 * Insert block into the list of order i.
-	 */
-	list_append(block, &b->order[i]);
-}
-
-/** @}
- */
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision feeac0d8cd6e0ce736779bc5f1dc701c5cf42ba6)
+++ kernel/generic/src/mm/frame.c	(revision 02e5e3425d6e6ecccf2cd07c77b7170db6f5419a)
@@ -38,7 +38,6 @@
  *
  * This file contains the physical frame allocator and memory zone management.
- * The frame allocator is built on top of the buddy allocator.
- *
- * @see buddy.c
+ * The frame allocator is built on top of the two-level bitmap structure.
+ *
  */
 
@@ -62,4 +61,6 @@
 #include <str.h>
 
+#define BITMAP_BLOCK_SIZE  1024
+
 zones_t zones;
 
@@ -92,9 +93,4 @@
 }
 
-NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
-{
-	return (frame - zone->frames);
-}
-
 /** Initialize frame structure.
  *
@@ -104,6 +100,6 @@
 NO_TRACE static void frame_initialize(frame_t *frame)
 {
-	frame->refcount = 1;
-	frame->buddy_order = 0;
+	frame->refcount = 0;
+	frame->parent = NULL;
 }
 
@@ -161,11 +157,6 @@
 	
 	/* Move other zones up */
-	size_t j;
-	for (j = zones.count; j > i; j--) {
+	for (size_t j = zones.count; j > i; j--)
 		zones.info[j] = zones.info[j - 1];
-		if (zones.info[j].buddy_system != NULL)
-			zones.info[j].buddy_system->data =
-			    (void *) &zones.info[j];
-	}
 	
 	zones.count++;
@@ -237,23 +228,31 @@
 }
 
-/** @return True if zone can allocate specified order */
-NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
-{
+/** @return True if zone can allocate specified number of frames */
+NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count,
+    pfn_t constraint)
+{
+	/*
+	 * The function bitmap_allocate_range() does not modify
+	 * the bitmap if the last argument is NULL.
+	 */
 	return ((zone->flags & ZONE_AVAILABLE) &&
-	    buddy_system_can_alloc(zone->buddy_system, order));
-}
-
-/** Find a zone that can allocate order frames.
+	    bitmap_allocate_range(&zone->bitmap, count, zone->base,
+	    constraint, NULL));
+}
+
+/** Find a zone that can allocate specified number of frames
  *
  * Assume interrupts are disabled and zones lock is
  * locked.
  *
- * @param order Size (2^order) of free space we are trying to find.
- * @param flags Required flags of the target zone.
- * @param hind  Preferred zone.
- *
- */
-NO_TRACE static size_t find_free_zone(uint8_t order, zone_flags_t flags,
-    size_t hint)
+ * @param count      Number of free frames we are trying to find.
+ * @param flags      Required flags of the target zone.
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
+ * @param hind       Preferred zone.
+ *
+ */
+NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
+    pfn_t constraint, size_t hint)
 {
 	if (hint >= zones.count)
@@ -267,7 +266,7 @@
 		if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
 			/*
-			 * Check if the zone has 2^order frames area available.
+			 * Check if the zone can satisfy the allocation request.
 			 */
-			if (zone_can_alloc(&zones.info[i], order))
+			if (zone_can_alloc(&zones.info[i], count, constraint))
 				return i;
 		}
@@ -282,169 +281,16 @@
 }
 
-/**************************/
-/* 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!!
- *
- */
-NO_TRACE static link_t *zone_buddy_find_block(buddy_system_t *buddy,
-    link_t *child, uint8_t order)
-{
-	frame_t *frame = list_get_instance(child, frame_t, buddy_link);
-	zone_t *zone = (zone_t *) buddy->data;
-	
-	size_t 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 buddy Buddy system.
- * @param block Block for which buddy should be found.
- *
- * @return Buddy for given block if found.
- *
- */
-NO_TRACE static link_t *zone_buddy_find_buddy(buddy_system_t *buddy,
-    link_t *block)
-{
-	frame_t *frame = list_get_instance(block, frame_t, buddy_link);
-	zone_t *zone = (zone_t *) buddy->data;
-	ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
-	    frame->buddy_order));
-	
-	bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
-	
-	size_t index;
-	if (is_left) {
-		index = (frame_index(zone, frame)) +
-		    (1 << frame->buddy_order);
-	} else {  /* 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 buddy Buddy system.
- * @param block Block to bisect.
- *
- * @return Right block.
- *
- */
-NO_TRACE static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
-{
-	frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
-	frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
-	
-	return &frame_r->buddy_link;
-}
-
-/** Buddy system coalesce implementation.
- *
- * @param buddy   Buddy system.
- * @param block_1 First block.
- * @param block_2 First block's buddy.
- *
- * @return Coalesced block (actually block that represents lower
- *         address).
- *
- */
-NO_TRACE static link_t *zone_buddy_coalesce(buddy_system_t *buddy,
-    link_t *block_1, link_t *block_2)
-{
-	frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
-	frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
-	
-	return ((frame1 < frame2) ? block_1 : block_2);
-}
-
-/** Buddy system set_order implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- * @param order Order to set.
- *
- */
-NO_TRACE static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
-    uint8_t order)
-{
-	list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
-}
-
-/** Buddy system get_order implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- * @return Order of block.
- *
- */
-NO_TRACE static uint8_t zone_buddy_get_order(buddy_system_t *buddy,
-    link_t *block)
-{
-	return list_get_instance(block, frame_t, buddy_link)->buddy_order;
-}
-
-/** Buddy system mark_busy implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- */
-NO_TRACE static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t *block)
-{
-	list_get_instance(block, frame_t, buddy_link)->refcount = 1;
-}
-
-/** Buddy system mark_available implementation.
- *
- * @param buddy Buddy system.
- * @param block Buddy system block.
- *
- */
-NO_TRACE static void zone_buddy_mark_available(buddy_system_t *buddy,
-    link_t *block)
-{
-	list_get_instance(block, frame_t, buddy_link)->refcount = 0;
-}
-
-static buddy_system_operations_t zone_buddy_system_operations = {
-	.find_buddy = zone_buddy_find_buddy,
-	.bisect = zone_buddy_bisect,
-	.coalesce = zone_buddy_coalesce,
-	.set_order = zone_buddy_set_order,
-	.get_order = zone_buddy_get_order,
-	.mark_busy = zone_buddy_mark_busy,
-	.mark_available = zone_buddy_mark_available,
-	.find_block = zone_buddy_find_block
-};
-
 /******************/
 /* Zone functions */
 /******************/
 
+/** Return frame from zone. */
+NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)
+{
+	ASSERT(index < zone->count);
+	
+	return &zone->frames[index];
+}
+
 /** Allocate frame in particular zone.
  *
@@ -452,28 +298,37 @@
  * Panics if allocation is impossible.
  *
- * @param zone  Zone to allocate from.
- * @param order Allocate exactly 2^order frames.
+ * @param zone       Zone to allocate from.
+ * @param count      Number of frames to allocate
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
  *
  * @return Frame index in zone.
  *
  */
-NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
+NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
+    pfn_t constraint)
 {
 	ASSERT(zone->flags & ZONE_AVAILABLE);
 	
-	/* Allocate frames from zone buddy system */
-	link_t *link = buddy_system_alloc(zone->buddy_system, order);
-	
-	ASSERT(link);
+	/* Allocate frames from zone */
+	size_t index;
+	int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
+	    constraint, &index);
+	
+	ASSERT(avail);
+	
+	/* Update frame reference count */
+	for (size_t i = 0; i < count; i++) {
+		frame_t *frame = zone_get_frame(zone, index + i);
+		
+		ASSERT(frame->refcount == 0);
+		frame->refcount = 1;
+	}
 	
 	/* Update zone information. */
-	zone->free_count -= (1 << order);
-	zone->busy_count += (1 << order);
-	
-	/* Frame will be actually a first frame of the block. */
-	frame_t *frame = list_get_instance(link, frame_t, buddy_link);
-	
-	/* Get frame address */
-	return make_frame_index(zone, frame);
+	zone->free_count -= count;
+	zone->busy_count += count;
+	
+	return index;
 }
 
@@ -482,25 +337,27 @@
  * Assume zone is locked and is available for deallocation.
  *
- * @param zone      Pointer to zone from which the frame is to be freed.
- * @param frame_idx Frame index relative to zone.
- *
- * @return          Number of freed frames.
- *
- */
-NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
+ * @param zone  Pointer to zone from which the frame is to be freed.
+ * @param index Frame index relative to zone.
+ *
+ * @return Number of freed frames.
+ *
+ */
+NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
 {
 	ASSERT(zone->flags & ZONE_AVAILABLE);
 	
-	frame_t *frame = &zone->frames[frame_idx];
+	frame_t *frame = zone_get_frame(zone, index);
 	size_t size = 0;
 	
-	ASSERT(frame->refcount);
+	ASSERT(frame->refcount > 0);
 	
 	if (!--frame->refcount) {
-		size = 1 << frame->buddy_order;
-		buddy_system_free(zone->buddy_system, &frame->buddy_link);		
+		bitmap_free_range(&zone->bitmap, index, 1);
+		
 		/* Update zone information. */
-		zone->free_count += size;
-		zone->busy_count -= size;
+		zone->free_count++;
+		zone->busy_count--;
+		
+		size = FRAME_SIZE;
 	}
 	
@@ -508,28 +365,16 @@
 }
 
-/** Return frame from zone. */
-NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
-{
-	ASSERT(frame_idx < zone->count);
-	return &zone->frames[frame_idx];
-}
-
 /** Mark frame in zone unavailable to allocation. */
-NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
+NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
 {
 	if (!(zone->flags & ZONE_AVAILABLE))
 		return;
-//	ASSERT(zone->flags & ZONE_AVAILABLE);
-	
-	frame_t *frame = zone_get_frame(zone, frame_idx);
-	if (frame->refcount)
+	
+	frame_t *frame = zone_get_frame(zone, index);
+	if (frame->refcount > 0)
 		return;
 	
-	link_t *link __attribute__ ((unused));
-	
-	link = buddy_system_alloc_block(zone->buddy_system,
-	    &frame->buddy_link);
-	
-	ASSERT(link);
+	bitmap_set_range(&zone->bitmap, index, 1);
+	
 	zone->free_count--;
 	reserve_force_alloc(1);
@@ -538,16 +383,15 @@
 /** Merge two zones.
  *
- * Expect buddy to point to space at least zone_conf_size large.
  * Assume z1 & z2 are locked and compatible and zones lock is
  * locked.
  *
- * @param z1     First zone to merge.
- * @param z2     Second zone to merge.
- * @param old_z1 Original date of the first zone.
- * @param buddy  Merged zone buddy.
+ * @param z1       First zone to merge.
+ * @param z2       Second zone to merge.
+ * @param old_z1   Original data of the first zone.
+ * @param confdata Merged zone configuration data.
  *
  */
 NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
-    buddy_system_t *buddy)
+    void *confdata)
 {
 	ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
@@ -564,69 +408,26 @@
 	zones.info[z1].free_count += zones.info[z2].free_count;
 	zones.info[z1].busy_count += zones.info[z2].busy_count;
-	zones.info[z1].buddy_system = buddy;
-	
-	uint8_t order = fnzb(zones.info[z1].count);
-	buddy_system_create(zones.info[z1].buddy_system, order,
-	    &zone_buddy_system_operations, (void *) &zones.info[z1]);
-	
-	zones.info[z1].frames =
-	    (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
-	    + buddy_conf_size(order));
-	
-	/* This marks all frames busy */
-	size_t i;
-	for (i = 0; i < zones.info[z1].count; i++)
-		frame_initialize(&zones.info[z1].frames[i]);
-	
-	/* Copy frames from both zones to preserve full frame orders,
-	 * parents etc. Set all free frames with refcount = 0 to 1, because
-	 * we add all free frames to buddy allocator later again, clearing
-	 * order to 0. Don't set busy frames with refcount = 0, as they
-	 * will not be reallocated during merge and it would make later
-	 * problems with allocation/free.
+	
+	bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
+	    BITMAP_BLOCK_SIZE, confdata +
+	    (sizeof(frame_t) * zones.info[z1].count));
+	
+	zones.info[z1].frames = (frame_t *) confdata;
+	
+	/*
+	 * Copy frames and bits from both zones to preserve parents, etc.
 	 */
-	for (i = 0; i < old_z1->count; i++)
+	
+	for (size_t i = 0; i < old_z1->count; i++) {
+		bitmap_set(&zones.info[z1].bitmap, i,
+		    bitmap_get(&old_z1->bitmap, i));
 		zones.info[z1].frames[i] = old_z1->frames[i];
-	
-	for (i = 0; i < zones.info[z2].count; i++)
-		zones.info[z1].frames[base_diff + i]
-		    = zones.info[z2].frames[i];
-	
-	i = 0;
-	while (i < zones.info[z1].count) {
-		if (zones.info[z1].frames[i].refcount) {
-			/* Skip busy frames */
-			i += 1 << zones.info[z1].frames[i].buddy_order;
-		} else {
-			/* Free frames, set refcount = 1
-			 * (all free frames have refcount == 0, we need not
-			 * to check the order)
-			 */
-			zones.info[z1].frames[i].refcount = 1;
-			zones.info[z1].frames[i].buddy_order = 0;
-			i++;
-		}
-	}
-	
-	/* Add free blocks from the original zone z1 */
-	while (zone_can_alloc(old_z1, 0)) {
-		/* Allocate from the original zone */
-		pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
-		
-		/* Free the frame from the merged zone */
-		frame_t *frame = &zones.info[z1].frames[frame_idx];
-		frame->refcount = 0;
-		buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
-	}
-	
-	/* Add free blocks from the original zone z2 */
-	while (zone_can_alloc(&zones.info[z2], 0)) {
-		/* Allocate from the original zone */
-		pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
-		
-		/* Free the frame from the merged zone */
-		frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
-		frame->refcount = 0;
-		buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
+	}
+	
+	for (size_t i = 0; i < zones.info[z2].count; i++) {
+		bitmap_set(&zones.info[z1].bitmap, base_diff + i,
+		    bitmap_get(&zones.info[z2].bitmap, i));
+		zones.info[z1].frames[base_diff + i] =
+		    zones.info[z2].frames[i];
 	}
 }
@@ -651,55 +452,11 @@
 	size_t cframes = SIZE2FRAMES(zone_conf_size(count));
 	
-	if ((pfn < zones.info[znum].base)
-	    || (pfn >= zones.info[znum].base + zones.info[znum].count))
+	if ((pfn < zones.info[znum].base) ||
+	    (pfn >= zones.info[znum].base + zones.info[znum].count))
 		return;
 	
-	frame_t *frame __attribute__ ((unused));
-
-	frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
-	ASSERT(!frame->buddy_order);
-	
-	size_t i;
-	for (i = 0; i < cframes; i++) {
-		zones.info[znum].busy_count++;
+	for (size_t i = 0; i < cframes; i++)
 		(void) zone_frame_free(&zones.info[znum],
 		    pfn - zones.info[znum].base + i);
-	}
-}
-
-/** Reduce allocated block to count of order 0 frames.
- *
- * The allocated block needs 2^order frames. Reduce all frames
- * in the block to order 0 and free the unneeded frames. This means that
- * when freeing the previously allocated block starting with frame_idx,
- * you have to free every frame.
- *
- * @param znum      Zone.
- * @param frame_idx Index the first frame of the block.
- * @param count     Allocated frames in block.
- *
- */
-NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,
-    size_t count)
-{
-	ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
-	ASSERT(frame_idx + count < zones.info[znum].count);
-	
-	uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
-	ASSERT((size_t) (1 << order) >= count);
-	
-	/* Reduce all blocks to order 0 */
-	size_t i;
-	for (i = 0; i < (size_t) (1 << order); i++) {
-		frame_t *frame = &zones.info[znum].frames[i + frame_idx];
-		frame->buddy_order = 0;
-		if (!frame->refcount)
-			frame->refcount = 1;
-		ASSERT(frame->refcount == 1);
-	}
-	
-	/* Free unneeded frames */
-	for (i = count; i < (size_t) (1 << order); i++)
-		(void) zone_frame_free(&zones.info[znum], i + frame_idx);
 }
 
@@ -721,5 +478,6 @@
 	bool ret = true;
 	
-	/* We can join only 2 zones with none existing inbetween,
+	/*
+	 * We can join only 2 zones with none existing inbetween,
 	 * the zones have to be available and with the same
 	 * set of flags
@@ -735,16 +493,12 @@
 	    + zones.info[z2].count));
 	
-	uint8_t order;
-	if (cframes == 1)
-		order = 0;
-	else
-		order = fnzb(cframes - 1) + 1;
-	
 	/* Allocate merged zone data inside one of the zones */
 	pfn_t pfn;
-	if (zone_can_alloc(&zones.info[z1], order)) {
-		pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
-	} else if (zone_can_alloc(&zones.info[z2], order)) {
-		pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
+	if (zone_can_alloc(&zones.info[z1], cframes, 0)) {
+		pfn = zones.info[z1].base +
+		    zone_frame_alloc(&zones.info[z1], cframes, 0);
+	} else if (zone_can_alloc(&zones.info[z2], cframes, 0)) {
+		pfn = zones.info[z2].base +
+		    zone_frame_alloc(&zones.info[z2], cframes, 0);
 	} else {
 		ret = false;
@@ -754,12 +508,7 @@
 	/* Preserve original data from z1 */
 	zone_t old_z1 = zones.info[z1];
-	old_z1.buddy_system->data = (void *) &old_z1;
 	
 	/* Do zone merging */
-	buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
-	zone_merge_internal(z1, z2, &old_z1, buddy);
-	
-	/* Free unneeded config frames */
-	zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
+	zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn)));
 	
 	/* Subtract zone information from busy frames */
@@ -774,11 +523,6 @@
 	
 	/* Move zones down */
-	size_t i;
-	for (i = z2 + 1; i < zones.count; i++) {
+	for (size_t i = z2 + 1; i < zones.count; i++)
 		zones.info[i - 1] = zones.info[i];
-		if (zones.info[i - 1].buddy_system != NULL)
-			zones.info[i - 1].buddy_system->data =
-			    (void *) &zones.info[i - 1];
-	}
 	
 	zones.count--;
@@ -799,7 +543,8 @@
 void zone_merge_all(void)
 {
-	size_t i = 0;
+	size_t i = 1;
+	
 	while (i < zones.count) {
-		if (!zone_merge(i, i + 1))
+		if (!zone_merge(i - 1, i))
 			i++;
 	}
@@ -808,15 +553,15 @@
 /** Create new frame zone.
  *
- * @param zone  Zone to construct.
- * @param buddy Address of buddy system configuration information.
- * @param start Physical address of the first frame within the zone.
- * @param count Count of frames in zone.
- * @param flags Zone flags.
+ * @param zone     Zone to construct.
+ * @param start    Physical address of the first frame within the zone.
+ * @param count    Count of frames in zone.
+ * @param flags    Zone flags.
+ * @param confdata Configuration data of the zone.
  *
  * @return Initialized zone.
  *
  */
-NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,
-    pfn_t start, size_t count, zone_flags_t flags)
+NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
+    zone_flags_t flags, void *confdata)
 {
 	zone->base = start;
@@ -825,31 +570,26 @@
 	zone->free_count = count;
 	zone->busy_count = 0;
-	zone->buddy_system = buddy;
 	
 	if (flags & ZONE_AVAILABLE) {
 		/*
-		 * Compute order for buddy system and initialize
+		 * Initialize frame bitmap (located after the array of
+		 * frame_t structures in the configuration space).
 		 */
-		uint8_t order = fnzb(count);
-		buddy_system_create(zone->buddy_system, order,
-		    &zone_buddy_system_operations, (void *) zone);
-		
-		/* Allocate frames _after_ the confframe */
-		
-		/* Check sizes */
-		zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
-		    buddy_conf_size(order));
-		
-		size_t i;
-		for (i = 0; i < count; i++)
+		
+		bitmap_initialize(&zone->bitmap, count, BITMAP_BLOCK_SIZE,
+		    confdata + (sizeof(frame_t) * count));
+		
+		/*
+		 * Initialize the array of frame_t structures.
+		 */
+		
+		zone->frames = (frame_t *) confdata;
+		
+		for (size_t i = 0; i < count; i++)
 			frame_initialize(&zone->frames[i]);
-		
-		/* Stuffing frames */
-		for (i = 0; i < count; i++) {
-			zone->frames[i].refcount = 0;
-			buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
-		}
-	} else
+	} else {
+		bitmap_initialize(&zone->bitmap, 0, 0, NULL);
 		zone->frames = NULL;
+	}
 }
 
@@ -863,5 +603,6 @@
 size_t zone_conf_size(size_t count)
 {
-	return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
+	return (count * sizeof(frame_t) +
+	    bitmap_size(count, BITMAP_BLOCK_SIZE));
 }
 
@@ -869,9 +610,8 @@
 pfn_t zone_external_conf_alloc(size_t count)
 {
-	size_t size = zone_conf_size(count);
-	size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
-
-	return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH,
-	    FRAME_LOWMEM | FRAME_ATOMIC, 0));
+	size_t frames = SIZE2FRAMES(zone_conf_size(count));
+	
+	return ADDR2PFN((uintptr_t)
+	    frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0));
 }
 
@@ -881,5 +621,5 @@
  * @param count     Size of zone in frames.
  * @param confframe Where configuration frames are supposed to be.
- *                  Automatically checks, that we will not disturb the
+ *                  Automatically checks that we will not disturb the
  *                  kernel and possibly init. If confframe is given
  *                  _outside_ this zone, it is expected, that the area is
@@ -898,17 +638,20 @@
 	
 	if (flags & ZONE_AVAILABLE) {  /* Create available zone */
-		/* Theoretically we could have NULL here, practically make sure
+		/*
+		 * Theoretically we could have NULL here, practically make sure
 		 * nobody tries to do that. If some platform requires, remove
 		 * the assert
 		 */
 		ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
-
+		
 		/* Update the known end of physical memory. */
 		config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
 		
-		/* If confframe is supposed to be inside our zone, then make sure
+		/*
+		 * If confframe is supposed to be inside our zone, then make sure
 		 * it does not span kernel & init
 		 */
 		size_t confcount = SIZE2FRAMES(zone_conf_size(count));
+		
 		if ((confframe >= start) && (confframe < start + count)) {
 			for (; confframe < start + count; confframe++) {
@@ -923,6 +666,5 @@
 				
 				bool overlap = false;
-				size_t i;
-				for (i = 0; i < init.cnt; i++)
+				for (size_t i = 0; i < init.cnt; i++) {
 					if (overlaps(addr, PFN2ADDR(confcount),
 					    init.tasks[i].paddr,
@@ -931,4 +673,6 @@
 						break;
 					}
+				}
+				
 				if (overlap)
 					continue;
@@ -937,9 +681,6 @@
 			}
 			
-			if (confframe >= start + count) {
-				flags &= ~ZONE_AVAILABLE;
-				goto nonavail;
-//				panic("Cannot find configuration data for zone.");
-			}
+			if (confframe >= start + count)
+				panic("Cannot find configuration data for zone.");
 		}
 		
@@ -950,11 +691,10 @@
 		}
 		
-		buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
-		zone_construct(&zones.info[znum], buddy, start, count, flags);
+		void *confdata = (void *) PA2KA(PFN2ADDR(confframe));
+		zone_construct(&zones.info[znum], start, count, flags, confdata);
 		
 		/* If confdata in zone, mark as unavailable */
 		if ((confframe >= start) && (confframe < start + count)) {
-			size_t i;
-			for (i = confframe; i < confframe + confcount; i++)
+			for (size_t i = confframe; i < confframe + confcount; i++)
 				zone_mark_unavailable(&zones.info[znum],
 				    i - zones.info[znum].base);
@@ -965,6 +705,5 @@
 		return znum;
 	}
-nonavail:
-	(void)0; // label trick
+	
 	/* Non-available zone */
 	size_t znum = zones_insert_zone(start, count, flags);
@@ -973,5 +712,6 @@
 		return (size_t) -1;
 	}
-	zone_construct(&zones.info[znum], NULL, start, count, flags);
+	
+	zone_construct(&zones.info[znum], start, count, flags, NULL);
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1015,25 +755,29 @@
 }
 
-/** Allocate power-of-two frames of physical memory.
- *
- * @param order Allocate exactly 2^order frames.
- * @param flags Flags for host zone selection and address processing.
- * @param pzone Preferred zone.
+/** Allocate frames of physical memory.
+ *
+ * @param count      Number of continuous frames to allocate.
+ * @param flags      Flags for host zone selection and address processing.
+ * @param constraint Indication of physical address bits that cannot be
+ *                   set in the address of the first allocated frame.
+ * @param pzone      Preferred zone.
  *
  * @return Physical address of the allocated frame.
  *
  */
-uintptr_t frame_alloc_generic(uint8_t order, frame_flags_t flags,
+uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
     uintptr_t constraint, size_t *pzone)
 {
-	size_t size = ((size_t) 1) << order;
+	ASSERT(count > 0);
+	
 	size_t hint = pzone ? (*pzone) : 0;
+	pfn_t frame_constraint = ADDR2PFN(constraint);
 	
 	/*
 	 * If not told otherwise, we must first reserve the memory.
 	 */
-	if (!(flags & FRAME_NO_RESERVE)) 
-		reserve_force_alloc(size);
-
+	if (!(flags & FRAME_NO_RESERVE))
+		reserve_force_alloc(count);
+	
 loop:
 	irq_spinlock_lock(&zones.lock, true);
@@ -1042,9 +786,11 @@
 	 * First, find suitable frame zone.
 	 */
-	size_t znum = find_free_zone(order,
-	    FRAME_TO_ZONE_FLAGS(flags), hint);
-	
-	/* If no memory, reclaim some slab memory,
-	   if it does not help, reclaim all */
+	size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+	    frame_constraint, hint);
+	
+	/*
+	 * If no memory, reclaim some slab memory,
+	 * if it does not help, reclaim all.
+	 */
 	if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
 		irq_spinlock_unlock(&zones.lock, true);
@@ -1053,6 +799,6 @@
 		
 		if (freed > 0)
-			znum = find_free_zone(order,
-			    FRAME_TO_ZONE_FLAGS(flags), hint);
+			znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+			    frame_constraint, hint);
 		
 		if (znum == (size_t) -1) {
@@ -1062,6 +808,6 @@
 			
 			if (freed > 0)
-				znum = find_free_zone(order,
-				    FRAME_TO_ZONE_FLAGS(flags), hint);
+				znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
+				    frame_constraint, hint);
 		}
 	}
@@ -1070,6 +816,8 @@
 		if (flags & FRAME_ATOMIC) {
 			irq_spinlock_unlock(&zones.lock, true);
+			
 			if (!(flags & FRAME_NO_RESERVE))
-				reserve_free(size);
+				reserve_free(count);
+			
 			return 0;
 		}
@@ -1090,10 +838,10 @@
 #ifdef CONFIG_DEBUG
 		printf("Thread %" PRIu64 " waiting for %zu frames, "
-		    "%zu available.\n", THREAD->tid, size, avail);
+		    "%zu available.\n", THREAD->tid, count, avail);
 #endif
 		
 		/*
-		 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
-		 * to prevent deadlock with TLB shootdown.
+		 * Since the mem_avail_mtx is an active mutex, we need to
+		 * disable interrupts to prevent deadlock with TLB shootdown.
 		 */
 		ipl_t ipl = interrupts_disable();
@@ -1101,7 +849,8 @@
 		
 		if (mem_avail_req > 0)
-			mem_avail_req = min(mem_avail_req, size);
+			mem_avail_req = min(mem_avail_req, count);
 		else
-			mem_avail_req = size;
+			mem_avail_req = count;
+		
 		size_t gen = mem_avail_gen;
 		
@@ -1119,6 +868,6 @@
 	}
 	
-	pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
-	    + zones.info[znum].base;
+	pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,
+	    frame_constraint) + zones.info[znum].base;
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1130,13 +879,13 @@
 }
 
-uintptr_t frame_alloc(uint8_t order, frame_flags_t flags, uintptr_t constraint)
-{
-	return frame_alloc_generic(order, flags, constraint, NULL);
-}
-
-uintptr_t frame_alloc_noreserve(uint8_t order, frame_flags_t flags,
+uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint)
+{
+	return frame_alloc_generic(count, flags, constraint, NULL);
+}
+
+uintptr_t frame_alloc_noreserve(size_t count, frame_flags_t flags,
     uintptr_t constraint)
 {
-	return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, constraint,
+	return frame_alloc_generic(count, flags | FRAME_NO_RESERVE, constraint,
 	    NULL);
 }
@@ -1154,6 +903,4 @@
 void frame_free_generic(uintptr_t frame, frame_flags_t flags)
 {
-	size_t size;
-	
 	irq_spinlock_lock(&zones.lock, true);
 	
@@ -1163,8 +910,9 @@
 	pfn_t pfn = ADDR2PFN(frame);
 	size_t znum = find_zone(pfn, 1, 0);
-
+	
 	ASSERT(znum != (size_t) -1);
 	
-	size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
+	size_t size =
+	    zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1173,5 +921,5 @@
 	 * Signal that some memory has been freed.
 	 */
-
+	
 	
 	/*
@@ -1179,6 +927,8 @@
 	 * to prevent deadlock with TLB shootdown.
 	 */
+	
 	ipl_t ipl = interrupts_disable();
 	mutex_lock(&mem_avail_mtx);
+	
 	if (mem_avail_req > 0)
 		mem_avail_req -= min(mem_avail_req, size);
@@ -1188,4 +938,5 @@
 		condvar_broadcast(&mem_avail_cv);
 	}
+	
 	mutex_unlock(&mem_avail_mtx);
 	interrupts_restore(ipl);
@@ -1236,7 +987,7 @@
 	irq_spinlock_lock(&zones.lock, true);
 	
-	size_t i;
-	for (i = 0; i < count; i++) {
+	for (size_t i = 0; i < count; i++) {
 		size_t znum = find_zone(start + i, 1, 0);
+		
 		if (znum == (size_t) -1)  /* PFN not found */
 			continue;
@@ -1263,4 +1014,5 @@
 	/* Tell the architecture to create some memory */
 	frame_low_arch_init();
+	
 	if (config.cpu_active == 1) {
 		frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
@@ -1269,10 +1021,7 @@
 		    SIZE2FRAMES(config.stack_size));
 		
-		size_t i;
-		for (i = 0; i < init.cnt; i++) {
-			pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
-			frame_mark_unavailable(pfn,
+		for (size_t i = 0; i < init.cnt; i++)
+			frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr),
 			    SIZE2FRAMES(init.tasks[i].size));
-		}
 		
 		if (ballocs.size)
@@ -1280,9 +1029,11 @@
 			    SIZE2FRAMES(ballocs.size));
 		
-		/* Black list first frame, as allocating NULL would
+		/*
+		 * Blacklist first frame, as allocating NULL would
 		 * fail in some places
 		 */
 		frame_mark_unavailable(0, 1);
 	}
+	
 	frame_high_arch_init();
 }
@@ -1290,21 +1041,24 @@
 /** Adjust bounds of physical memory region according to low/high memory split.
  *
- * @param low[in]	If true, the adjustment is performed to make the region
- *			fit in the low memory. Otherwise the adjustment is
- *			performed to make the region fit in the high memory.
- * @param basep[inout]	Pointer to a variable which contains the region's base
- *			address and which may receive the adjusted base address.
- * @param sizep[inout]	Pointer to a variable which contains the region's size
- *			and which may receive the adjusted size.
- * @retun		True if the region still exists even after the
- *			adjustment, false otherwise.
+ * @param low[in]      If true, the adjustment is performed to make the region
+ *                     fit in the low memory. Otherwise the adjustment is
+ *                     performed to make the region fit in the high memory.
+ * @param basep[inout] Pointer to a variable which contains the region's base
+ *                     address and which may receive the adjusted base address.
+ * @param sizep[inout] Pointer to a variable which contains the region's size
+ *                     and which may receive the adjusted size.
+ *
+ * @return True if the region still exists even after the adjustment.
+ * @return False otherwise.
+ *
  */
 bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
 {
 	uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
-
+	
 	if (low) {
 		if (*basep > limit)
 			return false;
+		
 		if (*basep + *sizep > limit)
 			*sizep = limit - *basep;
@@ -1312,4 +1066,5 @@
 		if (*basep + *sizep <= limit)
 			return false;
+		
 		if (*basep <= limit) {
 			*sizep -= limit - *basep;
@@ -1317,4 +1072,5 @@
 		}
 	}
+	
 	return true;
 }
@@ -1328,6 +1084,6 @@
 	
 	uint64_t total = 0;
-	size_t i;
-	for (i = 0; i < zones.count; i++)
+	
+	for (size_t i = 0; i < zones.count; i++)
 		total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
 	
@@ -1352,6 +1108,5 @@
 	*free = 0;
 	
-	size_t i;
-	for (i = 0; i < zones.count; i++) {
+	for (size_t i = 0; i < zones.count; i++) {
 		*total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
 		
@@ -1390,6 +1145,5 @@
 	 */
 	
-	size_t i;
-	for (i = 0;; i++) {
+	for (size_t i = 0;; i++) {
 		irq_spinlock_lock(&zones.lock, true);
 		
@@ -1444,6 +1198,5 @@
 	size_t znum = (size_t) -1;
 	
-	size_t i;
-	for (i = 0; i < zones.count; i++) {
+	for (size_t i = 0; i < zones.count; i++) {
 		if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
 			znum = i;
@@ -1458,9 +1211,9 @@
 	}
 	
-	uintptr_t base = PFN2ADDR(zones.info[i].base);
-	zone_flags_t flags = zones.info[i].flags;
-	size_t count = zones.info[i].count;
-	size_t free_count = zones.info[i].free_count;
-	size_t busy_count = zones.info[i].busy_count;
+	uintptr_t base = PFN2ADDR(zones.info[znum].base);
+	zone_flags_t flags = zones.info[znum].flags;
+	size_t count = zones.info[znum].count;
+	size_t free_count = zones.info[znum].free_count;
+	size_t busy_count = zones.info[znum].busy_count;
 	
 	irq_spinlock_unlock(&zones.lock, true);
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision feeac0d8cd6e0ce736779bc5f1dc701c5cf42ba6)
+++ kernel/generic/src/mm/km.c	(revision 02e5e3425d6e6ecccf2cd07c77b7170db6f5419a)
@@ -247,6 +247,6 @@
 	 */
 	uintptr_t page;
-	uintptr_t frame = frame_alloc(ONE_FRAME,
-	    FRAME_HIGHMEM | FRAME_ATOMIC | flags, 0); 
+	uintptr_t frame =
+	    frame_alloc(1, FRAME_HIGHMEM | FRAME_ATOMIC | flags, 0);
 	if (frame) {
 		page = km_map(frame, PAGE_SIZE,
@@ -256,5 +256,5 @@
 		ASSERT(page);
 	} else {
-		frame = frame_alloc(ONE_FRAME, FRAME_LOWMEM | flags, 0);
+		frame = frame_alloc(1, FRAME_LOWMEM | flags, 0);
 		if (!frame)
 			return (uintptr_t) NULL;
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision feeac0d8cd6e0ce736779bc5f1dc701c5cf42ba6)
+++ kernel/generic/src/mm/slab.c	(revision 02e5e3425d6e6ecccf2cd07c77b7170db6f5419a)
@@ -183,5 +183,5 @@
 	
 	void *data = (void *)
-	    PA2KA(frame_alloc_generic(cache->order, flags, 0, &zone));
+	    PA2KA(frame_alloc_generic(cache->frames, flags, 0, &zone));
 	if (!data)
 		return NULL;
@@ -197,5 +197,5 @@
 		}
 	} else {
-		fsize = (PAGE_SIZE << cache->order);
+		fsize = FRAMES2SIZE(cache->frames);
 		slab = data + fsize - sizeof(*slab);
 	}
@@ -203,5 +203,5 @@
 	/* Fill in slab structures */
 	size_t i;
-	for (i = 0; i < ((size_t) 1 << cache->order); i++)
+	for (i = 0; i < cache->frames; i++)
 		frame_set_parent(ADDR2PFN(KA2PA(data)) + i, slab, zone);
 	
@@ -231,5 +231,5 @@
 	atomic_dec(&cache->allocated_slabs);
 	
-	return (1 << cache->order);
+	return cache->frames;
 }
 
@@ -558,8 +558,8 @@
 {
 	if (cache->flags & SLAB_CACHE_SLINSIDE)
-		return ((PAGE_SIZE << cache->order)
-		    - sizeof(slab_t)) / cache->size;
+		return (FRAMES2SIZE(cache->frames) - sizeof(slab_t)) /
+		    cache->size;
 	else
-		return (PAGE_SIZE << cache->order) / cache->size;
+		return FRAMES2SIZE(cache->frames) / cache->size;
 }
 
@@ -570,5 +570,5 @@
 {
 	size_t objects = comp_objects(cache);
-	size_t ssize = PAGE_SIZE << cache->order;
+	size_t ssize = FRAMES2SIZE(cache->frames);
 	
 	if (cache->flags & SLAB_CACHE_SLINSIDE)
@@ -634,15 +634,9 @@
 		cache->flags |= SLAB_CACHE_SLINSIDE;
 	
-	/* Minimum slab order */
-	size_t pages = SIZE2FRAMES(cache->size);
-	
-	/* We need the 2^order >= pages */
-	if (pages == 1)
-		cache->order = 0;
-	else
-		cache->order = fnzb(pages - 1) + 1;
+	/* Minimum slab frames */
+	cache->frames = SIZE2FRAMES(cache->size);
 	
 	while (badness(cache) > SLAB_MAX_BADNESS(cache))
-		cache->order += 1;
+		cache->frames <<= 1;
 	
 	cache->objects = comp_objects(cache);
@@ -870,5 +864,5 @@
 		
 		const char *name = cache->name;
-		uint8_t order = cache->order;
+		size_t frames = cache->frames;
 		size_t size = cache->size;
 		size_t objects = cache->objects;
@@ -880,6 +874,6 @@
 		irq_spinlock_unlock(&slab_cache_lock, true);
 		
-		printf("%-18s %8zu %8u %8zu %8ld %8ld %8ld %-5s\n",
-		    name, size, (1 << order), objects, allocated_slabs,
+		printf("%-18s %8zu %8zu %8zu %8ld %8ld %8ld %-5s\n",
+		    name, size, frames, objects, allocated_slabs,
 		    cached_objs, allocated_objs,
 		    flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
