Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 7e752b2a0d66c871748e5fa9e8bbe3a27c70a202)
+++ kernel/generic/src/mm/frame.c	(revision 933cadfdb63d0a16870db764880b5c144894e112)
@@ -45,4 +45,5 @@
 #include <typedefs.h>
 #include <mm/frame.h>
+#include <mm/reserve.h>
 #include <mm/as.h>
 #include <panic.h>
@@ -59,4 +60,5 @@
 #include <macros.h>
 #include <config.h>
+#include <str.h>
 
 zones_t zones;
@@ -472,23 +474,25 @@
  * @param frame_idx Frame index relative to zone.
  *
- */
-NO_TRACE static void zone_frame_free(zone_t *zone, size_t frame_idx)
+ * @return          Number of freed frames.
+ *
+ */
+NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
 {
 	ASSERT(zone_flags_available(zone->flags));
 	
 	frame_t *frame = &zone->frames[frame_idx];
-	
-	/* Remember frame order */
-	uint8_t order = frame->buddy_order;
+	size_t size = 0;
 	
 	ASSERT(frame->refcount);
 	
 	if (!--frame->refcount) {
-		buddy_system_free(zone->buddy_system, &frame->buddy_link);
-		
+		size = 1 << frame->buddy_order;
+		buddy_system_free(zone->buddy_system, &frame->buddy_link);		
 		/* Update zone information. */
-		zone->free_count += (1 << order);
-		zone->busy_count -= (1 << order);
-	}
+		zone->free_count += size;
+		zone->busy_count -= size;
+	}
+	
+	return size;
 }
 
@@ -516,4 +520,5 @@
 	ASSERT(link);
 	zone->free_count--;
+	reserve_force_alloc(1);
 }
 
@@ -645,5 +650,5 @@
 	for (i = 0; i < cframes; i++) {
 		zones.info[znum].busy_count++;
-		zone_frame_free(&zones.info[znum],
+		(void) zone_frame_free(&zones.info[znum],
 		    pfn - zones.info[znum].base + i);
 	}
@@ -683,5 +688,5 @@
 	/* Free unneeded frames */
 	for (i = count; i < (size_t) (1 << order); i++)
-		zone_frame_free(&zones.info[znum], i + frame_idx);
+		(void) zone_frame_free(&zones.info[znum], i + frame_idx);
 }
 
@@ -695,6 +700,4 @@
  * not to be 2^order size. Once the allocator is running it is no longer
  * possible, merged configuration data occupies more space :-/
- *
- * The function uses
  *
  */
@@ -837,4 +840,7 @@
 			buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
 		}
+
+		/* "Unreserve" new frames. */
+		reserve_free(count);
 	} else
 		zone->frames = NULL;
@@ -999,4 +1005,10 @@
 	size_t hint = pzone ? (*pzone) : 0;
 	
+	/*
+	 * If not told otherwise, we must first reserve the memory.
+	 */
+	if (!(flags & FRAME_NO_RESERVE)) 
+		reserve_force_alloc(size);
+
 loop:
 	irq_spinlock_lock(&zones.lock, true);
@@ -1033,4 +1045,6 @@
 		if (flags & FRAME_ATOMIC) {
 			irq_spinlock_unlock(&zones.lock, true);
+			if (!(flags & FRAME_NO_RESERVE))
+				reserve_free(size);
 			return NULL;
 		}
@@ -1088,4 +1102,14 @@
 }
 
+void *frame_alloc(uint8_t order, frame_flags_t flags)
+{
+	return frame_alloc_generic(order, flags, NULL);
+}
+
+void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
+{
+	return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
+}
+
 /** Free a frame.
  *
@@ -1095,8 +1119,11 @@
  *
  * @param frame Physical Address of of the frame to be freed.
- *
- */
-void frame_free(uintptr_t frame)
-{
+ * @param flags Flags to control memory reservation.
+ *
+ */
+void frame_free_generic(uintptr_t frame, frame_flags_t flags)
+{
+	size_t size;
+	
 	irq_spinlock_lock(&zones.lock, true);
 	
@@ -1106,8 +1133,9 @@
 	pfn_t pfn = ADDR2PFN(frame);
 	size_t znum = find_zone(pfn, 1, 0);
+
 	
 	ASSERT(znum != (size_t) -1);
 	
-	zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
+	size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1118,5 +1146,5 @@
 	mutex_lock(&mem_avail_mtx);
 	if (mem_avail_req > 0)
-		mem_avail_req--;
+		mem_avail_req -= min(mem_avail_req, size);
 	
 	if (mem_avail_req == 0) {
@@ -1125,4 +1153,17 @@
 	}
 	mutex_unlock(&mem_avail_mtx);
+	
+	if (!(flags & FRAME_NO_RESERVE))
+		reserve_free(size);
+}
+
+void frame_free(uintptr_t frame)
+{
+	frame_free_generic(frame, 0);
+}
+
+void frame_free_noreserve(uintptr_t frame)
+{
+	frame_free_generic(frame, FRAME_NO_RESERVE);
 }
 
@@ -1355,8 +1396,12 @@
 	bool available = zone_flags_available(flags);
 	
+	uint64_t size;
+	const char *size_suffix;
+	bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
+	
 	printf("Zone number:       %zu\n", znum);
 	printf("Zone base address: %p\n", (void *) base);
-	printf("Zone size:         %zu frames (%zu KiB)\n", count,
-	    SIZE2KB(FRAMES2SIZE(count)));
+	printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
+	    size, size_suffix);
 	printf("Zone flags:        %c%c%c\n",
 	    available ? 'A' : ' ',
@@ -1365,8 +1410,12 @@
 	
 	if (available) {
-		printf("Allocated space:   %zu frames (%zu KiB)\n",
-		    busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
-		printf("Available space:   %zu frames (%zu KiB)\n",
-		    free_count, SIZE2KB(FRAMES2SIZE(free_count)));
+		bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
+		    false);
+		printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
+		    busy_count, size, size_suffix);
+		bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
+		    false);
+		printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
+		    free_count, size, size_suffix);
 	}
 }
