Subversion Repositories HelenOS

Compare Revisions

Regard whitespace Rev 813 → Rev 814

/kernel/trunk/generic/include/proc/thread.h
111,7 → 111,6
ARCH_THREAD_DATA; /**< Architecture-specific data. */
 
__u8 *kstack; /**< Thread's kernel stack. */
__u8 *ustack; /**< Thread's user stack. */
};
 
/** Thread list lock.
/kernel/trunk/generic/include/mm/heap.h
File deleted
/kernel/trunk/generic/include/mm/frame.h
35,10 → 35,15
#include <adt/list.h>
#include <synch/spinlock.h>
#include <mm/buddy.h>
#include <mm/slab.h>
#include <arch/mm/page.h>
 
#define ONE_FRAME 0
 
#define ZONES_MAX 16 /**< Maximum number of zones in system */
 
#define ZONE_JOIN 0x1 /**< If possible, merge with neighberhood zones */
 
 
#define FRAME_KA 0x1 /* skip frames conflicting with user address space */
#define FRAME_PANIC 0x2 /* panic on failure */
#define FRAME_ATOMIC 0x4 /* do not panic and do not sleep on failure */
48,92 → 53,61
#define FRAME_NO_MEMORY 1 /* frame_alloc return status */
#define FRAME_ERROR 2 /* frame_alloc return status */
 
#define FRAME2ADDR(zone, frame) ((zone)->base + (((frame) - (zone)->frames) << FRAME_WIDTH))
#define ADDR2FRAME(zone, addr) (&((zone)->frames[(((addr) - (zone)->base) >> FRAME_WIDTH)]))
#define FRAME_INDEX(zone, frame) ((index_t)((frame) - (zone)->frames))
#define FRAME_INDEX_ABS(zone, frame) (((index_t)((frame) - (zone)->frames)) + (zone)->base_index)
#define FRAME_INDEX_VALID(zone, index) (((index) >= 0) && ((index) < ((zone)->free_count + (zone)->busy_count)))
/* Return true if the interlvals overlap */
static inline int overlaps(__address s1,__address e1, __address s2, __address e2)
{
if (s1 >= s2 && s1 < e2)
return 1;
if (e1 >= s2 && e1 < e2)
return 1;
if ((s1 < s2) && (e1 >= e2))
return 1;
return 0;
}
 
static inline __address PFN2ADDR(pfn_t frame)
{
return (__address)(frame << PAGE_WIDTH);
}
 
static inline pfn_t ADDR2PFN(__address addr)
{
return (pfn_t)(addr >> PAGE_WIDTH);
}
 
static inline pfn_t SIZE2PFN(__address size)
{
if (!size)
return 0;
return (pfn_t)((size-1) >> PAGE_WIDTH)+1;
}
 
#define IS_BUDDY_ORDER_OK(index, order) ((~(((__native) -1) << (order)) & (index)) == 0)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) (((FRAME_INDEX((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) (((FRAME_INDEX((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) (((FRAME_INDEX_ABS((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) (((FRAME_INDEX_ABS((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
 
#define ZONE_BLACKLIST_SIZE 8
 
#define frame_alloc(order, flags) frame_alloc_generic(order, flags, NULL, NULL)
#define frame_alloc_rc(order, flags, status) frame_alloc_generic(order, flags, status, NULL)
#define frame_alloc_rc_zone(order, flags, status, zone) frame_alloc_generic(order, flags, status, zone)
 
struct zone {
link_t link; /**< link to previous and next zone */
 
SPINLOCK_DECLARE(lock); /**< this lock protects everything below */
__address base; /**< physical address of the first frame in the frames array */
index_t base_index; /**< frame index offset of the zone base */
frame_t *frames; /**< array of frame_t structures in this zone */
count_t free_count; /**< number of free frame_t structures */
count_t busy_count; /**< number of busy frame_t structures */
buddy_system_t * buddy_system; /**< buddy system for the zone */
int flags;
};
 
struct frame {
count_t refcount; /**< tracking of shared frames */
__u8 buddy_order; /**< buddy system block order */
link_t buddy_link; /**< link to the next free block inside one order */
void *parent; /**< If allocated by slab, this points there */
};
 
struct region {
__address base;
size_t size;
};
 
extern region_t zone_blacklist[];
extern count_t zone_blacklist_count;
extern void frame_region_not_free(__address base, size_t size);
extern void zone_create_in_region(__address base, size_t size);
 
extern spinlock_t zone_head_lock; /**< this lock protects zone_head list */
extern link_t zone_head; /**< list of all zones in the system */
 
extern zone_t *zone_create(__address start, size_t size, int flags);
extern void zone_attach(zone_t *zone);
 
extern void frame_init(void);
extern void frame_initialize(frame_t *frame, zone_t *zone);
 
__address frame_alloc_generic(__u8 order, int flags, int * status, zone_t **pzone);
 
 
__address frame_alloc_generic(__u8 order, int flags, int * status, int *pzone);
extern void frame_free(__address addr);
 
zone_t * get_zone_by_frame(frame_t * frame);
extern void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags);
 
/*
* Buddy system operations
*/
link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * buddy);
link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block);
link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * buddy_l, link_t * buddy_r);
void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order);
__u8 zone_buddy_get_order(buddy_system_t *b, link_t * block);
void zone_buddy_mark_busy(buddy_system_t *b, link_t * block);
extern frame_t * frame_addr2frame(__address addr);
void * frame_get_parent(pfn_t frame, int hint);
void frame_set_parent(pfn_t frame, void *data, int hint);
void frame_mark_unavailable(pfn_t start, pfn_t count);
__address zone_conf_size(pfn_t start, pfn_t count);
 
