Commit 75340d2a authored by Anton Burtsev's avatar Anton Burtsev Committed by Vikram Narayanan

Simple, list-based capability allocator

  -- I've split capability allocation and cspaces, this makes much more
     sense -- complex domains can implement custom allocation policies,
     simple domains go with a static set of caps
  -- This is a list-based (zone like) allocator
parent c7c672e4
ccflags-y += -Ivirt/kvm -Iarch/x86/kvm
obj-$(CONFIG_LCD) += lcd-domains.o
#
#obj-m += lcd.o
lcd-domains-y += $(addprefix ../../../virt/lcd/, core.o cap.o \
ipc.o cap-cache.o)
lcd-domains-y += lcd-vtx.o utils.o
/*
* Author: Anton Burtsev <aburtsev@flux.utah.edu>
* Copyright: University of Utah
*/
#ifndef _LCD_CAP_CACHE_H_
#define _LCD_CAP_CACHE_H_
#include <lcd/cap.h>
#include <linux/spinlock.h>
struct cap_cache {
uint32_t *cap;
uint32_t head;
spinlock_t lock;
};
int lcd_init_list_cache(struct cap_cache *list_cache, uint64_t size);
void lcd_free_list_cache(struct cap_cache *list_cache);
int lcd_alloc_cap(struct cap_cache *cap_cache, capability_t *free_cap);
void lcd_free_cap(struct cap_cache *cap_cache, capability_t free_cap);
#endif
......@@ -5,6 +5,7 @@
#define __LCD_CAP_H__
#include <linux/types.h>
#include <linux/spinlock.h>
#include <uapi/linux/lcd-cap.h>
......
......@@ -17,21 +17,34 @@ static inline int lcd_create_sync_endpoint(capability_t cap, capability_t rvp) {
};
int lcd_create_sync_endpoint(capability_t otherend) {
int ret;
struct sync_ipc *rvp;
capability_t free_cap;
rvp = alloc_sync_ipc();
if(!rvp) {
printk(KERN_ERR "Failed to allocate memory\n");
return -ENOMEM;
ret = -ENOMEM;
goto err;
};
ret = lcd_alloc_free_cap(cap_cache, &free_cap);
if(ret) {
printk(KERN_ERR "Failed to allocate free capability\n");
ret = -ENOSPC;
kfree(rvp);
goto err;
};
cnode = lcd_cnode_lookup(&current->cspace, free_cap);
if(cnode == 0) {
printk(KERN_ERR "Failed to create capability\n");
kfree(rvp);
return -ENOMEM;
ret = -ENOMEM;
goto err;
};
cnode->type = LCD_TYPE_SYNC_EP;
......@@ -39,10 +52,18 @@ int lcd_create_sync_endpoint(capability_t otherend) {
lcd_cnode_release(cnode);
ipc_reply(otherend,
msg->cap_regs[0] = free_cap;
msg->valid_cap_regs = 1;
ipc_reply(otherend, msg);
lcd_cap_drop(free_cap);
lcd_release_free_cap(cap_cache);
return 0;
err:
msg->err = ret;
ipc_reply(otherend, msg);
return ret;
};
......
#include <linux/slab.h>
#include <lcd/cap-cache.h>
#include <lcd/cap.h>
int lcd_init_list_cache(struct cap_cache *list_cache, uint64_t size) {
uint32_t i;
list_cache->cap = kmalloc(sizeof(*list_cache->cap)*size, GFP_KERNEL);
if(!list_cache->cap)
return -ENOMEM;
list_cache->head = 0;
for(i = 0; i < size; i++) {
list_cache->cap[i] = i + 1;
}
list_cache->cap[size - 2] = size - 2;
return 0;
}
void lcd_free_list_cache(struct cap_cache *list_cache) {
kfree(list_cache->cap);
return;
};
int lcd_alloc_cap(struct cap_cache *cap_cache, capability_t *free_cap) {
unsigned long flags;
uint32_t head;
spin_lock_irqsave(&cap_cache->lock, flags);
if(cap_cache->head == cap_cache->cap[cap_cache->head]) {
spin_unlock_irqrestore(&cap_cache->lock, flags);
return -ENOMEM;
};
head = cap_cache->head;
*free_cap = (capability_t)head;
cap_cache->head = cap_cache->cap[head];
spin_unlock_irqrestore(&cap_cache->lock, flags);
return 0;
};
void lcd_free_cap(struct cap_cache *cap_cache, capability_t free_cap) {
unsigned long flags;
spin_lock_irqsave(&cap_cache->lock, flags);
cap_cache->cap[(uint32_t)free_cap] = cap_cache->head;
cap_cache->head = (uint32_t)free_cap;
spin_unlock_irqrestore(&cap_cache->lock, flags);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment