Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
xcap
xcap-capability-linux
Commits
d4a334cb
Commit
d4a334cb
authored
Aug 13, 2014
by
Charlie Jacobsen
Committed by
Vikram Narayanan
Oct 25, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Starting tests for api.
parent
3206be73
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
188 additions
and
422 deletions
+188
-422
drivers/lcd-prototype/api/Makefile
drivers/lcd-prototype/api/Makefile
+3
-0
drivers/lcd-prototype/api/api-tests.c
drivers/lcd-prototype/api/api-tests.c
+19
-0
drivers/lcd-prototype/api/api.c
drivers/lcd-prototype/api/api.c
+25
-217
drivers/lcd-prototype/api/cap-cache.c
drivers/lcd-prototype/api/cap-cache.c
+0
-63
drivers/lcd-prototype/api/cap.c
drivers/lcd-prototype/api/cap.c
+57
-75
drivers/lcd-prototype/api/defs.h
drivers/lcd-prototype/api/defs.h
+84
-67
No files found.
drivers/lcd-prototype/api/Makefile
0 → 100644
View file @
d4a334cb
obj-$(CONFIG_LCD_PROTOTYPE_API)
+=
api.o cap.o
drivers/lcd-prototype/api/api-tests.c
0 → 100644
View file @
d4a334cb
/*
* api-tests.c
*
* Authors: Anton Burtsev <aburtsev@flux.utah.edu>
* Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*/
static
int
test01
(
void
)
{
return
0
;
}
static
int
api_tests
(
void
)
{
if
(
test01
())
return
-
1
;
LCD_MSG
(
"all api tests passed!"
);
}
drivers/lcd-prototype/api/api.c
View file @
d4a334cb
/*
* api.c
*
* Authors: Anton Burtsev <aburtsev@flux.utah.edu>
* Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*/
int
lcd_mk_sync_endpoint
(
cptr_t
dest
)
{
int
ret
;
struct
sync_ipc
*
rvp
;
capability_t
rvp_cap
;
struct
cnode
*
cnode
;
struct
message_info
*
msg
=
&
current
->
utcb
->
msg_info
;
rvp
=
lcd_create_sync_ep
();
if
(
!
rvp
)
{
printk
(
KERN_ERR
"Failed to allocate memory
\n
"
);
ret
=
-
ENOMEM
;
goto
err
;
};
ret
=
lcd_alloc_cap
(
&
current
->
cap_cache
,
&
rvp_cap
);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to allocate free capability
\n
"
);
ret
=
-
ENOSPC
;
kfree
(
rvp
);
goto
err
;
};
ret
=
lcd_cap_insert_object
(
&
current
->
cspace
,
rvp_cap
,
rvp
,
LCD_TYPE_SYNC_EP
);
if
(
cnode
==
0
)
{
lcd_destroy_rvp
(
rvp
);
goto
err
;
};
msg
->
cap_regs
[
0
]
=
rvp_cap
;
msg
->
valid_cap_regs
=
1
;
ipc_reply
(
reply_cap
,
msg
);
lcd_cap_drop
(
&
current
->
cspace
,
rvp_cap
);
lcd_free_cap
(
&
current
->
cap_cache
,
rvp_cap
);
return
0
;
err:
msg
->
err
=
ret
;
ipc_reply
(
reply_cap
,
msg
);
return
ret
;
};
int
lcd_api_create_lcd
(
struct
message_info
*
msg
,
struct
lcd_api
*
api
,
capability_t
reply_cap
)
{
int
ret
;
int
i
;
capability_t
lcd_cap
;
struct
cnode
*
cnode
;
char
*
module_name
;
module_name
=
lcd_cap_marshal_string
(
&
msg
->
regs
[
1
],
LCD_MAX_REGS
-
1
);
if
(
!
module_name
)
{
printk
(
KERN_ERR
"Failed to unmarshal LCD name
\n
"
);
ret
=
-
EINVAL
;
goto
err
;
};
lcd_task
=
lcd_create_as_module
(
module_name
);
if
(
!
lcd_task
)
{
printk
(
KERN_ERR
"Failed to create LCD from a module:%s
\n
"
,
module_name
);
ret
=
-
ENOMEM
;
goto
err
;
};
ret
=
lcd_alloc_cap
(
&
current
->
cap_cache
,
&
lcd_cap
);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to allocate free capability
\n
"
);
ret
=
-
ENOSPC
;
lcd_destroy
(
lcd_task
);
goto
err
;
};
ret
=
lcd_cap_insert_object
(
&
current
->
cspace
,
lcd_cap
,
lcd_task
,
LCD_TYPE_LCD
);
if
(
cnode
==
0
)
{
lcd_destroy
(
lcd_task
);
goto
err
;
};
for
(
int
i
=
0
;
i
<
cap_regs
-
2
;
i
++
)
{
capability_t
boot_cap
;
ret
=
lcd_alloc_cap
(
&
lcd_task
->
cap_cache
,
&
boot_cap
);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to allocate free capability
\n
"
);
ret
=
-
ENOSPC
;
lcd_destroy
(
lcd_task
);
goto
err
;
};
ret
=
lcd_cap_move_object
(
&
lcd_task
->
cspace
,
boot_cap
,
&
current
->
cspace
,
msg
->
cap_regs
[
i
]);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to move boot capability number:d
\n
"
,
i
);
ret
=
-
ENOSPC
;
lcd_destroy
(
lcd_task
);
goto
err
;
};
lcd_task
->
utcb
->
boot_info
.
boot_caps
[
i
]
=
boot_cap
;
lcd_drop_cap
(
&
current
->
cspace
,
msg
->
cap_regs
[
i
]);
};
msg
->
cap_regs
[
0
]
=
lcd_cap
;
msg
->
valid_cap_regs
=
1
;
ipc_reply
(
reply_cap
,
msg
);
lcd_cap_drop
(
&
current
->
cspace
,
lcd_cap
);
lcd_free_cap
(
&
current
->
cap_cache
,
lcd_cap
);
return
0
;
err:
msg
->
err
=
ret
;
ipc_reply
(
reply_cap
,
msg
);
return
ret
;
};
int
lcd_api_execution_loop
(
struct
lcd_api
*
lcd_api
)
{
struct
message_info
*
msg
=
&
current
->
utcb
->
msg_info
;
capability_t
reply_cap
;
enum
lcd_api_calls
call
;
int
ret
;
int
i
;
#include <linux/kernel.h>
#include <linux/module.h>
#include "../include/common.h"
#include "defs.h"
for
(
i
=
0
;
i
<
LCD_MAX_CAP_REGS
;
i
++
)
{
static
int
api_tests
(
void
);
ret
=
lcd_alloc_cap
(
&
current
->
cap_cache
,
&
msg
->
cap_regs
[
i
]);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to allocate free capability
\n
"
);
return
-
ENOSPC
;
};
};
while
(
!
lcd_api
->
exit_flag
)
{
msg
->
valid_regs
=
sizeof
(
msg
->
regs
)
/
sizeof
(
msg
->
regs
[
0
]);
ret
=
ipc_recv
(
lcd_api
->
rvp
,
msg
);
if
(
ret
)
{
printk
(
KERN_ERR
"lcd_api: recv failed:%d
\n
"
,
ret
);
continue
;
}
reply_cap
=
msg
->
cap_regs
[
msg
->
valid_cap_regs
];
// We know we're serving a call invocation, reply cap is
// verified by the ipc_call()
if
(
msg
->
valid_regs
==
0
)
{
printk
(
KERN_ERR
"lcd_api: invalid invocation
\n
"
);
msg
->
valid_regs
=
0
;
msg
->
valid_cap_regs
=
0
;
ipc_reply
(
reply_cap
,
msg
);
lcd_cap_drop
(
&
current
->
cspace
,
reply_cap
);
continue
;
};
call
=
msg
->
regs
[
0
];
switch
(
call
)
{
case
LCD_CREATE_SYNC_ENDPOINT
:
ret
=
lcd_api_create_sync_endpoint
(
msg
,
lcd_api
,
reply_cap
);
break
;
case
LCD_CREATE_LCD
:
ret
=
lcd_api_create_lcd
(
msg
,
lcd_api
,
reply_cap
);
break
;
default:
printk
(
KERN_ERR
"lcd_api: invalid call number:%d
\n
"
,
call
);
msg
->
valid_regs
=
0
;
msg
->
valid_cap_regs
=
0
;
ipc_reply
(
reply_cap
,
msg
);
lcd_cap_drop
(
&
current
->
cspace
,
reply_cap
);
};
};
for
(
i
=
0
;
i
<
LCD_MAX_CAP_REGS
;
i
++
)
{
static
int
__init
api_init
(
void
)
{
LCD_MSG
(
"api starting"
);
ret
=
lcd_free_cap
(
&
current
->
cap_cache
,
msg
->
cap_regs
[
i
]);
};
/*
* Run regression tests
*/
if
(
api_tests
())
{
return
-
1
;
}
return
0
;
};
int
lcd_api_thread
(
void
*
p
)
{
int
ret
;
struct
lcd_api
*
api
=
(
struct
lcd_api
*
)
p
;
ret
=
lcd_enter
();
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to enter LCD:%d
\n
"
,
ret
);
return
ret
;
};
api
->
ep
=
lcd_make_sync_endpoint
(
&
current
->
cspace
,
&
current
->
cap_cache
,
&
api
->
ep_cap
);
if
(
api
->
ep
)
{
printk
(
KERN_ERR
"Failed to create API endpoint:%d
\n
"
,
ret
);
return
-
EINVAL
;
};
ret
=
lcd_api_execution_loop
(
api
);
return
ret
;
};
int
lcd_api_init
(
struct
lcd_api
*
api
)
{
int
ret
;
struct
task_struct
*
t
;
t
=
kthread_create
(
lcd_api_thread
,
api
,
"lcd-api"
);
if
(
!
t
)
{
printk
(
KERN_ERR
"Failed to create LCD API thread
\n
"
);
return
-
EINVAL
;
};
}
wake_up_process
(
t
);
return
0
;
static
void
__exit
api_exit
(
void
)
{
return
;
}
int
lcd_api_exit
(
struct
lcd_api
*
api
)
{
api
->
exit_flag
=
1
;
};
module_init
(
api_init
);
module_exit
(
api_exit
);
/* DEBUG -------------------------------------------------- */
#include "api-tests.c"
drivers/lcd-prototype/api/cap-cache.c
deleted
100644 → 0
View file @
3206be73
/*
* Authors: Anton Burtsev <aburtsev@flux.utah.edu>
* Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*/
#include <linux/slab.h>
#include <lcd/cap-cache.h>
#include <lcd/cap.h>
int
lcd_init_list_cache
(
struct
cap_cache
*
list_cache
,
uint64_t
size
)
{
uint32_t
i
;
list_cache
->
cap
=
kmalloc
(
sizeof
(
*
list_cache
->
cap
)
*
size
,
GFP_KERNEL
);
if
(
!
list_cache
->
cap
)
return
-
ENOMEM
;
list_cache
->
head
=
0
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
list_cache
->
cap
[
i
]
=
i
+
1
;
}
list_cache
->
cap
[
size
-
2
]
=
size
-
2
;
return
0
;
}
void
lcd_free_list_cache
(
struct
cap_cache
*
list_cache
)
{
kfree
(
list_cache
->
cap
);
return
;
};
int
lcd_alloc_cap
(
struct
cap_cache
*
cap_cache
,
capability_t
*
free_cap
)
{
unsigned
long
flags
;
uint32_t
head
;
spin_lock_irqsave
(
&
cap_cache
->
lock
,
flags
);
if
(
cap_cache
->
head
==
cap_cache
->
cap
[
cap_cache
->
head
])
{
spin_unlock_irqrestore
(
&
cap_cache
->
lock
,
flags
);
return
-
ENOMEM
;
};
head
=
cap_cache
->
head
;
*
free_cap
=
(
capability_t
)
head
;
cap_cache
->
head
=
cap_cache
->
cap
[
head
];
spin_unlock_irqrestore
(
&
cap_cache
->
lock
,
flags
);
return
0
;
};
void
lcd_free_cap
(
struct
cap_cache
*
cap_cache
,
capability_t
free_cap
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
cap_cache
->
lock
,
flags
);
cap_cache
->
cap
[(
uint32_t
)
free_cap
]
=
cap_cache
->
head
;
cap_cache
->
head
=
(
uint32_t
)
free_cap
;
spin_unlock_irqrestore
(
&
cap_cache
->
lock
,
flags
);
return
0
;
}
drivers/lcd-prototype/api/cap.c
View file @
d4a334cb
...
...
@@ -6,7 +6,7 @@
#include "defs.h"
#include "../include/common.h"
struct
cspace
*
lcd_mk_
cspace
(
void
)
int
lcd_mk_cspace
(
struct
cspace
*
*
cspace
_ptr
)
{
struct
cspace
*
cspace
;
int
i
;
...
...
@@ -15,90 +15,72 @@ struct cspace * lcd_mk_cspace(void)
*/
cspace
=
kmalloc
(
sizeof
(
*
cspace
),
GFP_KERNEL
);
if
(
!
cspace
)
return
NULL
;
memset
(
cspace
,
0
,
sizeof
(
*
cspace
));
/* sets cnode types to invalid */
/*
* Initialize free list
return
-
ENOMEM
;
/*
* Sets cnode types to unformed, and free_slot to 0
*/
for
(
i
=
0
;
i
<
LCD_NUM_CAPS
;
i
++
)
list_add
(
&
cspace
->
free_list
,
&
cspace
->
cnodes
[
i
].
free_list
);
memset
(
cspace
,
0
,
sizeof
(
*
cspace
));
/*
* Initialize lock
*/
mutex_init
(
&
cspace
->
lock
);
return
cspace
;
/*
* Done
*/
*
cspace_ptr
=
cspace
;
return
0
;
}
int
lcd_cap_insert
(
struct
cspace
*
cspace
,
cptr_t
cptr
,
void
*
object
,
enum
lcd_cap_type
type
)
{
struct
cnode
*
cnode
;
cnode
=
lcd_cnode_lookup
(
cspace
,
cap
);
if
(
cnode
==
0
)
{
printk
(
KERN_ERR
"Failed to create capability
\n
"
);
return
-
ENOMEM
;
};
cnode
->
type
=
type
;
cnode
->
object
=
object
;
lcd_cnode_release
(
cnode
);
return
0
;
struct
cnode
*
cnode
=
NULL
;
int
ret
;
/*
* Lookup cnode
*/
ret
=
lcd_lock_cspace
(
cspace
);
if
(
!
ret
)
{
cnode
=
__lcd_cnode_lookup
(
cspace
,
cptr
);
lcd_unlock_cspace
(
cspace
);
}
else
{
return
ret
;
}
/*
* Set vals
*/
if
(
cnode
&&
cnode
->
type
==
LCD_CAP_TYPE_UNFORMED
)
{
cnode
->
object
=
object
;
cnode
->
type
=
type
;
return
0
;
}
else
{
return
-
EINVAL
;
}
}
struct
sync_ipc
*
lcd_cap_make_sync_endpoint
(
struct
cspace
*
cspace
,
struct
cap_cache
*
cache
,
capability_t
*
cap
)
{
struct
sync_ipc
*
rvp
;
rvp
=
alloc_sync_ipc
();
if
(
!
rvp
)
{
printk
(
KERN_ERR
"Failed to allocate memory
\n
"
);
return
NULL
;
};
ret
=
lcd_alloc_cap
(
cache
,
cap
);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to allocate free capability
\n
"
);
kfree
(
rvp
);
return
NULL
;
};
ret
=
lcd_cap_insert_object
(
cspace
,
*
cap
,
rvp
,
LCD_TYPE_SYNC_EP
);
if
(
ret
)
{
printk
(
KERN_ERR
"Failed to insert endpoint into the cspace:%d
\n
"
,
ret
);
kfree
(
rvp
);
return
NULL
;
};
return
rvp
;
};
struct
cnode
*
lcd_cnode_lookup
(
struct
cspace
*
cspace
,
capability_t
cap
)
{
unsigned
long
flags
;
if
(
cap
>=
LCD_MAX_CAPS
)
return
NULL
;
spin_lock_irqsave
(
&
cspace
->
lock
,
flags
);
lcd_cnode_lock
(
&
cspace
->
cnode
[
cap
]);
spin_unlock_irqrestore
(
&
cspace
->
lock
,
flags
);
return
&
cspace
->
cnode
[
cap
];
};
EXPORT_SYMBOL
(
lcd_cnode_lookup
);
void
lcd_cap_drop
(
struct
cspace
*
cspace
,
capability_t
cap
)
{
struct
cnode
*
cnode
;
cnode
=
lcd_cnode_lookup
(
cspace
,
cap
);
if
(
!
cnode
)
return
;
cnode
->
type
=
LCD_TYPE_FREE
;
cnode
->
object
=
NULL
;
lcd_cnode_release
(
cnode
);
return
;
};
int
lcd_cap_grant
(
struct
cspace
*
src_cspace
,
struct
cspace
*
dest_cspace
,
cptr_t
src_cptr
,
cptr_t
dest_cptr
)
{
struct
cnode
*
src_cnode
;
int
ret
;
/*
* Get source capability data
*/
ret
=
lcd_cnode_lookup
(
src_cspace
,
src_cptr
,
&
src_cnode
);
if
(
ret
)
return
ret
;
if
(
!
src_cnode
)
return
-
EINVAL
;
if
(
!
__lcd_cap_can_grant
(
src_cnode
))
return
-
EINVAL
;
/*
* Insert into destination
*/
return
lcd_cap_insert
(
dest_cspace
,
dest_cptr
,
src_cnode
->
object
,
src_cnode
->
type
);
}
void
lcd_rm_cspace
(
struct
cspace
*
cspace
)
{
kfree
(
cspace
);
}
drivers/lcd-prototype/api/defs.h
View file @
d4a334cb
...
...
@@ -3,41 +3,37 @@
* Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*
* This simple prototype uses a global lock on an lcd's cspace.
* This simple prototype uses a global lock on an lcd's cspace. No
* rights checking. The lcd need only have a valid cnode mapped by
* the cptr. Capability grants just copy cnode data from one cspace
* to another. Capabilities cannot be revoked, so if a cnode is valid,
* it can be used freely. Cnodes are allocated in a linear order, so
* no need to do fancy free lists, etc.
*/
#ifndef LCD_PROTOTYPE_API_DEFS_H
#define LCD_PROTOTYPE_API_DEFS_H
#include <linux/
spinlock
.h>
#include <linux/
mutex
.h>
#include <lcd-prototype/lcd.h>
/* CAPABILITIES -------------------------------------------------- */
enum
lcd_cap_type
{
LCD_CAP_TYPE_
INVALI
D
=
0
,
LCD_CAP_TYPE_SYNC_EP
=
1
,
LCD_CAP_TYPE_
UNFORME
D
=
0
,
LCD_CAP_TYPE_SYNC_EP
=
1
,
};
enum
lcd_cap_right
{
LCD_CAP_RIGHT_READ
=
0x01
,
LCD_CAP_RIGHT_WRITE
=
0x02
,
LCD_CAP_RIGHT_GRANT
=
0x04
,
};
#define LCD_CAP_RIGHT_ALL = (LCD_CAP_RIGHT_READ | LCD_CAP_RIGHT_WRITE | LCD_CAP_RIGHT_GRANT)
struct
cnode
{
enum
lcd_cap_type
type
;
int
rights
;
void
*
object
;
struct
listhead
free_list
;
};
#define LCD_NUM_CAPS 32
struct
cspace
{
struct
mutex
lock
;
struct
cnode
cnodes
[
LCD_NUM_CAPS
];
struct
listhead
free_
lis
t
;
int
free_
slo
t
;
};
/**
...
...
@@ -47,56 +43,79 @@ static inline struct cspace * lcd_cspace(void)
{
return
current
->
lcd
->
cspace
;
}
/**
* Set current's cspace
*/
static
inline
void
lcd_store_cspace
(
struct
cspace
*
cspace
)
{
current
->
lcd
->
cspace
=
cspace
;
}
/**
* Allocates memory and initializes the contents of a cspace.
*/
struct
cspace
*
lcd_mk_
cspace
(
void
);
int
lcd_mk_cspace
(
struct
cspace
*
*
cspace
_ptr
);
/**
* Acquires/releases global cspace lock. Must wrap calls to unsafe
* insert, lookup, etc. with lock/unlock.
* insert, lookup, etc. with lock/unlock. Lock returns zero if
* lock successfully taken (no signals).
*/
void
lcd_lock_cspace
(
struct
cspace
*
cspace
);
void
lcd_unlock_cspace
(
struct
cspace
*
cspace
);
static
inline
int
lcd_lock_cspace
(
struct
cspace
*
cspace
)
{
return
mutex_lock_interruptible
(
cspace
->
lock
);
}
static
inline
void
lcd_unlock_cspace
(
struct
cspace
*
cspace
)
{
mutex_unlock
(
cspace
->
lock
);
}
/**
* (UNSAFE) Insert object into cspace at cptr with type and rights.
* (SAFE) Allocates an empty cnode slot, and returns a cptr to it. Returns
* non-zero if no free slots available.
*/
int
__lcd_cap_insert
(
struct
cspace
*
cspace
,
cptr_t
cptr
,
void
*
object
,
enum
lcd_cap_type
type
,
int
rights
);
static
inline
int
lcd_cap_alloc
(
struct
cspace
*
cspace
,
cptr_t
*
cptr
)
{
int
ret
=
lcd_lock_cspace
(
cspace
);
if
(
!
ret
)
{
if
(
cspace
->
free_slot
<
LCD_NUM_CAPS
)
*
cptr
=
++
cspace
->
free_slot
;
else
ret
=
-
ENOMEM
;
lcd_unlock_cspace
(
cspace
);
}
return
ret
;
}
/**
* (SAFE) Insert object into cspace.
*/
static
inline
int
lcd_cap_insert
(
struct
cspace
*
cspace
,
cptr_t
cptr
,
void
*
object
,
enum
lcd_cap_type
type
,
int
rights
)
{
lcd_lock_cspace
(
cspace
);
__lcd_cap_insert
(
cspace
,
cptr
,
object
,
type
,
rights
);
lcd_unlock_cspace
(
cspace
);
}
void
*
object
,
enum
lcd_cap_type
type
);
/**
* (UNSAFE) Look up cnode in cspace at cptr.
*/
struct
cnode
*
__lcd_cnode_lookup
(
struct
cspace
*
cspace
,
cptr_t
cptr
);