/*
* TODO: Implement the following functions.
*/
extern frame_t *frame_reference(frame_t *frame);
extern void frame_release(frame_t *frame);
 
 
/*
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(__address base);
void zone_print_one(int znum);
 
#endif
/kernel/trunk/generic/include/mm/slab.h
32,6 → 32,7
#include <adt/list.h>
#include <synch/spinlock.h>
#include <arch/atomic.h>
#include <mm/frame.h>
 
/** Minimum size to be allocated by malloc */
#define SLAB_MIN_MALLOC_W 4
126,4 → 127,6
/* Malloc support */
extern void * kalloc(unsigned int size, int flags);
extern void kfree(void *obj);
#define malloc(x) kalloc(x, FRAME_ATOMIC)
#define free(x) kfree(x)
#endif
/kernel/trunk/generic/include/mm/buddy.h
42,6 → 42,9
void (*set_order)(buddy_system_t *, link_t *, __u8); /**< Set order of block passed as argument. */
__u8 (*get_order)(buddy_system_t *, link_t *); /**< Return order of block passed as argument. */
void (*mark_busy)(buddy_system_t *, link_t *); /**< Mark block as busy */
void (*mark_available)(buddy_system_t *, link_t *); /**< Mark block as busy */
/** Find parent of block that has given order */
link_t *(* find_block)(buddy_system_t *, link_t *, __u8);
};
 
struct buddy_system {
51,10 → 54,14
void *data; /**< Pointer to be used by the implementation. */
};
 
extern buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op, void *data);
extern void buddy_system_create(buddy_system_t *b,
__u8 max_order,
buddy_system_operations_t *op, void *data);
extern link_t *buddy_system_alloc(buddy_system_t *b, __u8 i);
extern bool buddy_system_can_alloc(buddy_system_t *b, __u8 order);
extern void buddy_system_free(buddy_system_t *b, link_t *block);
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size);
extern size_t buddy_conf_size(int max_order);
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block);
 
#endif
/kernel/trunk/generic/include/typedefs.h
66,10 → 66,6
typedef struct buddy_system buddy_system_t;
typedef struct buddy_system_operations buddy_system_operations_t;
 
typedef struct zone zone_t;
typedef struct frame frame_t;
typedef struct region region_t;
 
typedef enum as_area_type as_area_type_t;
typedef struct as_area as_area_t;
typedef struct as as_t;
/kernel/trunk/generic/src/proc/scheduler.c
29,7 → 29,6
#include <proc/scheduler.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <mm/heap.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <mm/as.h>
/kernel/trunk/generic/src/proc/task.c
29,7 → 29,7
#include <proc/thread.h>
#include <proc/task.h>
#include <mm/as.h>
#include <mm/heap.h>
#include <mm/slab.h>
 
