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

Dummy Commit

parent 9a4c14f4
#undef __KERNEL__
#define __KERNEL__
#undef MODULE
#define MODULE
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/slab.h> // included for kmalloc
#include <linux/kthread.h>
#include <linux/sched.h>
#include "cap.h"
struct task_struct *capTask;
struct cte initCte; /* TODO: Copy this cte to TCB */
///////////////////////// Test Program ///////////////////////////////////////////////////////////////////////////////
int thread_fn(void* abc)
{
/* TODO: CSpace for the first thread should be created before it runs */
LCD_Create_CSpace();
/* CSpace test cases */
/* Addr is 0x0 */
LCD_Untyped_Retype(0, ObjType_EndPoint, 0, LCD_CapInitThreadCNode, 0, 0, 0, 0);
print_cnode(&initCte, 0);
/* Addr is 0x400000000 */
LCD_Untyped_Retype(0, ObjType_CNode, 2, LCD_CapInitThreadCNode, 0, 0, 0x2, 0);
print_cnode(&initCte, 0);
/* Addr is 0x480000000 */
LCD_Untyped_Retype(0, ObjType_EndPoint, 0, LCD_CapInitThreadCNode, 0x40000000, 3, 0x1, 0);
print_cnode(&initCte, 0);
LCD_CNode_Search(LCD_CapInitThreadCNode, 0x40000000, 3);
LCD_CNode_Delete(LCD_CapInitThreadCNode, 0x48000000, 5);
print_cnode(&initCte, 0);
LCD_CNode_Delete(LCD_CapInitThreadCNode, 0x40000000, 3);
print_cnode(&initCte, 0);
LCD_CNode_Delete(LCD_CapInitThreadCNode, 0x00000000, 3);
print_cnode(&initCte, 0);
return 0;
}
static int __init hello_init(void)
{
printk(KERN_INFO "Hello world!\n");
capTask = kthread_run(thread_fn, NULL, "CapTest");
return 0; // Non-zero return means that the module couldn't be loaded.
}
static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
}
//////////////////////////External Interfaces////////////////////////////////////////////////////////////////////////////////
static int LCD_Create_CSpace(void)
{
/* Create CNode and put the capability to a slot in a TCB */
static struct capability *src_cap;
struct cte *threadInitCte= NULL;
uint32_t size_bits = 4;
printk(KERN_INFO "LCD_Create_CSpace\n");
/* Create CNode for internal use*/
src_cap = &(initCte.cap);
cnode_create_internal(src_cap, size_bits);
/* Create CNode for user */
threadInitCte= caps_locate_slot(initCte.cap.u.cnode.cnode, LCD_CapInitThreadCNode);
src_cap = &(threadInitCte->cap);
size_bits= 3;
cnode_create_internal(src_cap, size_bits);
printk(KERN_INFO "CSpace is created\n");
print_cnode(&initCte, 0);
return 0;
}
int LCD_Untyped_Retype(LCD_Untyped _service, LCD_Type objType, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects)
{
int returnVal = 0;
switch (objType)
{
case ObjType_CNode:
create_CNode(_service, size_bits, root, node_index, node_depth, node_offset, num_objects);
break;
case ObjType_EndPoint:
create_EndPoint(_service, size_bits, root, node_index, node_depth, node_offset, num_objects);
break;
default:
break;
}
return returnVal;
}
static void *LCD_CNode_Search(LCD_CNode _service, int node_index, int node_depth)
{
struct cte *tempCte = NULL;
struct cte *rootCte= NULL;
rootCte = caps_locate_slot(initCte.cap.u.cnode.cnode, _service);
caps_lookup_slot(&rootCte->cap, node_index, node_depth, 0, &tempCte, CAPRIGHTS_ALLRIGHTS);
/* free alloced memory */
switch(tempCte->cap.type)
{
case ObjType_CNode:
return (void*)tempCte->cap.u.cnode.cnode;
break;
case ObjType_EndPoint:
return NULL;
break;
default:
return NULL;
break;
}
return NULL;
}
static int LCD_CNode_Delete(LCD_CNode _service, int node_index, int node_depth)
{
struct cte *tempCte = NULL;
struct cte *rootCte= NULL;
rootCte = caps_locate_slot(initCte.cap.u.cnode.cnode, _service);
caps_lookup_slot(&rootCte->cap, node_index, node_depth, 0, &tempCte, CAPRIGHTS_ALLRIGHTS);
/* free alloced memory */
switch(tempCte->cap.type)
{
case ObjType_CNode:
kfree(tempCte->cap.u.cnode.cnode);
break;
case ObjType_EndPoint:
break;
default:
break;
}
memset(tempCte, 0, sizeof(struct cte));
return 0;
}
////////////////////////Internal Functions///////////////////////////////////////////////////////////////////////////////////////////////
int cnode_create_internal(struct capability *src_cap, int size_bits)
{
struct cte *objAddr;
objAddr = (struct cte*)kmalloc((1UL << size_bits)*sizeof(struct cte), GFP_KERNEL);
if (objAddr == 0)
{
printk(KERN_INFO "Fail to Alloc mem for initial CNode\n");
return 1;
}
memset(objAddr, 0, (1UL << size_bits)*sizeof(struct cte));
memset(src_cap, 0, sizeof(struct capability));
src_cap->type = ObjType_CNode;
src_cap->rights = CAPRIGHTS_ALLRIGHTS;
src_cap->u.cnode.cnode = objAddr;
src_cap->u.cnode.bits = size_bits;
src_cap->u.cnode.guard = 0;
src_cap->u.cnode.guard_size = 0;
return 0;
}
LCD_CPtr create_CNode(LCD_Untyped _service, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects)
{
/* Initialize the created capability */
static struct capability src_cap;
struct cte *tempCte = NULL;
struct cte *rootCte= NULL;
struct cte *objAddr;
memset(&src_cap, 0, sizeof(struct capability));
src_cap.type = ObjType_CNode;
src_cap.rights = CAPRIGHTS_ALLRIGHTS;
objAddr = (struct cte*)kmalloc((1UL << size_bits)*sizeof(struct cte), GFP_KERNEL);
memset(objAddr, 0, (1UL << size_bits)*sizeof(struct cte));
// Initialize type specific fields
src_cap.u.cnode.cnode = objAddr;
src_cap.u.cnode.bits = size_bits;
src_cap.u.cnode.guard = 0;
src_cap.u.cnode.guard_size = 0;
/* tempCte is pointing cnode*/
rootCte = caps_locate_slot(initCte.cap.u.cnode.cnode, root);
caps_lookup_slot (&rootCte->cap, node_index, node_depth, 0, &tempCte, CAPRIGHTS_ALLRIGHTS);
/* tempCte is pointing the first element in the cnode*/
tempCte = tempCte->cap.u.cnode.cnode;
/* tempCte is pointing the right element in the cnode*/
tempCte = caps_locate_slot(tempCte, node_offset);
memcpy(&tempCte->cap, &src_cap, sizeof(struct capability));
return 0;
}
LCD_CPtr create_EndPoint(LCD_Untyped _service, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects)
{
/* Initialize the created capability */
static struct capability src_cap;
struct cte *tempCte = NULL;
struct cte *rootCte= NULL;
struct cte *objAddr;
memset(&src_cap, 0, sizeof(struct capability));
src_cap.type = ObjType_EndPoint;
src_cap.rights = CAPRIGHTS_ALLRIGHTS;
objAddr = (struct cte*)kmalloc(100, GFP_KERNEL);
memset(objAddr, 0, 100);
/* tempCte is pointing cnode*/
rootCte = caps_locate_slot(initCte.cap.u.cnode.cnode, root);
caps_lookup_slot (&rootCte->cap, node_index, node_depth, 0, &tempCte, CAPRIGHTS_ALLRIGHTS);
/* tempCte is pointing the first element in the cnode*/
tempCte = tempCte->cap.u.cnode.cnode;
/* tempCte is pointing the right element in the cnode*/
tempCte = caps_locate_slot(tempCte, node_offset);
memcpy(&tempCte->cap, &src_cap, sizeof(struct capability));
return 0;
}
int caps_lookup_slot(struct capability *cnode_cap, LCD_CPtr cptr, uint8_t vbits, uint8_t resolved_bits, struct cte **ret, CapRights rights)
{
uint8_t bits_resolved;
LCD_CPtr cptr_guard;
size_t offset;
struct cte *next_slot;
int bitsleft;
// If vbit == 0, return root
if(vbits == 0) {
*ret = caps_locate_slot(initCte.cap.u.cnode.cnode, LCD_CapInitThreadCNode);
return 0;
}
printk("caps_lookup_slot: Cnode bits = %u, guard size = %u, valid bits = %u\n",
cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
vbits);
/* Can only resolve CNode type */
if (cnode_cap->type != ObjType_CNode) {
printk("caps_lookup_slot: Cap to lookup not of type CNode\n"
"cnode_cap->type = %u\n", cnode_cap->type);
return -1;
}
/* Apply rights to this CNode */
if ((cnode_cap->rights & rights) != rights) {
printk("caps_lookup_slot: Rights mismatch\n"
"Passed rights = %u, cnode_cap->rights = %u\n",
rights, cnode_cap->rights);
return -1;
}
/* Number of bits resolved by this cnode (bits + guard_size) */
bits_resolved = cnode_cap->u.cnode.bits +
cnode_cap->u.cnode.guard_size;
// If lookup exceeded expected depth then table is malformed
if (bits_resolved > vbits) {
printk("caps_lookup_slot: Lookup exceeded valid bits\n"
"Cnode bits = %u, guard size = %u, valid bits = %u\n",
cnode_cap->u.cnode.bits, cnode_cap->u.cnode.guard_size,
vbits);
return -1;
}
/* Guard-check (bit-mask of guard in cptr must match guard in cnode cap) */
cptr_guard = (cptr >> (vbits - cnode_cap->u.cnode.guard_size))
& MASK(cnode_cap->u.cnode.guard_size);
if (cptr_guard != cnode_cap->u.cnode.guard) {
printk("caps_lookup_slot: guard check failed\n");
return -1;
}
/* Locate capability in this cnode */
// Offset into the cnode
offset = (cptr >> (32 - resolved_bits - bits_resolved)) &
MASK(cnode_cap->u.cnode.bits);
// The capability at the offset
next_slot = caps_locate_slot(cnode_cap->u.cnode.cnode, offset);
// Do not return NULL type capability
if (next_slot->cap.type == ObjType_Null) {
return -1;
}
/* Number of bits left to resolve */
bitsleft = vbits - bits_resolved;
// If all bits have been resolved, return the capability
if(bitsleft == 0) {
*ret = next_slot;
return 0;
}
/* If next capability is not of type cnode, return it */
// XXX: Is this consistent?
if (next_slot->cap.type != ObjType_CNode) {
*ret = next_slot;
return 0;
}
/* Descend to next level */
return caps_lookup_slot(&next_slot->cap, cptr, bitsleft, bits_resolved+resolved_bits, ret, rights);
}
struct cte * caps_locate_slot(struct cte * topCte, size_t offset)
{
return (struct cte*)(topCte+ offset);
}
void print_cnode(struct cte * myCte, int depth)
{
struct capability * myCap;
struct capability * iterCap;
struct cte * iterCte;
int i = 0;
int j = 0;
int size = 0;
myCap = &myCte->cap;
if (depth == 0)
{
printk(KERN_INFO "=========print_code start=========\n");
}
if (myCap->type == ObjType_CNode)
{
size = myCap->u.cnode.bits;
size = (1UL<<size);
for (j = 0; j < depth; j++)
printk(" ");
printk("<CNode size: %d>\n", size);
for (i = 0 ; i < size; i++)
{
iterCte = caps_locate_slot(myCap->u.cnode.cnode, i);
iterCap = &iterCte->cap;
for (j = 0; j < depth; j++)
printk(" ");
printk("Depth: %d::: Type: %d\n", depth+1, iterCap->type);
if (iterCap->type == ObjType_CNode)
{
print_cnode(iterCte, depth+1);
}
}
}
if (depth == 0)
{
printk(KERN_INFO "==========print_code end==========\n");
}
}
module_init(hello_init);
module_exit(hello_cleanup);
typedef enum {ObjType_Untyped, ObjType_CNode=777, ObjType_EndPoint=888, ObjType_Null} LCD_Type;
/* caps with fixed slot potitions in the root CNode */
enum {
LCD_CapNull = 0, /* null cap */
LCD_CapInitThreadTCB = 1, /* initial thread's TCB cap */
LCD_CapInitThreadCNode = 2, /* initial thread's root CNode cap */
LCD_CapBootInfoFrame = 9, /* bootinfo frame cap */
LCD_CapInitThreadIPCBuffer = 10 /* initial thread's IPC buffer frame cap */
};
typedef uint32_t LCD_Word;
typedef LCD_Word LCD_CPtr;
typedef LCD_CPtr LCD_CNode;
typedef LCD_CPtr LCD_Untyped;
typedef LCD_CPtr LCD_TCB;
/// Sets the specified number of low-order bits to 1
#define MASK(bits) ((1UL << bits) - 1)
#define OBJBITS_CTE 7
typedef uint32_t LCD_CPtr;
typedef uint32_t CapRights;
typedef uint32_t un; /* unknown */
#define CAPRIGHTS_READ (1 << 0)
#define CAPRIGHTS_WRITE (1 << 1)
#define CAPRIGHTS_EXECUTE (1 << 2)
#define CAPRIGHTS_GRANT (1 << 3)
#define CAPRIGHTS_IDENTIFY (1 << 4)
#define CAPRIGHTS_NUM 5
#define CAPRIGHTS_ALLRIGHTS ((1 << CAPRIGHTS_NUM) - 1)
#define CAPRIGHTS_READ_WRITE (CAPRIGHTS_READ | CAPRIGHTS_WRITE)
#define CAPRIGHTS_NORIGHTS 0
struct CapRights
{
};
typedef struct endpoint
{
int a;
int b;
} EndPoint;
typedef struct cnode
{
int32_t bits;
int32_t guard;
int32_t guard_size;
struct cte * cnode;
}CNode;
union capability_u{
CNode cnode;
EndPoint endpoint;
};
struct capability
{
LCD_Type type;
CapRights rights;
union capability_u u;
};
struct cte
{
struct capability cap;
};
/* internal functions */
int caps_lookup_slot(struct capability *cnode_cap, LCD_CPtr cptr, uint8_t vbits, uint8_t resolved_bits, struct cte **ret, CapRights rights);
struct cte * caps_locate_slot(struct cte * topCte, size_t offset);
void print_cnode(struct cte * myCte, int depth);
LCD_CPtr create_CNode(LCD_Untyped _service, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects);
LCD_CPtr create_EndPoint(LCD_Untyped _service, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects);
int cnode_create_internal(struct capability *src_cap, int size_bits);
/* externel interface */
static int LCD_Create_CSpace(void);
int LCD_Untyped_Retype(LCD_Untyped _service, LCD_Type objType, int size_bits, LCD_CNode root, int node_index, int node_depth, int node_offset, int num_objects);
static int LCD_CNode_Delete(LCD_CNode _service, int node_index, int node_depth);
static void *LCD_CNode_Search(LCD_CNode _service, int node_index, int node_depth);
This diff is collapsed.
#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/mm.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/semaphore.h>
#include <linux/log2.h>
#include <linux/delay.h>
#include <linux/kfifo.h>
#include <asm/page.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("FLUX-LAB University of Utah");
typedef uint32_t lcd_cnode; // a pointer to the cnode
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.
typedef uint16_t lcd_cap_type;
#define MAX_SLOTS (PAGE_SIZE/sizeof(struct cte))
#define CNODE_SLOTS_PER_CNODE 64
#define CNODE_SLOTS_START (MAX_SLOTS - CNODE_SLOTS_PER_CNODE)
#define CNODE_INDEX_BITS (ilog2(MAX_SLOTS))
#define CAP_ID_SIZE (sizeof(cap_id) * 8)
#define MAX_DEPTH ((CAP_ID_SIZE + 1)/CNODE_INDEX_BITS)
#define SAFE_EXIT_IF_ALLOC_FAILED(ptr, label) \
if (ptr == NULL) \
{ \
goto label; \
} \
#define ASSERT(condition, expr) \
if(!(condition)) { \
printk("\nAssertion Failed at: %d\n",__LINE__); \
panic(#expr); \
}
enum __lcd_cap_type
{
lcd_type_free,
lcd_type_capability,
lcd_type_cnode,
lcd_type_endpoint,
lcd_type_separator
};
/* caps with fixed slot potitions in the root CNode */
enum {
LCD_CapNull = 0, /* null cap */
LCD_CapInitThreadTCB = 1, /* initial thread's TCB cap */
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
};
#define CAPRIGHTS_READ (1 << 0)
#define CAPRIGHTS_WRITE (1 << 1)
#define CAPRIGHTS_EXECUTE (1 << 2)
#define CAPRIGHTS_GRANT (1 << 3)
#define CAPRIGHTS_NUM 4
#define CAPRIGHTS_ALL ((1 << CAPRIGHTS_NUM) - 1)
#define CAPRIGHTS_RW (CAPRIGHTS_READ | CAPRIGHTS_WRITE)
#define CAPRIGHTS_RWX (CAPRIGHTS_RW | CAPRIGHTS_EXECUTE)
#define CAPRIGHTS_NORIGHTS 0
struct cap_derivation_tree
{
struct cte *cap;
struct cap_space *cspace;
struct cap_derivation_tree *next;
struct cap_derivation_tree *prev;
struct cap_derivation_tree *parent_ptr;
struct cap_derivation_tree *child_ptr;
};
struct capability
{
cap_id cid; // locally unique to each thread
};
struct capability_internal
{
void *hobject; // a pointer to a kernel object
struct cap_derivation_tree *cdt_node; // list of domain ids to whom this capability is granted
lcd_cap_rights crights; // specifies the rights the domain has over this capability
};
struct cte;
struct cap_node
{
cap_id cnode_id;
struct cte *table; /* points to another cnode table */
uint16_t table_level;
};
struct free_slot_t
{
int next_free_cap_slot;
int next_free_cnode_slot;
};
struct cte // capability table entry
{
union{
struct cap_node cnode;
struct capability_internal cap;
struct free_slot_t slot;
};
lcd_cap_type ctetype;
uint16_t index;
};
struct cap_space
{
struct cte root_cnode;
struct semaphore sem_cspace;
};
/* Helper Functions */
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);
id = id >> ((MAX_DEPTH - 1) * CNODE_INDEX_BITS);
bits = (int) id;
return bits;
}
static inline void lcd_clear_bits_at_level(cap_id *id, int level)
{
cap_id mask = (~0);
// clear all higher order bits.
mask = mask << ((MAX_DEPTH - 1) * CNODE_INDEX_BITS);
// clear lower order bits
mask = mask >> ((MAX_DEPTH - 1) * CNODE_INDEX_BITS);
// get the mask to appropriate position
mask = mask << (level * CNODE_INDEX_BITS);
mask = ~mask;
*id = (*id) & mask;
}
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;
lcd_clear_bits_at_level(cid, level);
id = id << (level * CNODE_INDEX_BITS);
*cid = *cid | id;
}
struct cte * lcd_reserve_cap_slot(struct cte *cnode, cap_id *cid, int free_slot);