All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit e1045ef9 authored by Muktesh Khole's avatar Muktesh Khole Committed by Vikram Narayanan

added feature to grant capabilities

parent a5d6ea85
...@@ -65,7 +65,6 @@ struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool all ...@@ -65,7 +65,6 @@ struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool all
newtable = kmem_cache_alloc(cspace->cnode_table_cache, 0); newtable = kmem_cache_alloc(cspace->cnode_table_cache, 0);
table->cnode[index].object = (void*)newtable; table->cnode[index].object = (void*)newtable;
newtable->table_level = table->table_level + 1; newtable->table_level = table->table_level + 1;
printk(KERN_ERR "lcd_cap Created a new table with level: %u", newtable->table_level);
for (i = 0; i < MAX_SLOTS_PER_TABLE; i++) for (i = 0; i < MAX_SLOTS_PER_TABLE; i++)
{ {
newtable->cnode[i].type = LCD_CAP_TYPE_FREE; newtable->cnode[i].type = LCD_CAP_TYPE_FREE;
...@@ -82,8 +81,11 @@ struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool all ...@@ -82,8 +81,11 @@ struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool all
} else { } else {
if ((alloc && table->cnode[levelId].type == LCD_CAP_TYPE_FREE) || if ((alloc && table->cnode[levelId].type == LCD_CAP_TYPE_FREE) ||
(!alloc && table->cnode[levelId].type != LCD_CAP_TYPE_FREE)) { (!alloc && table->cnode[levelId].type != LCD_CAP_TYPE_FREE)) {
printk(KERN_ERR "lcd_cap Lookup got a cnode");
cnode = &(table->cnode[levelId]); cnode = &(table->cnode[levelId]);
if (alloc) {
spin_lock_init(&cnode->lock);
cnode->cspace = cspace;
}
} else { } else {
printk(KERN_ERR "lcd_cap Lookup failed to get a cnode"); printk(KERN_ERR "lcd_cap Lookup failed to get a cnode");
cnode = NULL; cnode = NULL;
...@@ -105,6 +107,7 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap, ...@@ -105,6 +107,7 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
{ {
unsigned long flags, flags_cnode_lock; unsigned long flags, flags_cnode_lock;
struct cnode *cnode; struct cnode *cnode;
struct cdt_root_node *cdt_node;
spin_lock_irqsave(&cspace->lock, flags); spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) if (cspace->state != ALLOCATION_VALID)
...@@ -120,8 +123,8 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap, ...@@ -120,8 +123,8 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
}; };
cnode->object = object; cnode->object = object;
spin_lock_init(&cnode->lock);
spin_lock_irqsave(&cnode->lock, flags_cnode_lock); spin_lock_irqsave(&cnode->lock, flags_cnode_lock);
cdt_node = kmem_cache_alloc(cspace->cdt_root_cache, 0);
spin_unlock_irqrestore(&cspace->lock, flags); spin_unlock_irqrestore(&cspace->lock, flags);
cnode->cspace = cspace; cnode->cspace = cspace;
...@@ -130,7 +133,9 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap, ...@@ -130,7 +133,9 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
cnode->prev = NULL; cnode->prev = NULL;
cnode->child = NULL; cnode->child = NULL;
cnode->type = type; cnode->type = type;
cnode->cdt_root = kmem_cache_alloc(cspace->cdt_root_cache, 0); cnode->cdt_root = cdt_node;
cnode->cdt_root->state = ALLOCATION_VALID;
cnode->cdt_root->node_count = 0;
spin_lock_init(&(cnode->cdt_root->lock)); spin_lock_init(&(cnode->cdt_root->lock));
cnode->cdt_root->cnode = cnode; cnode->cdt_root->cnode = cnode;
cnode->cdt_root->node_count = 1; cnode->cdt_root->node_count = 1;
...@@ -146,11 +151,13 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) { ...@@ -146,11 +151,13 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
struct cnode *cnode; struct cnode *cnode;
unsigned long flags, flags_cnode_lock; unsigned long flags, flags_cnode_lock;
bool done = false; bool done = false, last_node;
struct cdt_root_node *cdt_node = NULL;
do { do {
spin_lock_irqsave(&cspace->lock, flags); spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) { if (cspace->state != ALLOCATION_VALID) {
printk(KERN_INFO "lcd_cap_delete cspace allocation is not valid\n");
spin_unlock_irqrestore(&cspace->lock, flags); spin_unlock_irqrestore(&cspace->lock, flags);
return; return;
} }
...@@ -158,6 +165,7 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) { ...@@ -158,6 +165,7 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
cnode = lcd_cnode_lookup(cspace, cap, false); cnode = lcd_cnode_lookup(cspace, cap, false);
if(cnode == NULL) if(cnode == NULL)
{ {
printk(KERN_INFO "lcd_cap_delete cnode not found\n");
spin_unlock_irqrestore(&cspace->lock, flags); spin_unlock_irqrestore(&cspace->lock, flags);
return; return;
} }
...@@ -165,23 +173,38 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) { ...@@ -165,23 +173,38 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
spin_lock_irqsave(&cnode->lock, flags_cnode_lock); spin_lock_irqsave(&cnode->lock, flags_cnode_lock);
spin_unlock_irqrestore(&cspace->lock, flags); spin_unlock_irqrestore(&cspace->lock, flags);
if (cnode->type == LCD_CAP_TYPE_FREE) { if (cnode->type == LCD_CAP_TYPE_FREE) {
printk(KERN_INFO "lcd_cap_delete cnode is already free\n");
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock); spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
return; return;
} }
if (spin_trylock(&cnode->cdt_root->lock)) { if (spin_trylock(&cnode->cdt_root->lock)) {
_lcd_delete_node(cspace, cnode); cdt_node = cnode->cdt_root;
if (cnode->cdt_root) { last_node = _lcd_delete_node(cspace, cnode);
spin_unlock(&cnode->cdt_root->lock); if (last_node) {
cnode->cdt_root = NULL; cdt_node->state = ALLOCATION_MARKED_FOR_DELETE;
} }
cnode->cdt_root = NULL;
lcd_free_cap(&(cspace->cap_cache), cap); spin_unlock(&(cdt_node->lock));
done = true; done = true;
} }
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock); spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
if (!done) { if (done) {
lcd_free_cap(&(cspace->cap_cache), cap);
if (last_node) {
// at this point we are not holding any locks
// so its ok to request for cspace lock
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cspace->lock, flags);
return;
}
cdt_node->state = ALLOCATION_REMOVED;
kmem_cache_free(cspace->cdt_root_cache, cdt_node);
spin_unlock_irqrestore(&(cspace->lock), flags);
}
} else {
// someone is using CDT root // someone is using CDT root
// wait for him to finish // wait for him to finish
msleep(5); msleep(5);
...@@ -190,6 +213,105 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) { ...@@ -190,6 +213,105 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
}; };
EXPORT_SYMBOL(lcd_cap_delete); EXPORT_SYMBOL(lcd_cap_delete);
int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *cspacedst, capability_t capdst)
{
struct cnode *cnodesrc, *cnodedst;
unsigned long flagssrc, flagsdst, flags_cnodesrc_lock, flags_cnodedst_lock;
bool done = false;
struct cdt_root_node *cdt_node;
do {
// src cspace and cnode
spin_lock_irqsave(&cspacesrc->lock, flagssrc);
if (cspacesrc->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cspacesrc->lock, flagssrc);
printk(KERN_ERR "lcd_cap_grant source cspace allocation is invalid");
return -EIDRM;
}
cnodesrc = lcd_cnode_lookup(cspacesrc, capsrc, false);
if(cnodesrc == NULL)
{
spin_unlock_irqrestore(&cspacesrc->lock, flagssrc);
printk(KERN_ERR "lcd_cap_grant cnode for source capability: %llu not found", capsrc);
return -EINVAL;
}
spin_lock_irqsave(&cnodesrc->lock, flags_cnodesrc_lock);
spin_unlock_irqrestore(&cspacesrc->lock, flagssrc);
if (cnodesrc->type == LCD_CAP_TYPE_FREE) {
spin_unlock_irqrestore(&cnodesrc->lock, flags_cnodesrc_lock);
printk(KERN_ERR "lcd_cap_grant cnode for source capability: %llu is invalid", capsrc);
return -EINVAL;
}
// dst cspace and cnode
spin_lock_irqsave(&cspacedst->lock, flagsdst);
if (cspacedst->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cnodesrc->lock, flags_cnodesrc_lock);
spin_unlock_irqrestore(&cspacedst->lock, flagsdst);
printk(KERN_ERR "lcd_cap_grant destination cspace allocation is invalid");
return -EIDRM;
}
cnodedst = lcd_cnode_lookup(cspacedst, capdst, true);
if(cnodedst == NULL)
{
spin_unlock_irqrestore(&cnodesrc->lock, flags_cnodesrc_lock);
spin_unlock_irqrestore(&cspacedst->lock, flagsdst);
printk(KERN_ERR "lcd_cap_grant cnode for destination capability: %llu not found", capdst);
return -EINVAL;
}
spin_lock_irqsave(&cnodedst->lock, flags_cnodedst_lock);
spin_unlock_irqrestore(&cspacedst->lock, flagsdst);
if (cnodedst->type != LCD_CAP_TYPE_FREE) {
spin_unlock_irqrestore(&cnodesrc->lock, flags_cnodesrc_lock);
spin_unlock_irqrestore(&cnodedst->lock, flags_cnodedst_lock);
printk(KERN_ERR "lcd_cap_grant cnode for destination capability: %llu is invalid", capdst);
return -EINVAL;
}
if (spin_trylock(&cnodesrc->cdt_root->lock)) {
cdt_node = cnodesrc->cdt_root;
cdt_node->node_count++;
// source and destination cnodes and cdt root is locked.
cnodedst->parent = cnodesrc;
cnodedst->type = cnodesrc->type;
cnodedst->object = cnodesrc->object;
cnodedst->cspace = cspacedst;
cnodedst->cdt_root = cnodesrc->cdt_root;
if (cnodesrc->child) {
struct cnode *childnode = cnodesrc->child;
cnodedst->prev = childnode->prev;
childnode->prev = cnodedst;
cnodedst->next = childnode;
} else {
cnodedst->prev = NULL;
cnodedst->next = NULL;
cnodedst->child = NULL;
}
cnodesrc->child = cnodedst;
done = true;
spin_unlock(&(cdt_node->lock));
}
spin_unlock_irqrestore(&cnodesrc->lock, flags_cnodesrc_lock);
spin_unlock_irqrestore(&cnodedst->lock, flags_cnodedst_lock);
if (!done) {
// someone is using CDT root
// wait for him to finish
msleep(5);
}
} while (!done);
return 0;
};
EXPORT_SYMBOL(lcd_cap_grant);
int lcd_cnode_insert(struct cspace *cspace, capability_t cap, struct cnode *cnode) { int lcd_cnode_insert(struct cspace *cspace, capability_t cap, struct cnode *cnode) {
/* XXX: not clear */ /* XXX: not clear */
...@@ -218,8 +340,6 @@ bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId) ...@@ -218,8 +340,6 @@ bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId)
bool more_levels; bool more_levels;
// Get rid of capability identifer bits // Get rid of capability identifer bits
capability_t c = ((uint64_t)cap >> CAP_IDENTIFIER_BITS) >> (table_level * TABLE_IDENTIFIER_BITS); capability_t c = ((uint64_t)cap >> CAP_IDENTIFIER_BITS) >> (table_level * TABLE_IDENTIFIER_BITS);
printk(KERN_ERR "lcd_cap cap: %llu", (uint64_t)cap);
printk(KERN_ERR "lcd_cap c = : %llu", (uint64_t)c);
if (c) if (c)
{ {
int level_mask = (MAX_TABLE_ID_SLOTS - 1); int level_mask = (MAX_TABLE_ID_SLOTS - 1);
...@@ -236,13 +356,24 @@ bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId) ...@@ -236,13 +356,24 @@ bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId)
} }
// assumes cnode and cdt root is locked (in that order) // assumes cnode and cdt root is locked (in that order)
void _lcd_delete_node (struct cspace *cspace, struct cnode *cnode){ bool _lcd_delete_node (struct cspace *cspace, struct cnode *cnode){
bool last_node;
cnode->object = NULL; cnode->object = NULL;
cnode->type = LCD_CAP_TYPE_FREE; cnode->type = LCD_CAP_TYPE_FREE;
cnode->cdt_root->node_count--; cnode->cdt_root->node_count--;
if (cnode->cdt_root->cnode == cnode) {
if (cnode->child) {
cnode->cdt_root->cnode = cnode->child;
} else if (cnode->next) {
cnode->cdt_root->cnode = cnode->next;
} else {
cnode->cdt_root->cnode = NULL;
}
}
if (cnode->cdt_root->node_count > 0) { if (cnode->cdt_root->node_count > 0) {
last_node = false;
// get cnode out of CDT // get cnode out of CDT
if (cnode->child) { if (cnode->child) {
struct cnode *childnode = cnode->child; struct cnode *childnode = cnode->child;
...@@ -288,8 +419,7 @@ void _lcd_delete_node (struct cspace *cspace, struct cnode *cnode){ ...@@ -288,8 +419,7 @@ void _lcd_delete_node (struct cspace *cspace, struct cnode *cnode){
} }
} else { } else {
// this was the last node // this was the last node
spin_unlock(&cnode->cdt_root->lock); last_node = true;
kmem_cache_free(cspace->cdt_root_cache, cnode->cdt_root);
cnode->cdt_root = NULL;
} }
} return last_node;
\ No newline at end of file }
\ No newline at end of file
...@@ -14,14 +14,12 @@ int __init api_init(void) ...@@ -14,14 +14,12 @@ int __init api_init(void)
{ {
bool res = true; bool res = true;
printk(KERN_ERR "lcd cspace entering module"); printk(KERN_ERR "lcd cspace entering module");
res = test_insert(); res = begintests();
if (res == false) { if (res == false) {
printk(KERN_ERR "lcd_cap_insert failed"); printk(KERN_ERR "tests failed");
} else { } else {
printk(KERN_ERR "lcd_cap_insert succeeded"); printk(KERN_ERR "tests succeeded");
test_delete();
} }
return 0; return 0;
} }
......
#include "test.h" #include "test.h"
#define TEST_PASSED true
#define TEST_FAILED false
int test_cap_count = 0; int test_cap_count = 0, test_cap_grant_count = 0;
struct cspace test_cspace; struct cspace test_cspace, test_cspace_grant;
int test_max_cap = 4 * MAX_CAP_SLOTS; int test_max_cap = 4 * MAX_CAP_SLOTS;
capability_t arr[4 * MAX_CAP_SLOTS] = {0}; capability_t arr[4 * MAX_CAP_SLOTS] = {0};
capability_t arr_grant[4 * MAX_CAP_SLOTS] = {0};
bool begintests(void) {
bool res;
lcd_init_cspace(&test_cspace);
lcd_init_cspace(&test_cspace_grant);
res = test_insert();
if (res == TEST_FAILED) {
printk(KERN_ERR "lcd_cap_test test_insert() failed\n");
return false;
} else {
printk(KERN_INFO "lcd_cap_test test_insert() Succeeded\n");
}
res = test_grant();
if (res == TEST_FAILED) {
printk(KERN_ERR "lcd_cap_test test_grant() failed\n");
return false;
} else {
printk(KERN_INFO "lcd_cap_test test_grant() Succeeded\n");
}
test_delete();
return true;
}
bool test_insert(void) { bool test_insert(void) {
capability_t cap; capability_t cap;
int i = 0; int i = 0;
int res = 0; int res = 0;
lcd_init_cspace(&test_cspace);
for (; i < test_max_cap; i++) { for (; i < test_max_cap; i++) {
if (lcd_alloc_cap(&(test_cspace.cap_cache), &cap) == 0) { if (lcd_alloc_cap(&(test_cspace.cap_cache), &cap) == 0) {
printk(KERN_ERR "lcd_cap_test got capability %llu", cap);
arr[test_cap_count++] = cap;
res = lcd_cap_insert(&test_cspace, cap, &test_max_cap, LCD_CAP_TYPE_SYNC_EP); res = lcd_cap_insert(&test_cspace, cap, &test_max_cap, LCD_CAP_TYPE_SYNC_EP);
if (res != 0) { if (res != 0) {
printk(KERN_ERR "lcd_cap_test insert failed for capability # %llu\n", cap);
break; break;
} else {
arr[test_cap_count++] = cap;
printk(KERN_INFO "lcd_cap_test insert succeeded for capability # %llu\n", cap);
} }
} else {
printk(KERN_ERR "lcd_cap_test insert failed to allocate capability\n");
return false;
} }
} }
return (res==0); return (res==0);
} }
bool test_grant(void) {
int i = 0;
int res;
capability_t capsrc, capdst;
for (; i < test_cap_count; i++) {
if (lcd_alloc_cap(&(test_cspace_grant.cap_cache), &capdst) == 0) {
capsrc = arr[i];
res = lcd_cap_grant(&test_cspace, capsrc, &(test_cspace_grant), capdst);
if (res == 0) {
arr_grant[test_cap_grant_count++] = capdst;
printk(KERN_INFO "lcd_cap_test grant capability # %llu to %llu succeeded\n", capsrc, capdst);
} else {
printk(KERN_ERR "lcd_cap_test grant capability # %llu to %llu failed\n", capsrc, capdst);
return false;
}
} else {
printk(KERN_ERR "lcd_cap_test grant failed to allcoate capability\n");
return false;
}
}
return true;
}
void test_delete(void) { void test_delete(void) {
int i = 0; int i = 0;
for (; i < test_cap_count; i++) { for (; i < test_cap_count; i++) {
lcd_cap_delete(&test_cspace, arr[i]); lcd_cap_delete(&test_cspace, arr[i]);
printk(KERN_INFO "lcd_cap_test deleted original capability # %llu\n", arr[i]);
} }
test_cap_count = 0; test_cap_count = 0;
for (i = 0; i < test_cap_grant_count; i++) {
lcd_cap_delete(&test_cspace_grant, arr_grant[i]);
printk(KERN_INFO "lcd_cap_test deleted granted capability # %llu\n", arr_grant[i]);
}
test_cap_grant_count = 0;
} }
\ No newline at end of file
...@@ -5,4 +5,7 @@ extern int lcd_cap_insert(struct cspace *cspace, capability_t cap, ...@@ -5,4 +5,7 @@ extern int lcd_cap_insert(struct cspace *cspace, capability_t cap,
void *object, enum lcd_cap_type type); void *object, enum lcd_cap_type type);
extern void lcd_cap_delete(struct cspace *cspace, capability_t cap); extern void lcd_cap_delete(struct cspace *cspace, capability_t cap);
bool test_insert(void); bool test_insert(void);
void test_delete(void); bool test_grant(void);
\ No newline at end of file void test_delete(void);
bool begintests(void);
\ No newline at end of file
...@@ -72,13 +72,13 @@ struct cspace { ...@@ -72,13 +72,13 @@ struct cspace {
}; };
bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId); bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId);
void _lcd_delete_node (struct cspace *cspace, struct cnode *cnode); bool _lcd_delete_node (struct cspace *cspace, struct cnode *cnode);
int lcd_cap_init_cspace(struct cspace *cspace); int lcd_cap_init_cspace(struct cspace *cspace);
struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool alloc); struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool alloc);
int lcd_cap_insert(struct cspace *cspace, capability_t cap, int lcd_cap_insert(struct cspace *cspace, capability_t cap,
void *object, enum lcd_cap_type type); void *object, enum lcd_cap_type type);
void lcd_cap_delete(struct cspace *cspace, capability_t cap); void lcd_cap_delete(struct cspace *cspace, capability_t cap);
//int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *cspacedst, capability_t capdst); int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *cspacedst, capability_t capdst);
#endif #endif
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