#include <synch/spinlock.h>
#include <arch.h>
/kernel/trunk/generic/src/proc/thread.c
29,7 → 29,6
#include <proc/scheduler.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <mm/heap.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <arch/asm.h>
95,6 → 94,7
static int thr_constructor(void *obj, int kmflags)
{
thread_t *t = (thread_t *)obj;
pfn_t pfn;
 
spinlock_initialize(&t->lock, "thread_t_lock");
link_initialize(&t->rq_link);
102,7 → 102,8
link_initialize(&t->th_link);
link_initialize(&t->threads_link);
t->kstack = (__u8 *)frame_alloc(ONE_FRAME, FRAME_KA | kmflags);
pfn = frame_alloc(ONE_FRAME, FRAME_KA | kmflags);
t->kstack = (__u8 *)PA2KA(PFN2ADDR(pfn));
if (!t->kstack)
return -1;
 
114,7 → 115,7
{
thread_t *t = (thread_t *)obj;
 
frame_free((__address) t->kstack);
frame_free(ADDR2PFN(KA2PA(t->kstack)));
return 1; /* One page freed */
}
 
193,9 → 194,6
t->cpu->fpu_owner=NULL;
spinlock_unlock(&t->cpu->lock);
 
if (t->ustack)
frame_free((__address) t->ustack);
/*
* Detach from the containing task.
*/
228,16 → 226,11
thread_t *thread_create(void (* func)(void *), void *arg, task_t *task, int flags)
{
thread_t *t;
__address frame_us = NULL;
 
t = (thread_t *) slab_alloc(thread_slab, 0);
if (t) {
ipl_t ipl;
if (THREAD_USER_STACK & flags) {
frame_us = frame_alloc(ONE_FRAME, FRAME_KA);
}
 
/* Not needed, but good for debugging */
memsetb((__address)t->kstack, THREAD_STACK_SIZE, 0);
 
247,8 → 240,6
spinlock_unlock(&tidlock);
interrupts_restore(ipl);
t->ustack = (__u8 *) frame_us;
context_save(&t->saved_context);
context_set(&t->saved_context, FADDR(cushion), (__address) t->kstack, THREAD_STACK_SIZE);
/kernel/trunk/generic/src/main/main.c
43,7 → 43,6
#include <align.h>
#include <interrupt.h>
#include <arch/mm/memory_init.h>
#include <mm/heap.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <genarch/mm/page_pt.h>
103,6 → 102,8
*/
void main_bsp(void)
{
__address stackaddr;
 
config.cpu_count = 1;
config.cpu_active = 1;
111,19 → 112,22
config.init_addr = init_addr;
config.init_size = init_size;
if (init_size > 0)
config.heap_addr = init_addr + init_size;
else
config.heap_addr = hardcoded_load_address + hardcoded_ktext_size + hardcoded_kdata_size;
config.kernel_size = ALIGN_UP(hardcoded_ktext_size + hardcoded_kdata_size, PAGE_SIZE);
stackaddr = config.base + config.kernel_size;
/* Avoid placing kernel on top of init */
if (overlaps(stackaddr,stackaddr+CONFIG_STACK_SIZE,
config.init_addr, config.init_addr+config.init_size)) {
config.heap_size = CONFIG_HEAP_SIZE + (config.memory_size / FRAME_SIZE) * sizeof(frame_t);
stackaddr = ALIGN_UP(config.init_addr+config.init_size,
CONFIG_STACK_SIZE);
config.init_size = ALIGN_UP(config.init_size,CONFIG_STACK_SIZE) + CONFIG_STACK_SIZE;
} else {
config.kernel_size += CONFIG_STACK_SIZE;
}
config.kernel_size = ALIGN_UP(config.heap_addr - hardcoded_load_address + config.heap_size, PAGE_SIZE);
config.heap_delta = config.kernel_size - (config.heap_addr - hardcoded_load_address + config.heap_size);
config.kernel_size = config.kernel_size + CONFIG_STACK_SIZE;
context_save(&ctx);
context_set(&ctx, FADDR(main_bsp_separated_stack), config.base + config.kernel_size - CONFIG_STACK_SIZE, CONFIG_STACK_SIZE);
context_set(&ctx, FADDR(main_bsp_separated_stack),
stackaddr, CONFIG_STACK_SIZE);
context_restore(&ctx);
/* not reached */
}
140,7 → 144,6
thread_t *t;
the_initialize(THE);
/*
* kconsole data structures must be initialized very early
* because other subsystems will register their respective
158,7 → 161,7
* Memory management subsystems initialization.
*/
arch_pre_mm_init();
early_heap_init(config.heap_addr, config.heap_size + config.heap_delta);
/* Initialize at least 1 memory segment big enough for slab to work */
frame_init();
slab_cache_init();
as_init();
165,7 → 168,6
page_init();
tlb_init();
arch_post_mm_init();
 
version_print();
 
printf("%P: hardcoded_ktext_size=%dK, hardcoded_kdata_size=%dK\n",
178,11 → 180,9
 
printf("config.memory_size=%dM\n", config.memory_size/(1024*1024));
printf("config.cpu_count=%d\n", config.cpu_count);
 
cpu_init();
 
calibrate_delay_loop();
 
timeout_init();
scheduler_init();
task_init();
/kernel/trunk/generic/src/lib/sort.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <mm/heap.h>
#include <mm/slab.h>
#include <memstr.h>
#include <sort.h>
#include <panic.h>
/kernel/trunk/generic/src/cpu/cpu.c
29,7 → 29,7
#include <cpu.h>
#include <arch.h>
#include <arch/cpu.h>
#include <mm/heap.h>
#include <mm/slab.h>
#include <mm/page.h>
#include <mm/frame.h>
#include <arch/types.h>
61,7 → 61,7
memsetb((__address) cpus, sizeof(cpu_t) * config.cpu_count, 0);
 
for (i=0; i < config.cpu_count; i++) {
cpus[i].stack = (__u8 *) frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC);
cpus[i].stack = (__u8 *) PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA | FRAME_PANIC)));
cpus[i].id = i;
/kernel/trunk/generic/src/adt/hash_table.c
35,7 → 35,7
#include <typedefs.h>
#include <arch/types.h>
#include <debug.h>
#include <mm/heap.h>
#include <mm/slab.h>
#include <memstr.h>
 
/** Create chained hash table.
/kernel/trunk/generic/src/mm/heap.c
File deleted
/kernel/trunk/generic/src/mm/slab.c
96,7 → 96,6
#include <adt/list.h>
#include <memstr.h>
#include <align.h>
#include <mm/heap.h>
#include <mm/frame.h>
#include <config.h>
#include <print.h>
154,11 → 153,12
slab_t *slab;
size_t fsize;
int i;
zone_t *zone = NULL;
int status;
frame_t *frame;
pfn_t pfn;
int zone=0;
 
data = (void *)frame_alloc_rc_zone(cache->order, FRAME_KA | flags, &status, &zone);
pfn = frame_alloc_rc_zone(cache->order, FRAME_KA | flags, &status, &zone);
data = (void *) PA2KA(PFN2ADDR(pfn));
if (status != FRAME_OK) {
return NULL;
}
165,7 → 165,7
if (! (cache->flags & SLAB_CACHE_SLINSIDE)) {
slab = slab_alloc(slab_extern_cache, flags);
if (!slab) {
frame_free((__address)data);
frame_free(ADDR2PFN(KA2PA(data)));
return NULL;
}
} else {
174,11 → 174,8
}
/* Fill in slab structures */
/* TODO: some better way of accessing the frame */
for (i=0; i < (1 << cache->order); i++) {
frame = ADDR2FRAME(zone, KA2PA((__address)(data+i*PAGE_SIZE)));
frame->parent = slab;
}
for (i=0; i < (1 << cache->order); i++)
frame_set_parent(pfn+i, slab, zone);
 
slab->start = data;
slab->available = cache->objects;
199,7 → 196,7
*/
static count_t slab_space_free(slab_cache_t *cache, slab_t *slab)
{
frame_free((__address)slab->start);
frame_free(ADDR2PFN(KA2PA(slab->start)));
if (! (cache->flags & SLAB_CACHE_SLINSIDE))
slab_free(slab_extern_cache, slab);
 
211,10 → 208,7
/** Map object to slab structure */
static slab_t * obj2slab(void *obj)
{
frame_t *frame;
 
frame = frame_addr2frame((__address)obj);
return (slab_t *)frame->parent;
return (slab_t *)frame_get_parent(ADDR2PFN(KA2PA(obj)), 0);
}
 
/**************************************/
725,8 → 719,9
/* Disable interrupts to avoid deadlocks with interrupt handlers */
ipl = interrupts_disable();
 
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) {
result = magazine_obj_get(cache);
}
if (!result)
result = slab_obj_create(cache, flags);
 
/kernel/trunk/generic/src/mm/as.c
36,8 → 36,8
#include <arch/mm/as.h>
#include <mm/page.h>
#include <mm/frame.h>
#include <mm/slab.h>
#include <mm/tlb.h>
#include <mm/heap.h>
#include <arch/mm/page.h>
#include <genarch/mm/page_pt.h>
#include <mm/asid.h>
253,7 → 253,7
* do not forget to distinguish between
* the different causes
*/
frame = frame_alloc(ONE_FRAME, 0);
frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
memsetb(PA2KA(frame), FRAME_SIZE, 0);
/*
/kernel/trunk/generic/src/mm/buddy.c
28,7 → 28,6
 
#include <mm/buddy.h>
#include <mm/frame.h>
#include <mm/heap.h>
#include <arch/types.h>
#include <typedefs.h>
#include <adt/list.h>
35,10 → 34,18
#include <debug.h>
#include <print.h>
 
/** Return size needed for the buddy configuration data */
size_t buddy_conf_size(int 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.
45,9 → 52,11
*
* @return New buddy system.
*/
buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op, void *data)
void buddy_system_create(buddy_system_t *b,
__u8 max_order,
buddy_system_operations_t *op,
void *data)
{
buddy_system_t *b;
int i;
 
ASSERT(max_order < BUDDY_SYSTEM_INNER_BLOCK);
60,20 → 69,10
ASSERT(op->mark_busy);
 
/*
* Allocate memory for structure describing the whole buddy system.
* Use memory after our own structure
*/
b = (buddy_system_t *) early_malloc(sizeof(buddy_system_t));
b->order = (link_t *) (&b[1]);
if (b) {
/*
* Allocate memory for all orders this buddy system will work with.
*/
b->order = (link_t *) early_malloc((max_order + 1) * sizeof(link_t));
if (!b->order) {
early_free(b);
return NULL;
}
for (i = 0; i <= max_order; i++)
list_initialize(&b->order[i]);
82,9 → 81,6
b->data = data;
}
return b;
}
 
/** Check if buddy system can allocate block
*
* @param b Buddy system pointer
114,6 → 110,42
}
 
/** 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;
__u8 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;
}
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.
137,7 → 169,6
b->op->mark_busy(b, res);
return res;
}
/*
* If order i is already the maximal order,
* the request cannot be satisfied.
167,8 → 198,8
b->op->set_order(b, hlp, i);
/*
* Return the other half to buddy system.
* PROBLEM!!!! WILL FIND OTHER PART AS BUDDY AND LINK TOGETHER
* Return the other half to buddy system. Mark the first part
* full, so that it won't coalsce again.
*/
b->op->mark_busy(b, res);
buddy_system_free(b, hlp);
/kernel/trunk/generic/src/mm/frame.c
27,9 → 27,18
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/*
* Locking order
*
* In order to access particular zone, the process must first lock
* the zones.lock, then lock the zone and then unlock the zones.lock.
* This insures, that we can fiddle with the zones in runtime without
* affecting the processes.
*
*/
 
#include <typedefs.h>
#include <arch/types.h>
#include <mm/heap.h>
#include <mm/frame.h>
#include <mm/as.h>
#include <panic.h>
40,258 → 49,386
#include <arch.h>
#include <print.h>
#include <align.h>
#include <mm/slab.h>
 
SPINLOCK_INITIALIZE(zone_head_lock); /**< this lock protects zone_head list */
LIST_INITIALIZE(zone_head); /**< list of all zones in the system */
typedef struct {
count_t refcount; /**< tracking of shared frames */
__u8 buddy_order; /**< buddy system block order */
link_t buddy_link; /**< link to the next free block inside one order */
void *parent; /**< If allocated by slab, this points there */
}frame_t;
 
/** Blacklist containing non-available areas of memory.
*
* This blacklist is used to exclude frames that cannot be allocated
* (e.g. kernel memory) from available memory map.
typedef struct {
SPINLOCK_DECLARE(lock); /**< this lock protects everything below */
pfn_t base; /**< frame_no of the first frame in the frames array */
pfn_t count; /**< Size of zone */
 
frame_t *frames; /**< array of frame_t structures in this zone */
count_t free_count; /**< number of free frame_t structures */
count_t busy_count; /**< number of busy frame_t structures */
buddy_system_t * buddy_system; /**< buddy system for the zone */
int flags;
}zone_t;
 
