Skip to content
GitLab
Menu
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
25949c4a
Commit
25949c4a
authored
Aug 13, 2014
by
Charlie Jacobsen
Committed by
Vikram Narayanan
Oct 25, 2016
Browse files
Starting api code.
parent
963eb782
Changes
12
Hide whitespace changes
Inline
Side-by-side
drivers/lcd-prototype/api/api.c
0 → 100644
View file @
25949c4a
/*
* 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
;
for
(
i
=
0
;
i
<
LCD_MAX_CAP_REGS
;
i
++
)
{
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
++
)
{
ret
=
lcd_free_cap
(
&
current
->
cap_cache
,
msg
->
cap_regs
[
i
]);
};
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
;
}
int
lcd_api_exit
(
struct
lcd_api
*
api
)
{
api
->
exit_flag
=
1
;
};
drivers/lcd-prototype/api/cap-cache.c
0 → 100644
View file @
25949c4a
/*
* 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
0 → 100644
View file @
25949c4a
/*
* Author: Anton Burtsev <aburtsev@flux.utah.edu>
* Copyright: University of Utah
*/
#include <linux/slab.h>
#include "defs.h"
#include "../include/common.h"
struct
cspace
*
lcd_mk_cspace
(
void
)
{
struct
cspace
*
cspace
;
int
i
;
/*
* Allocate cspace
*/
cspace
=
kmalloc
(
sizeof
(
*
cspace
),
GFP_KERNEL
);
if
(
!
cspace
)
return
NULL
;
memset
(
cspace
,
0
,
sizeof
(
*
cspace
));
/* sets cnode types to invalid */
/*
* Initialize free list
*/
for
(
i
=
0
;
i
<
LCD_NUM_CAPS
;
i
++
)
list_add
(
&
cspace
->
free_list
,
&
cspace
->
cnodes
[
i
].
free_list
);
/*
* Initialize lock
*/
mutex_init
(
&
cspace
->
lock
);
return
cspace
;
}
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
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
;
};
drivers/lcd-prototype/api/defs.h
0 → 100644
View file @
25949c4a
/*
* Authors: Anton Burtsev <aburtsev@flux.utah.edu>
* Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*
* This simple prototype uses a global lock on an lcd's cspace.
*/
#ifndef LCD_PROTOTYPE_API_DEFS_H
#define LCD_PROTOTYPE_API_DEFS_H
#include <linux/spinlock.h>
#include <lcd-prototype/lcd.h>
/* CAPABILITIES -------------------------------------------------- */
enum
lcd_cap_type
{
LCD_CAP_TYPE_INVALID
=
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_list
;
};
/**
* Return current's cspace
*/
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
);
/**
* Acquires/releases global cspace lock. Must wrap calls to unsafe
* insert, lookup, etc. with lock/unlock.
*/
void
lcd_lock_cspace
(
struct
cspace
*
cspace
);
void
lcd_unlock_cspace
(
struct
cspace
*
cspace
);
/**
* (UNSAFE) Insert object into cspace at cptr with type and rights.
*/
int
__lcd_cap_insert
(
struct
cspace
*
cspace
,
cptr_t
cptr
,
void
*
object
,
enum
lcd_cap_type
type
,
int
rights
);
/**
* (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
);
}
/**
* (UNSAFE) Look up cnode in cspace at cptr.
*/
struct
cnode
*
__lcd_cnode_lookup
(
struct
cspace
*
cspace
,
cptr_t
cptr
);
/**
* (UNSAFE) Free cnode at cptr in cspace.
*/
void
__lcd_cap_drop
(
struct
cspace
*
cspace
,
cptr_t
cptr
);
/**
* (SAFE) Free cnode at cptr in cspace.
*/
static
inline
void
lcd_cap_drop
(
struct
cspace
*
cspace
,
cptr_t
cptr
)
{
lcd_lock_cspace
(
cspace
);
__lcd_cap_drop
(
cspace
,
cptr
);
lcd_unlock_cspace
(
cspace
);
}
/**
* (SAFE) Get capability type.
*/
static
inline
enum
lcd_cap_type
lcd_cap_type
(
struct
cspace
*
cspace
,
cptr_t
cptr
)
{
struct
cnode
*
cnode
;
enum
lcd_cap_type
type
;
lcd_lock_cspace
(
cspace
);
cnode
=
__lcd_lookup_cnode
(
cspace
,
cptr
);
type
=
cnode
->
type
;
lcd_unlock_cspace
(
cspace
);
return
type
;
}
/**
* (SAFE) Get capability rights.
*/
static
inline
int
lcd_cap_rights
(
struct
cspace
*
cspace
,
cptr_t
cptr
)
{
struct
cnode
*
cnode
;
int
rights
;
lcd_lock_cspace
(
cspace
);
cnode
=
__lcd_lookup_cnode
(
cspace
,
cptr
);
rights
=
cnode
->
rights
;
lcd_unlock_cspace
(
cspace
);
return
rights
;
}
static
inline
int
lcd_cap_can_read
()
{
return
rights
&
LCD_CAP_RIGHT_READ
;
}
static
inline
int
lcd_cap_can_write
(
int
rights
)
{
return
rights
&
LCD_CAP_RIGHT_WRITE
;
}
static
inline
int
lcd_cap_can_grant
(
int
rights
)
{
return
rights
&
LCD_CAP_RIGHT_GRANT
;
}
/**
* Deallocates cspace. Caller should ensure no one is trying to
* use the cspace (e.g., is waiting on the lock).
*/
void
lcd_rm_cspace
(
struct
cspace
*
cspace
);
#endif
/* LCD_PROTOTYPE_API_DEFS_H */
drivers/lcd-prototype/include/api-internal.h
0 → 100644
View file @
25949c4a
/*
* api-internal.h - direct access to hypervisor routines
*
* Author: Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*
* Use the higher-level calls in ipc.h. In the future,
* these won't be directly callable.
*/
#ifndef LCD_PROTOTYPE_API_INTERNAL_H
#define LCD_PROTOTYPE_API_INTERNAL_H
#include <lcd-prototype/lcd.h>
struct
lcd_handler
{
cptr_t
c
;
int
(
*
handler
)(
void
);
};
int
__lcd_send
(
cptr_t
c
);
int
__lcd_call
(
cptr_t
c
);
int
__lcd_select
(
struct
lcd_handlers
*
hs
,
int
hs_count
);
#endif
/* LCD_PROTOTYPE_API_INTERNAL_H */
drivers/lcd-prototype/include/api.h
0 → 100644
View file @
25949c4a
/*
* api.h - wrappers for calls into api code, via ipc
*
* Author: Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*
* Implemented by liblcd. Sets up and performs calls
* into api code, via ipc. See api code for more info.
*/
#ifndef LCD_PROTOTYPE_API_H
#define LCD_PROTOTYPE_API_H
#include <lcd-prototype/lcd.h>
int
lcd_mk_sync_endpoint
(
cptr_t
c
);
int
lcd_rm_sync_endpoint
(
cptr_t
c
);
#endif
/* LCD_PROTOTYPE_API_H */
drivers/lcd-prototype/include/common.h
0 → 100644
View file @
25949c4a
/*
* Author: Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
*
*/
#ifndef LCD_PROTOTYPE_COMMON_H
#define LCD_PROTOTYPE_COMMON_H
#define LCD_ERR(msg...) __lcd_err(__FILE__, __LINE__, msg)
static
inline
void
__lcd_err
(
char
*
file
,
int
lineno
,
char
*
fmt
,
...)
{
va_list
args
;
pr_err
(
"lcd-proto: %s:%d: error: "
,
file
,
lineno
);
va_start
(
args
,
fmt
);
vprintk
(
fmt
,
args
);
va_end
(
args
);
}
#define LCD_MSG(msg...) __lcd_msg(__FILE__, __LINE__, msg)
static
inline
void
__lcd_msg
(
char
*
file
,
int
lineno
,
char
*
fmt
,
...)
{
va_list
args
;