Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision e037cf3733f322897cbfc63ce44277485f52af9b)
+++ kernel/generic/src/mm/frame.c	(revision ebb35382370c13619311861065e5a3add01e3abe)
@@ -370,4 +370,5 @@
 {
 	assert(zone->flags & ZONE_AVAILABLE);
+	assert(zone->free_count >= count);
 
 	/* Allocate frames from zone */
@@ -410,8 +411,9 @@
 
 	frame_t *frame = zone_get_frame(zone, index);
-
 	assert(frame->refcount > 0);
 
 	if (!--frame->refcount) {
+		assert(zone->busy_count > 0);
+
 		bitmap_set(&zone->bitmap, index, 0);
 
@@ -432,7 +434,11 @@
 
 	frame_t *frame = zone_get_frame(zone, index);
+	assert(frame->refcount <= 1);
+
 	if (frame->refcount > 0)
 		return;
 
+	assert(zone->free_count > 0);
+
 	frame->refcount = 1;
 	bitmap_set_range(&zone->bitmap, index, 1);
@@ -440,4 +446,18 @@
 	zone->free_count--;
 	reserve_force_alloc(1);
+}
+
+/** Mark frame in zone available to allocation. */
+_NO_TRACE static void zone_mark_available(zone_t *zone, size_t index)
+{
+	assert(zone->flags & ZONE_AVAILABLE);
+
+	frame_t *frame = zone_get_frame(zone, index);
+	assert(frame->refcount == 1);
+
+	frame->refcount = 0;
+	bitmap_set_range(&zone->bitmap, index, 0);
+
+	zone->free_count++;
 }
 
@@ -465,4 +485,5 @@
 	/* Difference between zone bases */
 	pfn_t base_diff = zones.info[z2].base - zones.info[z1].base;
+	pfn_t gap = base_diff - zones.info[z1].count;
 
 	zones.info[z1].count = base_diff + zones.info[z2].count;
@@ -492,4 +513,12 @@
 		    zones.info[z2].frames[i];
 	}
+
+	/*
+	 * Mark the gap between the original zones as unavailable.
+	 */
+
+	for (size_t i = 0; i < gap; i++) {
+		zone_mark_unavailable(&zones.info[z1], old_z1->count + i);
+	}
 }
 
@@ -518,5 +547,5 @@
 
 	for (size_t i = 0; i < cframes; i++)
-		(void) zone_frame_free(&zones.info[znum],
+		zone_mark_available(&zones.info[znum],
 		    pfn - zones.info[znum].base + i);
 }