/*
* The zoneinfo.lock must be locked when accessing zoneinfo structure.
* Some of the attributes in zone_t structures are 'read-only'
*/
region_t zone_blacklist[ZONE_BLACKLIST_SIZE];
count_t zone_blacklist_count = 0;
 
static struct buddy_system_operations 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,
};
struct {
SPINLOCK_DECLARE(lock);
int count;
zone_t *info[ZONES_MAX];
}zones;
 
/** Initialize physical memory management
 
/*********************************/
/* Helper functions */
static inline index_t frame_index(zone_t *zone, frame_t *frame)
{
return (index_t)(frame - zone->frames);
}
static inline index_t frame_index_abs(zone_t *zone, frame_t *frame)
{
return (index_t)(frame - zone->frames) + zone->base;
}
static inline int frame_index_valid(zone_t *zone, index_t index)
{
return index >= 0 && index < zone->count;
}
 
/** Compute pfn_t from frame_t pointer & zone pointer */
static pfn_t make_frame_index(zone_t *zone, frame_t *frame)
{
return frame - zone->frames;
}
 
/** Initialize frame structure
*
* Initialize physical memory managemnt.
* Initialize frame structure.
*
* @param frame Frame structure to be initialized.
*/
void frame_init(void)
static void frame_initialize(frame_t *frame)
{
if (config.cpu_active == 1) {
frame_region_not_free(KA2PA(config.base), config.kernel_size);
if (config.init_size > 0)
frame_region_not_free(KA2PA(config.init_addr), config.init_size);
frame->refcount = 1;
frame->buddy_order = 0;
}
 
frame_arch_init();
/*************************************/
/* Zoneinfo functions */
 
/**
* Insert-sort zone into zones list
*/
static void zones_add_zone(zone_t *zone)
{
int i;
 
spinlock_lock(&zones.lock);
/* Try to merge */
if (zone->flags & ZONE_JOIN) {
for (i=0; i < zones.count; i++) {
spinlock_lock(&zones.info[i]->lock);
/* Join forward, join backward */
panic("Not implemented");
 
spinlock_unlock(&zones.info[i]->lock);
}
spinlock_unlock(&zones.lock);
} else {
if (zones.count+1 == ZONES_MAX)
panic("Maximum zone(%d) count exceeded.", ZONES_MAX);
zones.info[zones.count++] = zone;
}
spinlock_unlock(&zones.lock);
}
 
/**
* Find AND LOCK zone that can allocate order frames
* Try to find a zone where can we find the frame
*
* Assume zone_head_lock is locked.
* @param hint Start searching in zone 'hint'
* @param lock Lock zone if true
*
* Assume interrupts disable
*/
static zone_t * find_free_zone(__u8 order)
static zone_t * find_zone_and_lock(pfn_t frame, int *pzone)
{
link_t *cur;
int i;
int hint = pzone ? *pzone : 0;
zone_t *z;
 
for (cur = zone_head.next; cur != &zone_head;cur = cur->next) {
z = list_get_instance(cur, zone_t, link);
spinlock_lock(&zones.lock);
if (hint >= zones.count || hint < 0)
hint = 0;
i = hint;
do {
z = zones.info[i];
spinlock_lock(&z->lock);
/* Check if the zone has 2^order frames area available */
if (buddy_system_can_alloc(z->buddy_system, order))
if (z->base <= frame && z->base + z->count > frame) {
spinlock_unlock(&zones.lock); /* Unlock the global lock */
if (pzone)
*pzone = i;
return z;
}
spinlock_unlock(&z->lock);
spinlock_unlock(&z->lock);
}
i++;
if (i >= zones.count)
i = 0;
} while(i != hint);
 
spinlock_unlock(&zones.lock);
return NULL;
}
 
/** Allocate power-of-two frames of physical memory.
/**
* Find AND LOCK zone that can allocate order frames
*
* @param flags Flags for host zone selection and address processing.
* @param order Allocate exactly 2^order frames.
* @param pzone Pointer to preferred zone pointer, on output it changes
* to the zone that the frame was really allocated to
* Assume interrupts are disabled!!
*
* @return Allocated frame.
* @param pzone Pointer to preferred zone or NULL, on return contains zone number
*/
__address frame_alloc_generic(__u8 order, int flags, int * status, zone_t **pzone)
static zone_t * find_free_zone_lock(__u8 order, int *pzone)
{
ipl_t ipl;
link_t *tmp;
zone_t *zone = NULL;
frame_t *frame = NULL;
int freed;
__address v;
int i;
zone_t *z;
int hint = pzone ? *pzone : 0;
loop:
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
spinlock_lock(&zones.lock);
if (hint >= zones.count)
hint = 0;
i = hint;
do {
z = zones.info[i];
 
/*
* First, find suitable frame zone.
*/
if (pzone && *pzone) {
spinlock_lock(&(*pzone)->lock);
if (!buddy_system_can_alloc((*pzone)->buddy_system, order))
spinlock_unlock(&(*pzone)->lock);
else
zone = *pzone;
spinlock_lock(&z->lock);
 
/* Check if the zone has 2^order frames area available */
if (buddy_system_can_alloc(z->buddy_system, order)) {
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
if (!zone) {
zone = find_free_zone(order);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if (!zone && !(flags & FRAME_NO_RECLAIM)) {
spinlock_unlock(&zone_head_lock);
freed = slab_reclaim(0);
spinlock_lock(&zone_head_lock);
if (freed)
zone = find_free_zone(order);
if (!zone) {
spinlock_unlock(&zone_head_lock);
freed = slab_reclaim(SLAB_RECLAIM_ALL);
spinlock_lock(&zone_head_lock);
if (freed)
zone = find_free_zone(order);
spinlock_unlock(&z->lock);
if (++i >= zones.count)
i = 0;
} while(i != hint);
spinlock_unlock(&zones.lock);
return NULL;
}
}
}
 
if (!zone) {
if (flags & FRAME_PANIC)
panic("Can't allocate frame.\n");
/********************************************/
/* Buddy system functions */
/*
* TODO: Sleep until frames are available again.
/** 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!!
*/
spinlock_unlock(&zone_head_lock);
interrupts_restore(ipl);
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
__u8 order)
{
frame_t * frame;
zone_t * zone;
index_t index;
 
if (flags & FRAME_ATOMIC) {
ASSERT(status != NULL);
*status = FRAME_NO_MEMORY;
frame = list_get_instance(child, frame_t, buddy_link);
zone = (zone_t *) b->data;
 
index = frame_index(zone, frame);
do {
if (zone->frames[index].buddy_order != order) {
return &zone->frames[index].buddy_link;
}
} while(index-- > 0);
return NULL;
}
panic("Sleep not implemented.\n");
goto loop;
}
/* Allocate frames from zone buddy system */
tmp = buddy_system_alloc(zone->buddy_system, order);
ASSERT(tmp);
/** Buddy system find_buddy implementation
*
* @param b Buddy system.
* @param block Block for which buddy should be found
*
* @return Buddy for given block if found
*/
static link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block)
{
frame_t * frame;
zone_t * zone;
index_t index;
bool is_left, is_right;
/* Update zone information. */
zone->free_count -= (1 << order);
zone->busy_count += (1 << order);
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), frame->buddy_order));
 
/* Frame will be actually a first frame of the block. */
frame = list_get_instance(tmp, frame_t, buddy_link);
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
/* get frame address */
v = FRAME2ADDR(zone, frame);
ASSERT(is_left ^ is_right);
if (is_left) {
index = (frame_index(zone, frame)) + (1 << frame->buddy_order);
} else { // if (is_right)
index = (frame_index(zone, frame)) - (1 << frame->buddy_order);
}
 
spinlock_unlock(&zone->lock);
spinlock_unlock(&zone_head_lock);
interrupts_restore(ipl);
 
ASSERT(v == ALIGN_UP(v, FRAME_SIZE << 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;
}
}
 
if (flags & FRAME_KA)
v = PA2KA(v);
return NULL;
}
if (status)
*status = FRAME_OK;
/** Buddy system bisect implementation
*
* @param b Buddy system.
* @param block Block to bisect
*
* @return right block
*/
static link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) {
frame_t * frame_l, * frame_r;
 
if (pzone)
*pzone = zone;
return v;
frame_l = list_get_instance(block, frame_t, buddy_link);
frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
return &frame_r->buddy_link;
}
 
