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

Adding cspace initialization to INIT_TASK macro



Conflicts:
	include/linux/init_task.h
	include/linux/sched.h
Resolved-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent c173727c
......@@ -246,6 +246,7 @@ extern struct task_group root_task_group;
}, \
.thread_group = LIST_HEAD_INIT(tsk.thread_group), \
.thread_node = LIST_HEAD_INIT(init_signals.thread_head), \
.cspace = NULL, \
INIT_IDS \
INIT_PERF_EVENTS(tsk) \
INIT_TRACE_IRQFLAGS \
......
......@@ -1463,7 +1463,7 @@ struct task_struct {
atomic_t usage;
unsigned int flags; /* per process flags, defined below */
unsigned int ptrace;
void *cspace;
#ifdef CONFIG_SMP
struct llist_node wake_entry;
int on_cpu;
......
......@@ -5,6 +5,7 @@
#define MODULE
#include "capability.h"
#include <net/irda/parameters.h>
int init_module(void)
{
......@@ -64,7 +65,7 @@ struct cte * lcd_reserve_cap_slot(struct cte *cnode, cap_id *cid, int free_slot)
ASSERT(node[free_slot].ctetype == lcd_type_free, "Free List is corrupted\n");
// a valid empty slot
node[0].slot.next_free_cap_slot = node[free_slot].slot.next_free_cap_slot;
lcd_set_level_bits(cnode, cid, free_slot);
lcd_set_bits_at_level(cnode, cid, free_slot);
return &node[free_slot];
}
......@@ -142,7 +143,7 @@ cap_id lcd_lookup_free_slot(struct cap_space *cspace, struct cte **cap)
node[free_cnode_slot].ctetype = lcd_type_cnode;
lcd_initialize_freelist(node[free_cnode_slot].cnode.table, false);
node[free_cnode_slot].cnode.table_level = cnode->cnode.table_level + 1;
lcd_set_level_bits(cnode, &cid, free_cnode_slot);
lcd_set_bits_at_level(cnode, &cid, free_cnode_slot);
node[free_cnode_slot].cnode.cnode_id = cid;
cnode = &node[free_cnode_slot];
......@@ -214,20 +215,20 @@ void lcd_update_cdt(void *ptcb)
struct task_struct *tcb = ptcb;
struct cte *cnode, *node;
struct kfifo cnode_q;
struct cap_space *tcb_cspace;
bool cspace_locked;
int i = 0;
if (tcb == NULL)
return;
tcb_cspace = tcb->cspace;
// lock the cspace.
if (down_interruptible(&(tcb->cspace->sem_cspace)))
if (down_interruptible(&(tcb_cspace->sem_cspace)))
{
ASSERT(false, "lcd_update_cdt: Signal interrupted lock, CDT will be corrupted\n");
return;
}
cspace_locked = true;
cnode = &(tcb->cspace->root_cnode);
cnode = &(tcb_cspace->root_cnode);
if (cnode == NULL)
goto safe_return;
......@@ -246,7 +247,7 @@ void lcd_update_cdt(void *ptcb)
loop:
if (!cspace_locked)
{
if (down_interruptible(&(tcb->cspace->sem_cspace)))
if (down_interruptible(&(tcb_cspace->sem_cspace)))
{
ASSERT(false, "lcd_update_cdt: Signal interrupted lock, CDT will be corrupted\n");
kfifo_free(&cnode_q);
......@@ -299,7 +300,7 @@ loop:
if (p_cdt != NULL)
up(&(p_cdt->cspace->sem_cspace));
parent_lock_acquired = false;
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
cspace_locked = false;
goto loop;
}
......@@ -307,7 +308,7 @@ loop:
else
{
// failure to acquire parent lock
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
cspace_locked = false;
goto loop;
}
......@@ -327,7 +328,7 @@ loop:
} // while !kfifo_is_empty()
safe_return:
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
kfifo_free(&cnode_q);
return;
}
......@@ -398,11 +399,25 @@ uint32_t lcd_cap_delete_internal(struct cte *cap_cte)
return 0;
}
struct cap_space * lcd_create_cspace()
struct cap_space * lcd_create_cspace(void *objects[], lcd_cap_rights rights[])
{
struct cap_space *cspace = vmalloc(sizeof(struct cap_space));
int i;
struct cap_derivation_tree *cdtnode;
struct task_struct *tcb = objects[LCD_CapInitThreadTCB];
struct cap_space *cspace = kmalloc(sizeof(struct cap_space), GFP_KERNEL);
SAFE_EXIT_IF_ALLOC_FAILED(cspace, alloc_failure);
if (tcb == NULL)
{
ASSERT(false, "lcd_create_cspace: LCD_CapInitThreadTCB ");
}
if ((sizeof(objects)/sizeof(objects[0]) != LCD_CapFirstFreeSlot) ||
(sizeof(rights)/sizeof(rights[0]) != LCD_CapFirstFreeSlot))
{
ASSERT(false, "lcd_create_cspace: Invalid inputs, size of arrays should be equal to LCD_CapFirstFreeSlot\n");
return NULL;
}
// initialize semaphore
sema_init(&(cspace->sem_cspace), 1);
......@@ -412,9 +427,28 @@ struct cap_space * lcd_create_cspace()
cspace->root_cnode.cnode.table_level = 0;
cspace->root_cnode.cnode.table = kmalloc(PAGE_SIZE, GFP_KERNEL);
SAFE_EXIT_IF_ALLOC_FAILED(cspace->root_cnode.cnode.table, alloc_failure);
// Get the intitial capabilities into the cspace.
for (i = 0; i < LCD_CapFirstFreeSlot; i++)
{
if (objects[i] == NULL)
continue;
cdtnode = kmalloc(sizeof(struct cap_derivation_tree), GFP_KERNEL);
SAFE_EXIT_IF_ALLOC_FAILED(cdtnode, alloc_failure);
cspace->root_cnode.cnode.table[i].cap.hobject = objects[i];
cspace->root_cnode.cnode.table[i].cap.crights = rights[i];
cdtnode->cap = &(cspace->root_cnode.cnode.table[i]);
cdtnode->cspace = cspace;
cdtnode->parent_ptr = NULL;
cdtnode->child_ptr = NULL;
cdtnode->next = NULL;
cdtnode->prev = NULL;
cspace->root_cnode.cnode.table[i].cap.cdt_node = cdtnode;
}
// initialize the free list
lcd_initialize_freelist(cspace->root_cnode.cnode.table, true);
goto success;
alloc_failure:
......@@ -422,14 +456,22 @@ alloc_failure:
{
if (cspace->root_cnode.cnode.table)
{
for (i = 1; i < LCD_CapFirstFreeSlot; i++)
{
if (cspace->root_cnode.cnode.table[i].cap.cdt_node != NULL)
{
kfree(cspace->root_cnode.cnode.table[i].cap.cdt_node);
}
}
kfree(cspace->root_cnode.cnode.table);
cspace->root_cnode.cnode.table = NULL;
}
vfree(cspace);
kfree(cspace);
cspace = NULL;
}
success:
tcb->cspace = cspace;
return cspace;
}
......@@ -491,6 +533,7 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
{
cap_id cid = 0;
struct task_struct *stcb, *dtcb;
struct cap_space *stcb_cspace, *dtcb_cspace;
struct cte *src_cte = NULL, *dst_cte = NULL;
bool done = false;
struct cap_derivation_tree *dst_cdt_node = kmalloc(sizeof(struct cap_derivation_tree), GFP_KERNEL);
......@@ -508,19 +551,20 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
stcb = (struct task_struct *)src_tcb;
dtcb = (struct task_struct *)dst_tcb;
stcb_cspace = stcb->cspace;
dtcb_cspace = dtcb->cspace;
while (!done)
{
// Lock source cspace.
if (down_trylock(&(stcb->cspace->sem_cspace)) == 0)
if (down_trylock(&(stcb_cspace->sem_cspace)) == 0)
{
// if (down_trylock() == 0) lock dst cspace
if (down_trylock(&(dtcb->cspace->sem_cspace)) == 0)
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);
src_cte = lcd_lookup_capability(stcb_cspace, src_cid);
// get a free slot in destination.
cid = lcd_lookup_free_slot(dtcb->cspace, &dst_cte);
cid = lcd_lookup_free_slot(dtcb_cspace, &dst_cte);
if (cid != 0 && src_cte != NULL && dst_cte != NULL)
{
struct cap_derivation_tree *src_cdt_node = src_cte->cap.cdt_node;
......@@ -533,7 +577,7 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
dst_cte->cap.cdt_node = dst_cdt_node;
src_cdt_node->child_ptr = dst_cdt_node;
dst_cdt_node->cspace = dtcb->cspace;
dst_cdt_node->cspace = dtcb_cspace;
dst_cdt_node->parent_ptr = src_cdt_node;
dst_cdt_node->child_ptr = NULL;
dst_cdt_node->next = cdtnode;
......@@ -550,10 +594,10 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
ASSERT(false, "Source capability not found or no free slot in destination");
}
// release lock on dst cspace.
up(&(dtcb->cspace->sem_cspace));
up(&(dtcb_cspace->sem_cspace));
}
// release lock on source cspace.
up(&(stcb->cspace->sem_cspace));
up(&(stcb_cspace->sem_cspace));
}
if (!done)
msleep_interruptible(1);
......@@ -566,22 +610,24 @@ uint32_t lcd_cap_delete(void * ptcb, cap_id cid)
int ret;
struct cte *cap_cte;
struct task_struct *tcb = ptcb;
struct cap_space *tcb_cspace;
if (ptcb == NULL || cid == 0)
return -1;
if (down_interruptible(&(tcb->cspace->sem_cspace)))
tcb_cspace = tcb->cspace;
if (down_interruptible(&(tcb_cspace->sem_cspace)))
{
ASSERT(false, "lcd_cap_delete: Failed to acquire lock, cannot delete capability\n");
return -1;
}
cap_cte = lcd_lookup_capability(tcb->cspace, cid);
cap_cte = lcd_lookup_capability(tcb_cspace, cid);
if (cap_cte == NULL || cap_cte->cap.cdt_node == NULL)
{
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
return 0;
}
ret = lcd_cap_delete_internal(cap_cte);
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
return ret;
}
......@@ -589,25 +635,27 @@ uint32_t lcd_cap_revoke(void * ptcb, cap_id cid)
{
struct task_struct *tcb = ptcb;
struct cap_derivation_tree *cdt;
struct cap_space *tcb_cspace;
struct kfifo cdt_q;
struct cte *cap;
if (ptcb == NULL || cid == 0)
return -1;
tcb_cspace = tcb->cspace;
if (kfifo_alloc(&cdt_q, sizeof(struct cap_derivation_tree) * 512, GFP_KERNEL) != 0)
{
ASSERT(false, "lcd_cap_revoke: Failed to allocate kfifo\n");
return -1;
}
if (down_interruptible(&(tcb->cspace->sem_cspace)))
if (down_interruptible(&(tcb_cspace->sem_cspace)))
{
ASSERT(false, "lcd_cap_revoke: Signal interrupted cspace lock, CDT will be corrupted\n");
kfifo_free(&cdt_q);
return -1;
}
cap = lcd_lookup_capability(tcb->cspace, cid);
up(&(tcb->cspace->sem_cspace));
cap = lcd_lookup_capability(tcb_cspace, cid);
up(&(tcb_cspace->sem_cspace));
if (cap == NULL)
{
......@@ -654,9 +702,11 @@ void lcd_destroy_cspace(void *ptcb)
struct task_struct *tcb = ptcb;
struct cte *node, level_separator;
struct kfifo node_q;
struct cap_space *tcb_cspace;
int depth_count = 0;
if (tcb == NULL)
return;
tcb_cspace = tcb->cspace;
// patch the cdt
lcd_update_cdt(tcb);
......@@ -667,13 +717,13 @@ void lcd_destroy_cspace(void *ptcb)
return;
}
level_separator.ctetype = lcd_type_separator;
if (down_interruptible(&(tcb->cspace->sem_cspace)))
if (down_interruptible(&(tcb_cspace->sem_cspace)))
{
ASSERT(false, "lcd_update_cdt: Signal interrupted lock, CDT will be corrupted\n");
kfifo_free(&node_q);
return;
}
node = tcb->cspace->root_cnode.cnode.table;
node = tcb_cspace->root_cnode.cnode.table;
if (node != NULL)
kfifo_in(&node_q, node, 1);
kfifo_in(&node_q, &level_separator, 1);
......@@ -704,10 +754,10 @@ void lcd_destroy_cspace(void *ptcb)
}
kfree(node);
}
tcb->cspace->root_cnode.cnode.table = NULL;
tcb->cspace->root_cnode.ctetype = lcd_type_free;
up(&(tcb->cspace->sem_cspace));
kfree(tcb->cspace);
tcb_cspace->root_cnode.cnode.table = NULL;
tcb_cspace->root_cnode.ctetype = lcd_type_free;
up(&(tcb_cspace->sem_cspace));
kfree(tcb_cspace);
tcb->cspace = NULL;
kfifo_free(&node_q);
}
......@@ -716,18 +766,20 @@ uint32_t lcd_get_cap_rights(void * ptcb, cap_id cid, lcd_cap_rights *rights)
{
struct task_struct *tcb = ptcb;
struct cte *cap;
struct cap_space *tcb_cspace;
if (tcb == NULL || tcb->cspace == NULL || cid == 0 || rights == NULL)
return -1;
if (down_interruptible(&(tcb->cspace->sem_cspace)))
tcb_cspace = tcb->cspace;
if (down_interruptible(&(tcb_cspace->sem_cspace)))
return -1;
cap = lcd_lookup_capability(tcb->cspace, cid);
cap = lcd_lookup_capability(tcb_cspace, cid);
if (cap == NULL || cap->ctetype != lcd_type_capability)
{
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
return -1;
}
*rights = cap->cap.crights;
up(&(tcb->cspace->sem_cspace));
up(&(tcb_cspace->sem_cspace));
return 0;
}
\ No newline at end of file
......@@ -13,7 +13,6 @@
#include <linux/delay.h>
#include <linux/kfifo.h>
#include <asm/page.h>
#include "../../../SeL4/seL4-release-1.2/code/apps/wombat-vmlinux/linux-2.6.38.1/arch/arm/nwfpe/ARM-gcc.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("FLUX-LAB University of Utah");
......@@ -57,11 +56,10 @@ enum __lcd_cap_type
enum {
LCD_CapNull = 0, /* null cap */
LCD_CapInitThreadTCB = 1, /* initial thread's TCB cap */
LCD_CapInitThreadCNode = 2, /* initial thread's root CNode cap */
LCD_CapInitThreadPD = 3, /* initial thread' page directory */
LCD_CapIRQControl = 4, /* global IRQ controller */
LCD_CapInitThreadIPCBuffer = 5, /* initial thread's IPC buffer frame cap */
LCD_CapFirstFreeSlot = 6
LCD_CapInitThreadPD = 2, /* initial thread' page directory */
LCD_CapIRQControl = 3, /* global IRQ controller */
LCD_CapInitThreadIPCBuffer = 4, /* initial thread's IPC buffer frame cap */
LCD_CapFirstFreeSlot = 5
};
......@@ -134,7 +132,7 @@ struct cap_space
/* Helper Functions */
static inline int get_bits_at_level(cap_id id, int level)
static inline int lcd_get_bits_at_level(cap_id id, int level)
{
int bits = 0;
id = id << ((MAX_DEPTH - level - 1) * CNODE_INDEX_BITS);
......@@ -143,7 +141,7 @@ static inline int get_bits_at_level(cap_id id, int level)
return bits;
}
static inline void clear_bits_at_level(cap_id *id, int level)
static inline void lcd_clear_bits_at_level(cap_id *id, int level)
{
cap_id mask = (~0);
// clear all higher order bits.
......@@ -156,42 +154,50 @@ static inline void clear_bits_at_level(cap_id *id, int level)
*id = (*id) & mask;
}
static inline void lcd_set_level_bits(struct cte *cnode, cap_id *cid, int free_slot)
static inline void lcd_set_bits_at_level(struct cte *cnode, cap_id *cid, int free_slot)
{
int level = cnode->cnode.table_level;
cap_id id = free_slot;
*cid = cnode->cnode.cnode_id;
clear_bits_at_level(cid, level);
lcd_clear_bits_at_level(cid, level);
id = id << (level * CNODE_INDEX_BITS);
*cid = *cid | id;
}
static struct cte * lcd_reserve_cap_slot(struct cte *cnode, cap_id *cid, int free_slot);
struct cte * lcd_reserve_cap_slot(struct cte *cnode, cap_id *cid, int free_slot);
// initializes the free slots available in the cnode structure.
static void lcd_initialize_freelist(struct cte *cnode, bool bFirstCNode);
void lcd_initialize_freelist(struct cte *cnode, 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.
static cap_id lcd_lookup_free_slot(struct cap_space *cspace, struct cte **cap);
cap_id lcd_lookup_free_slot(struct cap_space *cspace, struct cte **cap);
static struct cte * lcd_lookup_capability(struct cap_space *cspace, cap_id cid);
struct cte * lcd_lookup_capability(struct cap_space *cspace, cap_id cid);
static void lcd_update_cdt(void *ptcb);
void lcd_update_cdt(void *ptcb);
static uint32_t lcd_cap_delete_internal(struct cte *cap_cte);
uint32_t lcd_cap_delete_internal(struct cte *cap_cte);
/* External Interface */
// creates a cspace for a thread. should be called during lcd creation.
// initially the cspace contains just three capabilities:
// one for its TCB
// one for its cspace
// one for the endpoint.
// expects the following objects as input with the rights for those objects:
// ****(LCD_CapInitThreadTCB is compulsory)
// Objects Index within input array Comments
// LCD_CapNull 0 Should be a NULL entry in objects array
// ****LCD_CapInitThreadTCB 1 Pointer to task_struct of thread.
// LCD_CapInitThreadPD 2 Pointer to the page directory of process.
// LCD_CapIRQControl 3 ?? will be used later.
// LCD_CapInitThreadIPCBuffer 4 Pointer to the IPC buffer which will be used.
// total number of object pointers expected is equal to LCD_CapFirstFreeSlot.
// Put a NULL pointer for entries which the thread is not expected to have.
// e.g. if the thread does not need an IPC buffer then objects[4] should be NULL.
// the returned value goes into the TCB of the caller.
struct cap_space * lcd_create_cspace(void);
struct cap_space * lcd_create_cspace(void *objects[], lcd_cap_rights rights[]);
// creates a new capability, inserts it into cspace of caller and
// returns the capability identifier.
......
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