Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision c5396c1804ab53d2d15266e72be0b0617bebb8b3)
+++ kernel/generic/src/mm/frame.c	(revision f72906c1ceb4b546d431ab8e9c41434425c1096f)
@@ -234,7 +234,91 @@
 	 * the bitmap if the last argument is NULL.
 	 */
+	
 	return ((zone->flags & ZONE_AVAILABLE) &&
 	    bitmap_allocate_range(&zone->bitmap, count, zone->base,
-	    constraint, NULL));
+	    FRAME_LOWPRIO, constraint, NULL));
+}
+
+/** Find a zone that can allocate specified number of frames
+ *
+ * This function searches among all zones. Assume interrupts are
+ * disabled and zones lock is locked.
+ *
+ * @param count      Number of free frames we are trying to find.
+ * @param flags      Required flags of the zone.
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
+ * @param hint       Preferred zone.
+ *
+ * @return Zone that can allocate specified number of frames.
+ * @return -1 if no zone can satisfy the request.
+ *
+ */
+NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
+    pfn_t constraint, size_t hint)
+{
+	for (size_t pos = 0; pos < zones.count; pos++) {
+		size_t i = (pos + hint) % zones.count;
+		
+		/* Check whether the zone meets the search criteria. */
+		if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
+			continue;
+		
+		/* Check if the zone can satisfy the allocation request. */
+		if (zone_can_alloc(&zones.info[i], count, constraint))
+			return i;
+	}
+	
+	return (size_t) -1;
+}
+
+/** Check if frame range  priority memory
+ *
+ * @param pfn   Starting frame.
+ * @param count Number of frames.
+ *
+ * @return True if the range contains only priority memory.
+ *
+ */
+NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
+{
+	return (base + count <= FRAME_LOWPRIO);
+}
+
+/** Find a zone that can allocate specified number of frames
+ *
+ * This function ignores zones that contain only high-priority
+ * memory. Assume interrupts are disabled and zones lock is locked.
+ *
+ * @param count      Number of free frames we are trying to find.
+ * @param flags      Required flags of the zone.
+ * @param constraint Indication of bits that cannot be set in the
+ *                   physical frame number of the first allocated frame.
+ * @param hint       Preferred zone.
+ *
+ * @return Zone that can allocate specified number of frames.
+ * @return -1 if no low-priority zone can satisfy the request.
+ *
+ */
+NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
+    pfn_t constraint, size_t hint)
+{	
+	for (size_t pos = 0; pos < zones.count; pos++) {
+		size_t i = (pos + hint) % zones.count;
+		
+		/* Skip zones containing only high-priority memory. */
+		if (is_high_priority(zones.info[i].base, zones.info[i].count))
+			continue;
+		
+		/* Check whether the zone meets the search criteria. */
+		if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
+			continue;
+		
+		/* Check if the zone can satisfy the allocation request. */
+		if (zone_can_alloc(&zones.info[i], count, constraint))
+			return i;
+	}
+	
+	return (size_t) -1;
 }
 
@@ -248,5 +332,8 @@
  * @param constraint Indication of bits that cannot be set in the
  *                   physical frame number of the first allocated frame.
- * @param hind       Preferred zone.
+ * @param hint       Preferred zone.
+ *
+ * @return Zone that can allocate specified number of frames.
+ * @return -1 if no zone can satisfy the request.
  *
  */
@@ -257,24 +344,15 @@
 		hint = 0;
 	
-	size_t i = hint;
-	do {
-		/*
-		 * Check whether the zone meets the search criteria.
-		 */
-		if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
-			/*
-			 * Check if the zone can satisfy the allocation request.
-			 */
-			if (zone_can_alloc(&zones.info[i], count, constraint))
-				return i;
-		}
-		
-		i++;
-		if (i >= zones.count)
-			i = 0;
-		
-	} while (i != hint);
-	
-	return (size_t) -1;
+	/*
+	 * Prefer zones with low-priority memory over
+	 * zones with high-priority memory.
+	 */
+	
+	size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
+	if (znum != (size_t) -1)
+		return znum;
+	
+	/* Take all zones into account */
+	return find_free_zone_all(count, flags, constraint, hint);
 }
 
@@ -312,5 +390,5 @@
 	size_t index;
 	int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
-	    constraint, &index);
+	    FRAME_LOWPRIO, constraint, &index);
 	
 	ASSERT(avail);
@@ -883,11 +961,4 @@
 }
 
-uintptr_t frame_alloc_noreserve(size_t count, frame_flags_t flags,
-    uintptr_t constraint)
-{
-	return frame_alloc_generic(count, flags | FRAME_NO_RESERVE, constraint,
-	    NULL);
-}
-
 /** Free frames of physical memory.
  *
@@ -1137,5 +1208,5 @@
 	/*
 	 * Because printing may require allocation of memory, we may not hold
-	 * the frame allocator locks when printing zone statistics.  Therefore,
+	 * the frame allocator locks when printing zone statistics. Therefore,
 	 * we simply gather the statistics under the protection of the locks and
 	 * print the statistics when the locks have been released.
@@ -1146,4 +1217,8 @@
 	 */
 	