/** Convert address to zone pointer
/** Buddy system coalesce implementation
*
* Assume zone_head_lock is held
* @param b Buddy system.
* @param block_1 First block
* @param block_2 First block's buddy
*
* @param addr Physical address
* @param lock If true, lock the zone
* @return Coalesced block (actually block that represents lower address)
*/
static zone_t * addr2zone(__address addr, int lock)
{
link_t *cur;
zone_t *z = NULL;
static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1,
link_t * block_2) {
frame_t *frame1, *frame2;
 
for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
z = list_get_instance(cur, zone_t, link);
frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame2 = list_get_instance(block_2, frame_t, buddy_link);
spinlock_lock(&z->lock);
return frame1 < frame2 ? block_1 : block_2;
}
/*
* Check if addr belongs to z.
/** Buddy system set_order implementation
*
* @param b Buddy system.
* @param block Buddy system block
* @param order Order to set
*/
if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
if (!lock)
spinlock_unlock(&z->lock);
return z;
static void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
}
 
spinlock_unlock(&z->lock);
/** Buddy system get_order implementation
*
* @param b Buddy system.
* @param block Buddy system block
*
* @return Order of block
*/
static __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
}
 
panic("Cannot find addr2zone: 0x%X", addr);
/** Buddy system mark_busy implementation
*
* @param b Buddy system
* @param block Buddy system block
*
*/
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 1;
}
 
