Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xcap
xcap-capability-linux
Commits
98d62b3c
Commit
98d62b3c
authored
Mar 10, 2014
by
Muktesh Khole
Committed by
Vikram Narayanan
Oct 25, 2016
Browse files
lcd_lookup_free_slot implementation
parent
cc7136e2
Changes
2
Hide whitespace changes
Inline
Side-by-side
xcap/capability.c
View file @
98d62b3c
...
...
@@ -17,10 +17,10 @@ void cleanup_module(void)
printk
(
KERN_INFO
"Cleaning up LCD Module
\n
"
);
}
void
lcd_initialize_freelist
(
struct
cte
*
cnode
,
int
size
,
bool
bFirstCNode
)
void
lcd_initialize_freelist
(
struct
cte
*
cnode
,
bool
bFirstCNode
)
{
int
startid
=
1
;
int
i
=
startid
;
int
i
;
if
(
cnode
==
NULL
)
return
;
...
...
@@ -31,15 +31,34 @@ void lcd_initialize_freelist(struct cte *cnode, int size, bool bFirstCNode)
}
cnode
[
0
].
ctetype
=
lcd_type_free
;
cnode
[
0
].
next_free_slot
=
startid
;
cnode
[
0
].
slot
.
next_free_
cap_
slot
=
startid
;
cnode
[
startid
].
ctetype
=
lcd_type_free
;
i
=
startid
;
for
(;
i
<
MAX
_SLOTS
-
1
;
i
++
)
for
(
i
=
startid
;
i
<
CNODE
_SLOTS
_START
;
i
++
)
{
cnode
[
i
].
next_free_slot
=
i
+
1
;
cnode
[
i
].
slot
.
next_free_
cap_
slot
=
i
+
1
;
cnode
[
i
+
1
].
ctetype
=
lcd_type_free
;
}
cnode
[
i
].
next_free_slot
=
0
;
cnode
[
i
].
slot
.
next_free_cap_slot
=
0
;
startid
=
CNODE_SLOTS_START
;
cnode
[
0
].
slot
.
next_free_cnode_slot
=
startid
;
cnode
[
startid
].
ctetype
=
lcd_type_free
;
for
(
i
=
CNODE_SLOTS_START
;
i
<
MAX_SLOTS
-
1
;
i
++
)
{
cnode
[
i
].
slot
.
next_free_cnode_slot
=
i
+
1
;
cnode
[
i
+
1
].
ctetype
=
lcd_type_free
;
}
cnode
[
i
].
slot
.
next_free_cnode_slot
=
0
;
}
struct
cte
*
lcd_insert_capability
(
struct
cte
*
node
,
cap_id
*
cid
,
int
free_slot
,
int
level
)
{
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
;
set_level_bits
(
cid
,
node
->
cnode
.
cnode_id
,
free_slot
,
level
);
return
&
node
[
free_slot
];
}
// caller responsible for locking cspace.
...
...
@@ -48,23 +67,76 @@ void lcd_initialize_freelist(struct cte *cnode, int size, bool bFirstCNode)
cap_id
lcd_lookup_free_slot
(
struct
cap_space
*
cspace
,
struct
cte
**
cap
)
{
cap_id
cid
=
0
;
struct
cte
*
cnode
;
bool
found
=
false
;
int
level
=
0
,
i
=
0
;
struct
kfifo
cnode_q
;
if
(
cspace
==
NULL
)
if
(
cspace
==
NULL
||
cap
==
NULL
)
return
0
;
cnode
=
cspace
->
root_cnode
;
while
(
!
found
)
if
(
kfifo_alloc
(
&
cnode_q
,
sizeof
(
struct
cte
)
*
512
,
GFP_KERNEL
)
!=
0
)
return
0
;
kfifo_in
(
&
cnode_q
,
cspace
->
root_cnode
.
cnode
.
cap_entry
,
1
);
while
(
!
found
&&
!
kfifo_is_empty
(
&
cnode_q
))
{
int
nxt
=
cnode
[
0
].
next_free_slot
;
// check if only one free slot is available
if
(
cnode
[
nxt
].
next_free_slot
==
0
)
int
free_cap_slot
=
0
,
free_cnode_slot
=
0
;
struct
cte
*
node
=
NULL
;
kfifo_out
(
&
cnode_q
,
node
,
1
);
if
(
node
==
NULL
)
return
0
;
free_cap_slot
=
node
[
0
].
next_free_cap_slot
;
free_cnode_slot
=
node
[
0
].
next_free_cnode_slot
;
if
(
free_cap_slot
!=
0
&&
free_cap_slot
<
CNODE_SLOTS_START
)
{
*
cap
=
lcd_insert_capability
(
node
,
&
cid
,
free_cap_slot
,
level
);
return
cid
;
}
else
if
(
free_cnode_slot
!=
0
&&
free_cnode_slot
>=
CNODE_SLOTS_START
&&
free_cnode_slot
<
MAX_SLOTS
)
{
// there is no slot free for capability
// 1. Check if free slots are available at next level
for
(
i
=
CNODE_SLOTS_START
;
i
<
free_cap_slot
;
i
++
)
{
if
(
node
[
i
].
ctetype
==
lcd_type_cnode
)
{
struct
cte
*
next_node
=
node
[
i
].
cnode
.
cap_entry
;
free_cap_slot
=
next_node
[
0
].
next_free_cap_slot
;
if
(
free_cap_slot
!=
0
&&
free_cap_slot
<
CNODE_SLOTS_START
)
{
*
cap
=
lcd_insert_capability
(
next_node
,
&
cid
,
free_cap_slot
,
level
+
1
);
return
cid
;
}
}
}
// we will have to allocate a new cnode
node
[
0
].
slot
.
next_free_cnode_slot
=
node
[
free_cnode_slot
].
slot
.
next_free_cnode_slot
;
node
[
free_cnode_slot
].
ctetype
=
lcd_type_cnode
;
node
[
free_cnode_slot
].
cnode
.
cap_entry
=
kmalloc
(
PAGE_SIZE
,
GFP_KERNEL
);
if
(
node
[
free_cnode_slot
].
cnode
.
cap_entry
==
NULL
)
return
0
;
lcd_initialize_freelist
(
node
[
free_cnode_slot
].
cnode
.
cap_entry
,
false
);
node
=
node
[
free_cnode_slot
].
cnode
.
cap_entry
;
free_cap_slot
=
node
[
0
].
next_free_cap_slot
;
if
(
free_cap_slot
!=
0
&&
free_cap_slot
<
CNODE_SLOTS_START
)
{
*
cap
=
lcd_insert_capability
(
node
,
&
cid
,
free_slot
,
level
+
1
);
return
cid
;
}
}
else
{
// nothing is free in this cnode
// kep lookin at all its children
for
(
i
=
CNODE_SLOTS_START
;
i
<
MAX_SLOTS
;
i
++
)
{
// only one free slot is available, allocate a new cnode and set free_cnode
kfifo_in
(
&
cnode_q
,
&
node
[
i
],
1
);
}
level
++
;
}
}
kfifo_free
(
&
cnode_q
);
return
cid
;
}
...
...
@@ -78,9 +150,9 @@ struct cte * lcd_lookup_capability(struct cap_space *cspace, cap_id cid)
mask
=
~
mask
;
// check if input is valid
if
(
cspace
==
NULL
||
cid
==
0
)
if
(
cspace
==
NULL
||
cid
==
0
||
cspace
->
root_cnode
.
cnode
.
cap_entry
==
NULL
)
return
NULL
;
cnode
=
cspace
->
root_cnode
;
cnode
=
cspace
->
root_cnode
.
cnode
.
cap_entry
;
while
(
id
>
0
)
{
...
...
@@ -114,21 +186,23 @@ struct cap_space * lcd_create_cspace()
sema_init
(
&
(
cspace
->
sem_cspace
),
1
);
// allocate memory for the first cnode.
cspace
->
root_cnode
=
kmalloc
(
PAGE_SIZE
,
GFP_KERNEL
);
SAFE_EXIT_IF_ALLOC_FAILED
(
cspace
->
root_cnode
,
alloc_failure
);
cspace
->
root_cnode
.
ctetype
=
lcd_type_cnode
;
cspace
->
root_cnode
.
cnode
.
cnode_id
=
0
;
cspace
->
root_cnode
.
cnode
.
level
=
0
;
cspace
->
root_cnode
.
cnode
.
cap_entry
=
kmalloc
(
PAGE_SIZE
,
GFP_KERNEL
);
SAFE_EXIT_IF_ALLOC_FAILED
(
cspace
->
root_cnode
.
cnode
.
cap_entry
,
alloc_failure
);
// initialize the free list
lcd_initialize_freelist
(
cspace
->
root_cnode
,
PAGE_SIZE
,
true
);
lcd_initialize_freelist
(
cspace
->
root_cnode
.
cnode
.
cap_entry
,
true
);
goto
success
;
alloc_failure:
if
(
cspace
)
{
if
(
cspace
->
root_cnode
)
if
(
cspace
->
root_cnode
.
cnode
.
cap_entry
)
{
kfree
(
cspace
->
root_cnode
);
cspace
->
root_cnode
=
NULL
;
kfree
(
cspace
->
root_cnode
.
cnode
.
cap_entry
);
cspace
->
root_cnode
.
cnode
.
cap_entry
=
NULL
;
}
vfree
(
cspace
);
cspace
=
NULL
;
...
...
@@ -150,11 +224,16 @@ cap_id lcd_create_cap(void * ptcb, void * hobject, lcd_cap_rights crights)
return
0
;
cspace
=
tcb
->
cspace
;
if
(
cspace
==
NULL
||
cspace
->
root_cnode
==
NULL
)
if
(
cspace
==
NULL
||
cspace
->
root_cnode
.
cnode
.
cap_entry
==
NULL
)
return
0
;
down_interruptible
(
&
cspace
->
sem_cspace
);
cid
=
lcd_lookup_free_slot
(
cspace
,
&
cap
);
if
(
cid
==
0
)
{
up
(
&
cspace
->
sem_cspace
);
return
0
;
}
cap
->
ctetype
=
lcd_type_capability
;
cap
->
cap
.
crights
=
crights
;
cap
->
cap
.
hobject
=
hobject
;
...
...
@@ -178,7 +257,7 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
while
(
!
done
)
{
//
if (down_trylock() == 0)
Lock source cspace.
// Lock source cspace.
if
(
down_trylock
(
stcb
->
cspace
->
sem_cspace
)
==
0
)
{
// if (down_trylock() == 0) lock dst cspace
...
...
@@ -188,7 +267,8 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
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
){
if
(
cid
!=
0
&&
src_cte
!=
NULL
&&
dst_cte
!=
NULL
)
{
struct
cap_derivation_list
*
cdt_node
;
// add the capability to destination.
dst_cte
->
ctetype
=
lcd_type_capability
;
...
...
@@ -198,17 +278,23 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
// update the CDT of source
cdt_node
=
kmalloc
(
sizeof
(
struct
cap_derivation_list
),
GFP_KERNEL
);
if
(
cdt_node
!=
NULL
){
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
;
cdt_node
->
remote_cid
=
cid
;
cdt_node
->
remote_TCB
=
dst
_tcb
;
}
else
{
else
{
ASSERT
(
false
,
"cdt_node allocation failed"
);
}
done
=
true
;
}
else
{
ASSERT
(
false
,
"Source capability not found or no free slot in destination"
);
}
// release lock on dst cspace.
up
(
dtcb
->
cspace
->
sem_cspace
);
}
...
...
@@ -219,4 +305,22 @@ cap_id lcd_cap_grant(void *src_tcb, cap_id src_cid, void * dst_tcb, lcd_cap_righ
msleep_interruptible
(
1
);
}
return
cid
;
}
uint32_t
lcd_get_cap_rights
(
void
*
ptcb
,
cap_id
cid
,
lcd_cap_rights
*
rights
)
{
struct
task_struct
*
tcb
=
ptcb
;
struct
cte
*
cap
;
if
(
tcb
==
NULL
||
tcb
->
cspace
==
NULL
||
cid
==
0
||
rights
==
NULL
)
return
-
1
;
down_interruptible
(
tcb
->
cspace
->
sem_cspace
);
cap
=
lcd_lookup_capability
(
tcb
->
cspace
,
cid
);
if
(
cap
==
NULL
||
cap
->
ctetype
!=
lcd_type_capability
)
{
up
(
tcb
->
cspace
->
sem_cspace
);
return
-
1
;
}
rights
=
cap
->
cap
.
crights
;
up
(
tcb
->
cspace
->
sem_cspace
);
return
0
;
}
\ No newline at end of file
xcap/capability.h
View file @
98d62b3c
...
...
@@ -11,6 +11,7 @@
#include
<linux/semaphore.h>
#include
<linux/log2.h>
#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"
...
...
@@ -24,7 +25,7 @@ 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.
#define MAX_SLOTS (PAGE_SIZE/sizeof(struct cte))
#define CNODE_SLOTS_PER_CNODE
5
#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)
...
...
@@ -98,22 +99,30 @@ struct cte;
struct
cap_node
{
cap_id
cnode_id
;
int
level
;
struct
cte
*
cap_entry
;
/* may point to another cnode or to a capability */
};
struct
free_slot_t
{
int
next_free_cap_slot
;
int
next_free_cnode_slot
;
};
struct
cte
// capability table entry
{
lcd_cap_type
ctetype
;
union
{
struct
cap_node
cnode
;
struct
capability_internal
cap
;
int
next_free_
slot
;
struct
free_slot_t
slot
;
};
};
struct
cap_space
{
struct
cte
*
root_cnode
;
struct
cte
root_cnode
;
struct
semaphore
sem_cspace
;
};
...
...
@@ -142,8 +151,10 @@ static inline void clear_bits_at_level(cap_id *id, int level)
*
id
=
(
*
id
)
&
mask
;
}
struct
cte
*
lcd_insert_capability
(
struct
cte
*
node
,
cap_id
*
cid
,
int
free_slot
,
int
level
);
// initializes the free slots available in the cnode structure.
void
lcd_initialize_freelist
(
struct
cte
*
cnode
,
int
size
,
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
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment