mirror of
https://github.com/drasko/codezero.git
synced 2026-02-14 19:03:16 +01:00
Substantially fixed cap_split() behaviour.
Need to fix ipc flags capability checking yet.
This commit is contained in:
@@ -103,6 +103,118 @@ void cap_list_print(struct cap_list *cap_list)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#define PAGER_TOTAL_MUTEX 5
|
||||
int setup_children_mutex(int total_caps, struct cap_list *cap_list)
|
||||
{
|
||||
struct capability *diff_cap, *mutex_cap;
|
||||
|
||||
struct task_ids ids;
|
||||
int err;
|
||||
|
||||
l4_getid(&ids);
|
||||
|
||||
cap_list_print(cap_list);
|
||||
|
||||
/* Find out own mutex capability on our own container */
|
||||
list_foreach_struct(mutex_cap, &cap_list->caps, list) {
|
||||
if (cap_type(mutex_cap) == CAP_TYPE_QUANTITY &&
|
||||
cap_rtype(mutex_cap) == CAP_RTYPE_MUTEXPOOL)
|
||||
goto found;
|
||||
}
|
||||
printf("cont%d: %s: FATAL: Could not find ipc "
|
||||
"capability to own container.\n",
|
||||
__cid(ids.tid), __FUNCTION__);
|
||||
BUG();
|
||||
|
||||
found:
|
||||
/* Create a new capability */
|
||||
BUG_ON(!(diff_cap = kzalloc(sizeof(*mutex_cap))));
|
||||
|
||||
/* Copy it over to new mutex cap buffer */
|
||||
memcpy(diff_cap, mutex_cap, sizeof (*mutex_cap));
|
||||
|
||||
/*
|
||||
* We would like to take some mutexes,
|
||||
* and leave the rest to children.
|
||||
*
|
||||
* We set up a capability that we want
|
||||
* to separate out from the original
|
||||
*/
|
||||
if (mutex_cap->size <= PAGER_TOTAL_MUTEX) {
|
||||
printf("%s: FATAL: Can't reserve enough mutexes "
|
||||
"for children. capid = %d, mutexes = %lu, "
|
||||
"pager needs = %d\n", __FUNCTION__,
|
||||
mutex_cap->capid, mutex_cap->size,
|
||||
PAGER_TOTAL_MUTEX);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Reserve out some mutexes to self */
|
||||
diff_cap->size = PAGER_TOTAL_MUTEX;
|
||||
|
||||
/* Split the mutex capability, passing the difference */
|
||||
if ((err = l4_capability_control(CAP_CONTROL_SPLIT,
|
||||
0, 0, 0, diff_cap)) < 0) {
|
||||
printf("l4_capability_control() replication of "
|
||||
"ipc capability failed.\n Could not "
|
||||
"complete CAP_CONTROL_SPLIT request on cap (%d), "
|
||||
"err = %d.\n", diff_cap->capid, err);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* The returned one is the given diff, but
|
||||
* created as a new capability, add it to list
|
||||
*/
|
||||
cap_list_insert(diff_cap, cap_list);
|
||||
cap_list_print(cap_list);
|
||||
|
||||
/*
|
||||
* Share the remainder capability with our container.
|
||||
*
|
||||
* This effectively enables all threads/spaces in this container
|
||||
* to use this pool of mutexes.
|
||||
*/
|
||||
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE,
|
||||
mutex_cap->capid, 0, 0)) < 0) {
|
||||
printf("l4_capability_control() sharing of "
|
||||
"capabilities failed.\n Could not "
|
||||
"complete CAP_CONTROL_SHARE request.\n");
|
||||
BUG();
|
||||
}
|
||||
cap_list_print(cap_list);
|
||||
|
||||
/* Find mutex syscall operation capability on our own container */
|
||||
list_foreach_struct(mutex_cap, &cap_list->caps, list) {
|
||||
if (cap_type(mutex_cap) == CAP_TYPE_UMUTEX &&
|
||||
cap_rtype(mutex_cap) == CAP_RTYPE_CONTAINER)
|
||||
goto found2;
|
||||
}
|
||||
printf("cont%d: %s: FATAL: Could not find UMUTEX "
|
||||
"capability to own container.\n",
|
||||
__cid(ids.tid), __FUNCTION__);
|
||||
BUG();
|
||||
|
||||
found2:
|
||||
|
||||
/*
|
||||
* Share it with our container.
|
||||
*
|
||||
* This effectively enables all threads/spaces in this container
|
||||
* to use this pool of mutexes.
|
||||
*/
|
||||
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE,
|
||||
mutex_cap->capid, 0, 0)) < 0) {
|
||||
printf("l4_capability_control() sharing of "
|
||||
"capabilities failed.\n Could not "
|
||||
"complete CAP_CONTROL_SHARE request.\n");
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Replicate, deduce and grant to children the capability to
|
||||
* talk to us only.
|
||||
@@ -115,7 +227,7 @@ void cap_list_print(struct cap_list *cap_list)
|
||||
* into a capability to only talk to our current space. Our space is a
|
||||
* reduced target, since it is a subset contained in our container.
|
||||
*/
|
||||
int setup_children_caps(int total_caps, struct cap_list *cap_list)
|
||||
int setup_children_ipc(int total_caps, struct cap_list *cap_list)
|
||||
{
|
||||
struct capability *ipc_cap, *cap;
|
||||
struct task_ids ids;
|
||||
@@ -195,6 +307,13 @@ found:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setup_children_caps(int total_caps, struct cap_list *cap_list)
|
||||
{
|
||||
setup_children_ipc(total_caps, cap_list);
|
||||
setup_children_mutex(total_caps, cap_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy all init-memory allocated capabilities */
|
||||
void copy_boot_capabilities(int ncaps)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#define __TASKNAME__ "test0"
|
||||
|
||||
//#define TEST_VERBOSE_PRINT
|
||||
// #define TEST_VERBOSE_PRINT
|
||||
#if defined (TEST_VERBOSE_PRINT)
|
||||
#define test_printf(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
|
||||
@@ -63,9 +63,12 @@ int main(int argc, char *argv[])
|
||||
user_mutex_test();
|
||||
}
|
||||
|
||||
/*
|
||||
exectest(parent_of_all);
|
||||
|
||||
while (1)
|
||||
wait_pager(pagerid);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <tests.h>
|
||||
#include <l4/api/capability.h>
|
||||
#include <l4/generic/cap-types.h>
|
||||
#include <l4lib/capability.h>
|
||||
#include <capability.h>
|
||||
|
||||
/*
|
||||
* Full ipc test. Sends/receives full utcb, done with the pager.
|
||||
@@ -48,26 +46,6 @@ void ipc_full_test(void)
|
||||
printf("FULL IPC TEST: -- FAILED --\n");
|
||||
}
|
||||
|
||||
int cap_request_pager(struct capability *cap)
|
||||
{
|
||||
int err;
|
||||
|
||||
write_mr(L4SYS_ARG0, (u32)cap);
|
||||
|
||||
if ((err = l4_sendrecv(pagerid, pagerid,
|
||||
L4_REQUEST_CAPABILITY)) < 0) {
|
||||
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check if syscall itself was successful */
|
||||
if ((err = l4_get_retval()) < 0) {
|
||||
printf("%s: Error: %d\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an extended ipc test that is done between 2 tasks that fork.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <tests.h>
|
||||
#include <capability.h>
|
||||
|
||||
/*
|
||||
* This structure is placed at the head of shared memory.
|
||||
@@ -36,7 +37,9 @@ int user_mutex_test(void)
|
||||
{
|
||||
pid_t child, parent;
|
||||
int map_size = PAGE_SIZE;
|
||||
struct capability cap;
|
||||
void *base;
|
||||
int err;
|
||||
|
||||
/* Get parent pid */
|
||||
parent = getpid();
|
||||
@@ -73,6 +76,27 @@ int user_mutex_test(void)
|
||||
else
|
||||
test_printf("Child %d running.\n", getpid());
|
||||
|
||||
/*
|
||||
* Request capability to ipc to each other from pager
|
||||
* (Actually only the sender needs it)
|
||||
*/
|
||||
memset(&cap, 0, sizeof(cap));
|
||||
if (child) {
|
||||
cap.owner = parent;
|
||||
cap.resid = child;
|
||||
} else {
|
||||
cap.owner = getpid();
|
||||
cap.resid = parent;
|
||||
}
|
||||
|
||||
cap.type = CAP_TYPE_IPC | CAP_RTYPE_THREAD;
|
||||
cap.access = CAP_IPC_EXTENDED | CAP_IPC_SEND | CAP_IPC_RECV;
|
||||
if ((err = cap_request_pager(&cap)) < 0) {
|
||||
printf("Ipc capability request failed. "
|
||||
"err = %d\n", err);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Child locks and produces */
|
||||
if (child == 0) {
|
||||
|
||||
@@ -107,7 +131,11 @@ int user_mutex_test(void)
|
||||
|
||||
}
|
||||
/* Sync with the parent */
|
||||
l4_send(parent, L4_IPC_TAG_SYNC);
|
||||
if ((err = l4_send_full(parent, L4_IPC_TAG_SYNC)) < 0) {
|
||||
printf("Error: l4_send() failed with %d\n", err);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
|
||||
/* Parent locks and consumes */
|
||||
} else {
|
||||
@@ -141,7 +169,10 @@ int user_mutex_test(void)
|
||||
l4_thread_switch(0);
|
||||
}
|
||||
/* Sync with the child */
|
||||
l4_receive(child);
|
||||
if ((err = l4_receive_full(child)) < 0) {
|
||||
printf("Error: l4_receive() failed with %d\n", err);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
// test_printf("Parent checking validity of value.\n");
|
||||
if (shared_page->shared_var != 0)
|
||||
|
||||
Reference in New Issue
Block a user