/** Return frame_t structure corresponding to address
/** Buddy system mark_available implementation
*
* @param b Buddy system
* @param block Buddy system block
*
*/
frame_t * frame_addr2frame(__address addr)
{
ipl_t ipl;
static void zone_buddy_mark_available(buddy_system_t *b, link_t * block) {
frame_t *frame;
zone_t *zone;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 0;
}
 
if (IS_KA(addr))
addr = KA2PA(addr);
static struct buddy_system_operations 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
};
 
/* Disable interrupts to avoid deadlocks with interrupt handlers */
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
/*************************************/
/* Zone functions */
zone = addr2zone(addr,0);
frame = ADDR2FRAME(zone, addr);
 
spinlock_unlock(&zone_head_lock);
interrupts_restore(ipl);
 
return frame;
}
 
 
/** Free a frame.
/** Allocate frame in particular zone
*
* Find respective frame structrue for supplied addr.
* Decrement frame reference count.
* If it drops to zero, move the frame structure to free list.
* Assume zone is locked
*
* @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
* @return Frame index in zone
*/
void frame_free(__address addr)
static pfn_t zone_frame_alloc(zone_t *zone,__u8 order, int flags, int *status)
{
ipl_t ipl;
zone_t *zone;
pfn_t v;
link_t *tmp;
frame_t *frame;
int order;
ASSERT(addr % FRAME_SIZE == 0);
/* Allocate frames from zone buddy system */
tmp = buddy_system_alloc(zone->buddy_system, order);
if (IS_KA(addr))
addr = KA2PA(addr);
ASSERT(tmp);
 
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
/* Update zone information. */
zone->free_count -= (1 << order);
zone->busy_count += (1 << order);
/*
* First, find host frame zone for addr.
/* Frame will be actually a first frame of the block. */
frame = list_get_instance(tmp, frame_t, buddy_link);
/* get frame address */
v = make_frame_index(zone, frame);
return v;
}
 
/** Free frame from zone
*
* Assume zone is locked
*/
zone = addr2zone(addr, 1); /* This locks the zone automatically */
static void zone_frame_free(zone_t *zone, pfn_t frame_idx)
{
frame_t *frame;
__u8 order;
frame = ADDR2FRAME(zone, addr);
frame = &zone->frames[frame_idx];
/* remember frame order */
order = frame->buddy_order;
305,80 → 442,28
/* Update zone information. */
zone->free_count += (1 << order);
zone->busy_count -= (1 << order);
spinlock_unlock(&zone->lock);
spinlock_unlock(&zone_head_lock);
interrupts_restore(ipl);
}
 
/** Mark frame region not free.
*
* Mark frame region not free.
*
* @param base Base address of non-available region.
* @param size Size of non-available region.
*/
void frame_region_not_free(__address base, size_t size)
/** Return frame from zone */
static frame_t * zone_get_frame(zone_t *zone, pfn_t frame_idx)
{
index_t index;
index = zone_blacklist_count++;
 
/* Force base to the nearest lower address frame boundary. */
base = ALIGN_DOWN(base, FRAME_SIZE);
/* Align size to frame boundary. */
size = ALIGN_UP(size, FRAME_SIZE);
 
ASSERT(index < ZONE_BLACKLIST_SIZE);
zone_blacklist[index].base = base;
zone_blacklist[index].size = size;
ASSERT(frame_idx < zone->count);
return &zone->frames[frame_idx];
}
 