+	size_t free_lowmem = 0;
+	size_t free_highmem = 0;
+	size_t free_highprio = 0;
+	
 	for (size_t i = 0;; i++) {
 		irq_spinlock_lock(&zones.lock, true);
@@ -1154,5 +1229,6 @@
 		}
 		
-		uintptr_t base = PFN2ADDR(zones.info[i].base);
+		pfn_t fbase = zones.info[i].base;
+		uintptr_t base = PFN2ADDR(fbase);
 		size_t count = zones.info[i].count;
 		zone_flags_t flags = zones.info[i].flags;
@@ -1160,7 +1236,36 @@
 		size_t busy_count = zones.info[i].busy_count;
 		
+		bool available = ((flags & ZONE_AVAILABLE) != 0);
+		bool lowmem = ((flags & ZONE_LOWMEM) != 0);
+		bool highmem = ((flags & ZONE_HIGHMEM) != 0);
+		bool highprio = is_high_priority(fbase, count);
+		
+		if (available) {
+			if (lowmem)
+				free_lowmem += free_count;
+			
+			if (highmem)
+				free_highmem += free_count;
+			
+			if (highprio) {
+				free_highprio += free_count;
+			} else {
+				/*
+				 * Walk all frames of the zone and examine
+				 * all high priority memory to get accurate
+				 * statistics.
+				 */
+				
+				for (size_t index = 0; index < count; index++) {
+					if (is_high_priority(fbase + index, 0)) {
+						if (!bitmap_get(&zones.info[i].bitmap, index))
+							free_highprio++;
+					} else
+						break;
+				}
+			}
+		}
+		
 		irq_spinlock_unlock(&zones.lock, true);
-		
-		bool available = ((flags & ZONE_AVAILABLE) != 0);
 		
 		printf("%-4zu", i);
@@ -1187,4 +1292,24 @@
 		printf("\n");
 	}
+	
+	printf("\n");
+	
+	uint64_t size;
+	const char *size_suffix;
+	
+	bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
+	    false);
+	printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
+	    free_lowmem, size, size_suffix);
+	
+	bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
+	    false);
+	printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
+	    free_highmem, size, size_suffix);
+	
+	bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
+	    false);
+	printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
+	    free_highprio, size, size_suffix);
 }
 
@@ -1212,5 +1337,10 @@
 	}
 	
-	uintptr_t base = PFN2ADDR(zones.info[znum].base);
+	size_t free_lowmem = 0;
+	size_t free_highmem = 0;
+	size_t free_highprio = 0;
+	
+	pfn_t fbase = zones.info[znum].base;
+	uintptr_t base = PFN2ADDR(fbase);
 	zone_flags_t flags = zones.info[znum].flags;
 	size_t count = zones.info[znum].count;
@@ -1218,17 +1348,47 @@
 	size_t busy_count = zones.info[znum].busy_count;
 	
+	bool available = ((flags & ZONE_AVAILABLE) != 0);
+	bool lowmem = ((flags & ZONE_LOWMEM) != 0);
+	bool highmem = ((flags & ZONE_HIGHMEM) != 0);
+	bool highprio = is_high_priority(fbase, count);
+	
+	if (available) {
+		if (lowmem)
+			free_lowmem = free_count;
+		
+		if (highmem)
+			free_highmem = free_count;
+		
+		if (highprio) {
+			free_highprio = free_count;
+		} else {
+			/*
+			 * Walk all frames of the zone and examine
+			 * all high priority memory to get accurate
+			 * statistics.
+			 */
+			
+			for (size_t index = 0; index < count; index++) {
+				if (is_high_priority(fbase + index, 0)) {
+					if (!bitmap_get(&zones.info[znum].bitmap, index))
+						free_highprio++;
+				} else
+					break;
+			}
+		}
+	}
+	
 	irq_spinlock_unlock(&zones.lock, true);
-	
-	bool available = ((flags & ZONE_AVAILABLE) != 0);
 	
 	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 (%" PRIu64 " %s)\n", count,
+	printf("Zone number:             %zu\n", znum);
+	printf("Zone base address:       %p\n", (void *) base);
+	printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
 	    size, size_suffix);
-	printf("Zone flags:        %c%c%c%c%c\n",
+	printf("Zone flags:              %c%c%c%c%c\n",
 	    available ? 'A' : '-',
 	    (flags & ZONE_RESERVED) ? 'R' : '-',
@@ -1240,10 +1400,26 @@
 		bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
 		    false);
-		printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
+		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",
+		printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
 		    free_count, size, size_suffix);
+		
+		bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
+		    false);
+		printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
+		    free_lowmem, size, size_suffix);
+		
+		bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
+		    false);
+		printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
+		    free_highmem, size, size_suffix);
+		
+		bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
+		    false);
+		printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
+		    free_highprio, size, size_suffix);
 	}
 }
