Commit f9a246cc authored by Muktesh Khole's avatar Muktesh Khole Committed by Vikram Narayanan
Browse files

Capability Module

parent 37074480
#undef __KERNEL__
#define __KERNEL__
......@@ -18,43 +17,78 @@ void cleanup_module(void)
printk(KERN_INFO "Cleaning up LCD Module\n");
}
void initialize_freelist(cte *cnode, int size, bool bFirstCNode=false)
void lcd_initialize_freelist(struct cte *cnode, int size, bool bFirstCNode)
{
int startid = 1;
int i = startid;
if (cnode == NULL)
return;
int max_slots = (size / sizeof(cte));
int startid = 1;
if (bFirstCNode)
{
startid = LCD_CapFirstFreeSlot;
}
cnode[0].ctetype = lcd_type_free;
cnode[0].next_free_slot = startid;
cnode[startid].ctetype = lcd_type_free;
for (int i = startid; i < max_slots-1; i++)
i = startid;
for (; i < MAX_SLOTS - 1; i++)
{
cnode[i].next_free_slot = i + 1;
cnode[i+1].ctetype = lcd_type_free;
}
cnode[i].next_free_slot = 0;
}
// caller responsible for locking cspace.
// free slot will be booked for the caller.
// ie. it will not longer be free once this function returns it.
cap_id lcd_lookup_free_slot(struct cap_space *cspace, struct cte **cap)
{
cap_id cid = 0;
struct cte *cnode;
bool found = false;
if (cspace == NULL)
return 0;
cnode = cspace->root_cnode;
while (!found)
{
int nxt = cnode[0].next_free_slot;
// check if only one free slot is available
if (cnode[nxt].next_free_slot == 0)
{
// only one free slot is available, allocate a new cnode and set free_cnode
}
}
return cid;
}
cap_space * lcd_create_cspace()
struct cte * lcd_lookup_capability(struct cap_space *cspace, cap_id cid)
{
cap_space *cspace = (cap_space *)vmalloc(sizeof(cap_space));
struct cte *cap;
return cap;
}
struct cap_space * lcd_create_cspace()
{
struct cap_space *cspace = vmalloc(sizeof(struct cap_space));
SAFE_EXIT_IF_ALLOC_FAILED(cspace, alloc_failure);
// initialize semaphore
sema_init(&(cspace->sem_cspace), 1);
// allocate memory for the first cnode.
cspace->root_cnode = (cte *)kmalloc(PAGE_SIZE, GFP_KERNEL);
cspace->root_cnode = kmalloc(PAGE_SIZE, GFP_KERNEL);
SAFE_EXIT_IF_ALLOC_FAILED(cspace->root_cnode, alloc_failure);
// initialize the free list
initialize_freelist(cspace->root_cnode, PAGE_SIZE, true);
lcd_initialize_freelist(cspace->root_cnode, PAGE_SIZE, true);
goto success;
......@@ -78,12 +112,81 @@ success:
cap_id lcd_create_cap(void * ptcb, void * hobject, lcd_cap_rights crights)
{
struct task_struct *tcb = (struct task_struct *)ptcb;
struct cap_space *cspace;
struct cte *cap;
cap_id cid;
if (ptcb == NULL)
return 0;
cspace = tcb->cspace;
if (cspace == NULL || cspace->root_cnode == NULL)
return 0;
//1. lock the cspace.
//2. walk the cspace to find empty slots.
// if only one empty slot left in cnode, create a new cnode, initialize its free list.
//3. Get the first free slot, set its type to capability.
// set its hObject, and rights.
//4. return the cap_id within this cspace.
down_interruptible(&cspace->sem_cspace);
cid = lcd_lookup_free_slot(cspace, &cap);
cap->ctetype = lcd_type_capability;
cap->cap.crights = crights;
cap->cap.hobject = hobject;
cap->cap.cdt_list = NULL;
up(&(cspace->sem_cspace));
return cid;
}
cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_rights crights)
{
cap_id cid = 0;
struct task_struct *stcb, *dtcb;
struct cte *src_cte = NULL, *dst_cte = NULL;
bool done = false;
if (src_tcb == NULL || dst_tcb == NULL || src_cid <= 0)
return 0;
stcb = (struct task_struct *)src_tcb;
dtcb = (struct task_struct *)dst_tcb;
while (!done)
{
// if (down_trylock() == 0) Lock source cspace.
if (down_trylock(stcb->cspace->sem_cspace) == 0)
{
// if (down_trylock() == 0) lock dst cspace
if (down_trylock(dtcb->cspace->sem_cspace) == 0)
{
// Lookup the source TCB and get a pointer to capability.
src_cte = lcd_lookup_capability(stcb->cspace, src_cid);
// get a free slot in destination.
cid = lcd_lookup_free_slot(dtcb->cspace, &dst_cte);
if (cid != 0){
struct cap_derivation_list *cdt_node;
// add the capability to destination.
dst_cte->ctetype = lcd_type_capability;
dst_cte->cap.crights = crights;
dst_cte->cap.hobject = src_cte->cap.hobject;
dst_cte->cap.cdt_list = NULL;
// update the CDT of source
cdt_node = kmalloc(sizeof(struct cap_derivation_list), GFP_KERNEL);
if (cdt_node != NULL){
cdt_node->next = src_cte->cap.cdt_list;
src_cte->cap.cdt_list = cdt_node;
cdt_node->remote_cid = src_cid;
cdt_node->remote_TCB = src_tcb;
}
else{
ASSERT(false, "cdt_node allocation failed");
}
done = true;
}
// release lock on dst cspace.
up(dtcb->cspace->sem_cspace);
}
// release lock on source cspace.
up(stcb->cspace->sem_cspace);
}
if (!done)
msleep_interruptible(1);
}
return cid;
}
\ No newline at end of file
#ifndef __LCD_CAPABILITY_H__
#define __LCD_CAPABILITY_H__
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab_def.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/log2.h>
#include <linux/delay.h>
#include <asm/page.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("FLUX-LAB University of Utah");
#define LCD_CAPABILITY
#define MAX_SLOTS (PAGE_SIZE/sizeof(struct cte))
#define CNODE_INDEX_BITS (ilog2(MAX_SLOTS))
#define SAFE_EXIT_IF_ALLOC_FAILED(ptr, label) \
if (ptr == NULL) \
......@@ -22,10 +27,16 @@ if (ptr == NULL) \
goto label; \
} \
#define ASSERT(condition, expr) \
if(!(condition)) { \
printk("\nAssertion Failed at: %d\n",__LINE__); \
panic(#expr); \
}
typedef enum _lcd_cap_type
{
lcd_type_free,
lcd_type_untyped,
lcd_type_capability,
lcd_type_cnode,
lcd_type_endpoint
}lcd_cap_type;
......@@ -42,7 +53,7 @@ enum {
};
typedef uint32_t lcd_cnode; // a pointer to the cnode
typedef uint32_t cap_id ; // a locally unique identifier (address within cspace)
typedef uint64_t cap_id ; // a locally unique identifier (address within cspace)
typedef uint32_t lcd_cnode_entry; // a pointer to an entry within a cnode
typedef uint64_t lcd_tcb; // a pointer/handle to the thread contrl block
typedef uint16_t lcd_cap_rights; // holds the rights associated with a capability.
......@@ -58,70 +69,64 @@ typedef uint16_t lcd_cap_rights; // holds the rights associated with a capabil
#define CAPRIGHTS_RWX (CAPRIGHTS_RW | CAPRIGHTS_EXECUTE)
#define CAPRIGHTS_NORIGHTS 0
typedef struct _cap_derivation_list
struct cap_derivation_list
{
void *remote_TCB; // reference to the thread which was granted this capability
cap_id remote_cid; // address in the remote threads capability space where this
// capability is stored.
struct _cap_derivation_list *next;
}cap_derivation_list;
struct cap_derivation_list *next;
};
typedef struct _capability
struct capability
{
cap_id cid; // locally unique to each thread
}capability;
};
typedef struct _capability_internal
struct capability_internal
{
void *hobject; // a pointer to a kernel object
struct cap_derivation_list *cdt_list; // list of domain ids to whom this capability is granted
lcd_cap_rights crights; // specifies the rights the domain has over this capability
}capability_internal;
};
struct _cap_node;
struct cte;
struct cap_node
{
struct cte *cap_entry; /* may point to another cnode or to a capability */
};
typedef struct _cte // capability table entry
struct cte // capability table entry
{
lcd_cap_type ctetype;
union{
struct _cap_node *cnode;
capability_internal *cap;
struct cap_node cnode;
struct capability_internal cap;
int next_free_slot;
};
}cte;
};
typedef struct _cap_node
{
struct _guard
{
int32_t guard_bits:27; // actual guard bits
int32_t guard_size:5; // number of valid bits in guard_bits
}guard;
int max_slots;
cte *cap_entry; /* may point to another cnode or to a capability */
}cap_node;
typedef struct _cap_space
struct cap_space
{
struct cte *root_cnode;
struct semaphore sem_cspace;
}cap_space;
};
/* Helper Functions */
// initializes the free slots available in the cnode structure.
void initialize_freelist(cap_node *cnode, int size, bool bFirstCNode=false);
void lcd_initialize_freelist(struct cte *cnode, int size, bool bFirstCNode);
// will be used to search for the cnode which has a free slot available.
// if no such cnode exists will make a call to create lcd_create_cnode to create an
// empty cnode.
cap_id lcd_lookup_free_slot();
cap_id lcd_lookup_free_slot(struct cap_space *cspace, struct cte **cap);
struct cte * lcd_lookup_capability(struct cap_space *cspace, cap_id cid);
// will be used to allocate memory for a cnode.
cap_node * lcd_create_cnode(uint16_t size);
struct cap_node * lcd_create_cnode(uint16_t size);
// will be used to de-allocate memory of a cnode.
uint32_t lcd_delete_cnode(cap_id cid);
......@@ -136,7 +141,7 @@ uint32_t lcd_delete_cnode(cap_id cid);
// one for its cspace
// one for the endpoint.
// the returned value goes into the TCB of the caller.
cap_space * lcd_create_cspace();
struct cap_space * lcd_create_cspace(void);
// creates a new capability, inserts it into cspace of caller and
// returns the capability identifier.
......@@ -147,7 +152,7 @@ cap_id lcd_create_cap(void * ptcb, void * hobject, lcd_cap_rights crights);
// returns the address of the capability within the cspace of the receiver thread.
// a logical AND of the crights and rights on the capability being granted will decide the
// final rights the granted capability will have.
cap_id lcd_cap_grant(void * dst_tcb, cap_id src_cid, lcd_cap_rights crights);
cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_rights crights);
// will be called to delete a particular capability in the calling threads
// cspace. threads have right to delete capabilities in their own cspace.
......
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