/** Create frame zones in region of available memory.
*
* Avoid any black listed areas of non-available memory.
* Assume that the black listed areas cannot overlap
* one another or cross available memory region boundaries.
*
* @param base Base address of available memory region.
* @param size Size of the region.
*/
void zone_create_in_region(__address base, size_t size) {
int i;
zone_t * z;
__address s;
size_t sz;
/** Mark frame in zone unavailable to allocation */
static void zone_mark_unavailable(zone_t *zone, pfn_t frame_idx)
{
frame_t *frame;
link_t *link;
ASSERT(base % FRAME_SIZE == 0);
ASSERT(size % FRAME_SIZE == 0);
if (!size)
return;
 
for (i = 0; i < zone_blacklist_count; i++) {
if (zone_blacklist[i].base >= base && zone_blacklist[i].base < base + size) {
s = base; sz = zone_blacklist[i].base - base;
ASSERT(base != s || sz != size);
zone_create_in_region(s, sz);
s = zone_blacklist[i].base + zone_blacklist[i].size;
sz = (base + size) - (zone_blacklist[i].base + zone_blacklist[i].size);
ASSERT(base != s || sz != size);
zone_create_in_region(s, sz);
return;
frame = zone_get_frame(zone, frame_idx);
link = buddy_system_alloc_block(zone->buddy_system,
&frame->buddy_link);
ASSERT(link);
zone->free_count--;
}
}
z = zone_create(base, size, 0);
 
if (!z) {
panic("Cannot allocate zone (base=%P, size=%d).\n", base, size);
}
zone_attach(z);
}
 
 
/** Create frame zone
*
* Create new frame zone.
385,223 → 470,294
*
* @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 conffram Address of configuration frame
* @param flags Zone flags.
*
* @return Initialized zone.
*/
zone_t * zone_create(__address start, size_t size, int flags)
static zone_t * zone_construct(pfn_t start, pfn_t count,
zone_t *z, int flags)
{
zone_t *z;
count_t cnt;
int i;
__u8 max_order;
 
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, "zone_lock");
z->base = start;
z->base_index = start / FRAME_SIZE;
z->count = count;
z->flags = flags;
 
z->free_count = cnt;
z->free_count = count;
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);
}
/*
* Create buddy system for the zone
* Compute order for buddy system, initialize
*/
for (max_order = 0; cnt >> max_order; max_order++)
for (max_order = 0; count >> max_order; max_order++)
;
z->buddy_system = buddy_system_create(max_order, &zone_buddy_system_operations, (void *) z);
z->buddy_system = (buddy_system_t *)&z[1];
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations,
(void *) z);
/* Allocate frames _after_ the conframe */
/* Check sizes */
z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order));
 
for (i = 0; i<count; i++) {
frame_initialize(&z->frames[i]);
}
/* Stuffing frames */
for (i = 0; i<cnt; i++) {
for (i = 0; i < count; i++) {
z->frames[i].refcount = 0;
buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);
}
}
return z;
}
 
/** Attach frame zone
 
/** Compute configuration data size for zone */
__address zone_conf_size(pfn_t start, pfn_t count)
{
int size = sizeof(zone_t) + count*sizeof(frame_t);
int max_order;
 
for (max_order = 0; count >> max_order; max_order++)
;
size += buddy_conf_size(max_order);
return size;
}
 
/** Create and add zone to system
*
* Attach frame zone to zone list.
*
* @param zone Zone to be attached.
* @param confframe Where configuration frame is supposed to be.
* Always check, that we will not disturb kernel pages
* the kernel and possibly init.
* If confframe is given _outside_ this zone, it is expected,
* that the area is already marked BUSY and big enough
* to contain zone_conf_size() amount of data
*/
void zone_attach(zone_t *zone)
void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags)
{
ipl_t ipl;
zone_t *z;
__address addr,endaddr;
pfn_t confcount;
int i;
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
/* Theoretically we could have here 0, practically make sure
* nobody tries to do that. If some platform requires, remove
* the assert
*/
ASSERT(confframe);
/* If conframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
confcount = SIZE2PFN(zone_conf_size(start,count));
if (confframe >= start && confframe < start+count) {
for (;confframe < start+count;confframe++) {
addr = PFN2ADDR(confframe);
endaddr = PFN2ADDR (confframe + confcount);
if (overlaps(addr, endaddr, KA2PA(config.base),
KA2PA(config.base+config.kernel_size)))
continue;
if (config.init_addr)
if (overlaps(addr,endaddr,
KA2PA(config.init_addr),
KA2PA(config.init_addr+config.init_size)))
continue;
break;
}
if (confframe >= start+count)
panic("Cannot find configuration data for zone.");
}
list_append(&zone->link, &zone_head);
z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags);
zones_add_zone(z);
spinlock_unlock(&zone_head_lock);
interrupts_restore(ipl);
/* If confdata in zone, mark as unavailable */
if (confframe >= start && confframe < start+count)
for (i=confframe; i<confframe+confcount; i++) {
zone_mark_unavailable(z, i - z->base);
}
}
 
/** 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 functions */
 
/** Set parent of frame */
void frame_set_parent(pfn_t pfn, void *data, int hint)
{
frame->refcount = 1;
frame->buddy_order = 0;
zone_t *zone = find_zone_and_lock(pfn, &hint);
 
ASSERT(zone);
 
zone_get_frame(zone, pfn-zone->base)->parent = data;
spinlock_unlock(&zone->lock);
}
 
