Index: generic/src/mm/frame.c
===================================================================
--- generic/src/mm/frame.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/frame.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,360 @@
+/*
+ * 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 <typedefs.h>
+#include <arch/types.h>
+#include <mm/heap.h>
+#include <mm/frame.h>
+#include <mm/vm.h>
+#include <panic.h>
+#include <debug.h>
+#include <list.h>
+#include <synch/spinlock.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+spinlock_t zone_head_lock;       /**< this lock protects zone_head list */
+link_t zone_head;                /**< list of all zones in the system */
+
+/** Initialize physical memory management
+ *
+ * Initialize physical memory managemnt.
+ */
+void frame_init(void)
+{
+	if (config.cpu_active == 1) {
+		zone_init();
+	}
+
+	frame_arch_init();
+	
+	if (config.cpu_active == 1) {
+                frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE);
+        }	
+}
+
+/** Allocate a frame
+ *
+ * Allocate a frame of physical memory.
+ *
+ * @param flags Flags for host zone selection and address processing.
+ *
+ * @return Allocated frame.
+ */
+__address frame_alloc(int flags)
+{
+	ipl_t ipl;
+	link_t *cur, *tmp;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame = NULL;
+	__address v;
+	
+loop:
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find suitable frame zone.
+	 */
+	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 any free frames.
+		 */
+		if (z->free_count) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	if (!zone) {
+		if (flags & FRAME_PANIC)
+			panic("Can't allocate frame.\n");
+		
+		/*
+		 * TODO: Sleep until frames are available again.
+		 */
+		spinlock_unlock(&zone_head_lock);
+		interrupts_restore(ipl);
+
+		panic("Sleep not implemented.\n");
+		goto loop;
+	}
+		
+	tmp = zone->free_head.next;
+	frame = list_get_instance(tmp, frame_t, link);
+
+	frame->refcount++;
+	list_remove(tmp);			/* remove frame from free_head */
+	zone->free_count--;
+	zone->busy_count++;
+	
+	v = zone->base + (frame - zone->frames) * FRAME_SIZE;
+	
+	if (flags & FRAME_KA)
+		v = PA2KA(v);
+	
+	spinlock_unlock(&zone->lock);
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+	
+	return v;
+}
+
+/** Free a frame.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Decrement frame reference count.
+ * 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)
+{
+	ipl_t ipl;
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+	ASSERT(frame->refcount);
+
+	if (!--frame->refcount) {
+		list_append(&frame->link, &zone->free_head);	/* append frame to free_head */
+		zone->free_count++;
+		zone->busy_count--;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+}
+
+/** Mark frame not free.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Increment frame reference count and remove the frame structure from free list.
+ *
+ * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE.
+ */
+void frame_not_free(__address addr)
+{
+	ipl_t ipl;
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+
+	if (!frame->refcount) {
+		frame->refcount++;
+
+		list_remove(&frame->link);			/* remove frame from free_head */
+		zone->free_count--;
+		zone->busy_count++;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+}
+
+/** Mark frame region not free.
+ *
+ * Mark frame region not free.
+ *
+ * @param start First address.
+ * @param stop Last address.
+ */
+void frame_region_not_free(__address start, __address stop)
+{
+        __address a;
+
+        start /= FRAME_SIZE;
+        stop /= FRAME_SIZE;
+        for (a = start; a <= stop; a++)
+                frame_not_free(a * FRAME_SIZE);
+}
+
+
+/** Initialize zonekeeping
+ *
+ * Initialize zonekeeping.
+ */
+void zone_init(void)
+{
+	spinlock_initialize(&zone_head_lock);
+	list_initialize(&zone_head);
+}
+
+/** 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;
+	
+	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);
+	
+		z->base = start;
+		z->flags = flags;
+
+		z->free_count = cnt;
+		list_initialize(&z->free_head);
+
+		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);
+			list_append(&z->frames[i].link, &z->free_head);
+		}
+		
+	}
+	
+	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 = 0;
+	link_initialize(&frame->link);
+}