void * frame_get_parent(pfn_t pfn, int hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
void *res;
 
/** Buddy system find_buddy implementation
ASSERT(zone);
res = zone_get_frame(zone, pfn - zone->base)->parent;
spinlock_unlock(&zone->lock);
return res;
}
 
/** Allocate power-of-two frames of physical memory.
*
* @param b Buddy system.
* @param block Block for which buddy should be found
* @param flags Flags for host zone selection and address processing.
* @param order Allocate exactly 2^order frames.
* @param pzone Preferred zone
*
* @return Buddy for given block if found
* @return Allocated frame.
*/
link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) {
frame_t * frame;
pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone)
{
ipl_t ipl;
int freed;
pfn_t v;
zone_t * zone;
index_t index;
bool is_left, is_right;
 
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
ASSERT(IS_BUDDY_ORDER_OK(FRAME_INDEX_ABS(zone, frame), frame->buddy_order));
loop:
ipl = interrupts_disable();
/*
* First, find suitable frame zone.
*/
zone = find_free_zone_lock(order,pzone);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if (!zone && !(flags & FRAME_NO_RECLAIM)) {
freed = slab_reclaim(0);
if (freed)
zone = find_free_zone_lock(order,pzone);
if (!zone) {
freed = slab_reclaim(SLAB_RECLAIM_ALL);
if (freed)
zone = find_free_zone_lock(order,pzone);
}
}
if (!zone) {
if (flags & FRAME_PANIC)
panic("Can't allocate frame.\n");
/*
* TODO: Sleep until frames are available again.
*/
interrupts_restore(ipl);
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
ASSERT(is_left ^ is_right);
if (is_left) {
index = (FRAME_INDEX(zone, frame)) + (1 << frame->buddy_order);
} else { // if (is_right)
index = (FRAME_INDEX(zone, frame)) - (1 << frame->buddy_order);
if (flags & FRAME_ATOMIC) {
ASSERT(status != NULL);
if (status)
*status = FRAME_NO_MEMORY;
return NULL;
}
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;
panic("Sleep not implemented.\n");
goto loop;
}
}
v = zone_frame_alloc(zone,order,flags,status);
v += zone->base;
return NULL;
spinlock_unlock(&zone->lock);
interrupts_restore(ipl);
 
if (status)
*status = FRAME_OK;
return v;
}
 
/** Buddy system bisect implementation
/** Free a frame.
*
* @param b Buddy system.
* @param block Block to bisect
* Find respective frame structrue for supplied addr.
* Decrement frame reference count.
* If it drops to zero, move the frame structure to free list.
*
* @return right block
* @param frame Frame no to be freed.
*/
link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) {
frame_t * frame_l, * frame_r;
void frame_free(pfn_t pfn)
{
ipl_t ipl;
zone_t *zone;
 
frame_l = list_get_instance(block, frame_t, buddy_link);
frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
ipl = interrupts_disable();
return &frame_r->buddy_link;
}
 
/** Buddy system coalesce implementation
*
* @param b Buddy system.
* @param block_1 First block
* @param block_2 First block's buddy
*
* @return Coalesced block (actually block that represents lower address)
/*
* First, find host frame zone for addr.
*/
link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, link_t * block_2) {
frame_t * frame1, * frame2;
zone = find_zone_and_lock(pfn,NULL);
ASSERT(zone);
frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame2 = list_get_instance(block_2, frame_t, buddy_link);
zone_frame_free(zone, pfn-zone->base);
return frame1 < frame2 ? block_1 : block_2;
spinlock_unlock(&zone->lock);
interrupts_restore(ipl);
}
 
/** Buddy system set_order implementation
*
* @param b Buddy system.
* @param block Buddy system block
* @param order Order to set
*/
void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
}
 
/** Buddy system get_order implementation
*
* @param b Buddy system.
* @param block Buddy system block
*
* @return Order of block
*/
__u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
 
/** Mark given range unavailable in frame zones */
void frame_mark_unavailable(pfn_t start, pfn_t count)
{
int i;
zone_t *zone;
int prefzone = 0;
 
for (i=0; i<count; i++) {
zone = find_zone_and_lock(start+i,&prefzone);
if (!zone) /* PFN not found */
continue;
zone_mark_unavailable(zone, start+i-zone->base);
 
spinlock_unlock(&zone->lock);
}
}
 
/** Buddy system mark_busy implementation
/** Initialize physical memory management
*
* @param b Buddy system
* @param block Buddy system block
*
* Initialize physical memory managemnt.
*/
void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
frame_t * frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 1;
void frame_init(void)
{
if (config.cpu_active == 1) {
zones.count = 0;
spinlock_initialize(&zones.lock,"zones_glob_lock");
}
/* Tell the architecture to create some memory */
frame_arch_init();
if (config.cpu_active == 1) {
frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
SIZE2PFN(config.kernel_size));
if (config.init_size > 0)
frame_mark_unavailable(ADDR2PFN(KA2PA(config.init_addr)),
SIZE2PFN(config.init_size));
}
}
 
 
 
/** Prints list of zones
*
*/
void zone_print_list(void) {
zone_t *zone = NULL;
link_t *cur;
int i;
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
spinlock_lock(&zones.lock);
printf("Base address\tFree Frames\tBusy Frames\n");
printf("------------\t-----------\t-----------\n");
for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
zone = list_get_instance(cur, zone_t, link);
for (i=0;i<zones.count;i++) {
zone = zones.info[i];
spinlock_lock(&zone->lock);
printf("%L\t%d\t\t%d\n",zone->base, zone->free_count, zone->busy_count);
printf("%L\t%d\t\t%d\n",PFN2ADDR(zone->base),
zone->free_count, zone->busy_count);
spinlock_unlock(&zone->lock);
}
spinlock_unlock(&zone_head_lock);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
609,33 → 765,26
*
* @param base Zone base address
*/
void zone_print_one(__address base) {
zone_t *zone = NULL, *z ;
link_t *cur;
void zone_print_one(int znum) {
zone_t *zone = NULL;
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&zone_head_lock);
spinlock_lock(&zones.lock);
for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
z = list_get_instance(cur, zone_t, link);
if (base == z->base) {
zone = z;
break;
}
}
if (!zone) {
spinlock_unlock(&zone_head_lock);
if (znum >= zones.count || znum < 0) {
printf("Zone number out of bounds.\n");
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("No zone with address %X\n", base);
return;
}
zone = zones.info[znum];
spinlock_lock(&zone->lock);
printf("Memory zone information\n\n");
printf("Zone base address: %P\n", zone->base);
printf("Zone size: %d frames (%dK)\n", zone->free_count + zone->busy_count, ((zone->free_count + zone->busy_count) * FRAME_SIZE) >> 10);
printf("Zone base address: %P\n", PFN2ADDR(zone->base));
printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10);
printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10);
printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10);
643,7 → 792,7
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE);
spinlock_unlock(&zone->lock);
spinlock_unlock(&zone_head_lock);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}