298 lines
10 KiB
C
298 lines
10 KiB
C
/**
|
|
* \file
|
|
* \brief Arch-generic capability invocation wrappers specific to the monitors
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2007, 2008, 2009, 2010, 2016, ETH Zurich.
|
|
* All rights reserved.
|
|
*
|
|
* This file is distributed under the terms in the attached LICENSE file.
|
|
* If you do not find this file, copies can be found by writing to:
|
|
* ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
|
|
*/
|
|
|
|
#include "invocations.h"
|
|
|
|
#include <string.h> // for memset()
|
|
|
|
bool monitor_can_send_cap(struct capability *cap)
|
|
{
|
|
/* Cannot send caps of these types so send error */
|
|
return !((cap->type == ObjType_Null) || (cap->type == ObjType_EndPointLMP)
|
|
|| (cap->type == ObjType_Dispatcher) || (cap->type == ObjType_Kernel)
|
|
|| (cap->type == ObjType_IRQTable));
|
|
}
|
|
|
|
/**
|
|
* \brief Invoke the kernel cap to acquire the raw metadata of a cap.
|
|
*
|
|
* \param cap The cap to identify
|
|
* \param out Struct to return the metadata
|
|
*/
|
|
errval_t monitor_cap_identify(struct capref cap, struct capability *out)
|
|
{
|
|
// If it's a NULL cap reference, return a fabricated Null cap
|
|
if(capref_is_null(cap)) {
|
|
goto nullcap;
|
|
}
|
|
|
|
uint8_t level = get_cap_level(cap);
|
|
capaddr_t caddr = get_cap_addr(cap);
|
|
errval_t err = invoke_monitor_identify_cap(caddr, level, out);
|
|
if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP &&
|
|
err_no(err>>10) == SYS_ERR_CAP_NOT_FOUND)
|
|
{
|
|
// XXX: is it ok to return a fabricated null cap when doing cap
|
|
// identify on an empty slot? -SG, 2013-07-31
|
|
goto nullcap;
|
|
}
|
|
return err;
|
|
|
|
nullcap:
|
|
memset(out, 0, sizeof(struct capability));
|
|
out->type = ObjType_Null;
|
|
return SYS_ERR_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Invoke the kernel cap to acquire the raw metadata of a cap that is
|
|
* located off another domains root cnode
|
|
*
|
|
* \param croot The root cnode of the process to which this cap belongs
|
|
* \param cap The caddr of the cap to identify
|
|
* \param level CSpace level of the cap to identify
|
|
* \param out Struct to return the metadata
|
|
*/
|
|
errval_t monitor_domains_cap_identify(struct capref croot, capaddr_t cap,
|
|
int level, struct capability *out)
|
|
{
|
|
assert (out != NULL);
|
|
|
|
uint8_t rootcap_level = get_cap_level(croot);
|
|
capaddr_t rootcap_addr = get_cap_addr(croot);
|
|
|
|
return invoke_monitor_identify_domains_cap(rootcap_addr, rootcap_level,
|
|
cap, level, out);
|
|
}
|
|
|
|
/**
|
|
* Let the kernel know that this capability has remote relations, and read the
|
|
* resulting remote relation flags.
|
|
*/
|
|
errval_t monitor_domcap_remote_relations(struct capref croot, capaddr_t cptr,
|
|
int level, uint8_t relations,
|
|
uint8_t mask, uint8_t *ret_relations)
|
|
{
|
|
uint8_t rootcap_level = get_cap_level(croot);
|
|
capaddr_t rootcap_addr = get_cap_addr(croot);
|
|
|
|
return invoke_monitor_remote_relations(rootcap_addr, rootcap_level,
|
|
cptr, level, relations, mask,
|
|
ret_relations);
|
|
}
|
|
|
|
errval_t monitor_remote_relations(struct capref cap, uint8_t relations,
|
|
uint8_t mask, uint8_t *ret_relations)
|
|
{
|
|
uint8_t level = get_cap_level(cap);
|
|
capaddr_t cptr = get_cap_addr(cap);
|
|
return monitor_domcap_remote_relations(cap_root, cptr, level, relations,
|
|
mask, ret_relations);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
|
|
errval_t monitor_cap_has_relations(struct capref cap, uint8_t mask,
|
|
uint8_t *res)
|
|
{
|
|
capaddr_t caddr = get_cap_addr(cap);
|
|
uint8_t level = get_cap_level(cap);
|
|
return invoke_monitor_cap_has_relations(caddr, level, mask, res);
|
|
}
|
|
|
|
/**
|
|
* \brief Invoke the kernel cap to set the type of #cap to null
|
|
*/
|
|
errval_t monitor_nullify_cap(struct capref cap)
|
|
{
|
|
capaddr_t caddr = get_cap_addr(cap);
|
|
uint8_t level = get_cap_level(cap);
|
|
return invoke_monitor_nullify_cap(caddr, level);
|
|
}
|
|
|
|
/**
|
|
* \brief Invoke the kernel cap to create a new cap.
|
|
*
|
|
* \param dest Location to place the new cap in.
|
|
* \param cap Metadata of the cap to create
|
|
* \param owner Core that currently owns the cap
|
|
*/
|
|
errval_t monitor_cap_create(struct capref dest, struct capability *cap,
|
|
coreid_t owner)
|
|
{
|
|
capaddr_t caddr = get_cnode_addr(dest);
|
|
uint8_t level = get_cnode_level(dest);
|
|
size_t slot = dest.slot;
|
|
|
|
return invoke_monitor_create_cap((uint64_t*)cap, caddr, level, slot, owner);
|
|
}
|
|
|
|
/**
|
|
* \brief Retype a capability on behalf of another domains. Capabilities which
|
|
* are remote (cross-core) must be retyped through the monitor to maintain
|
|
* cross-core consistancy.
|
|
*/
|
|
errval_t monitor_retype_remote_cap(struct capref dest_start, struct capref src, gensize_t offset,
|
|
enum objtype newtype, gensize_t objsize,
|
|
gensize_t count)
|
|
{
|
|
// Address of destination cspace
|
|
capaddr_t dcs_addr = get_croot_addr(dest_start);
|
|
// Address of the cap to the destination CNode
|
|
capaddr_t dcn_addr = get_cnode_addr(dest_start);
|
|
// Depth/Level of destination cnode
|
|
enum cnode_type dcn_level = get_cnode_level(dest_start);
|
|
// Address of source cspace
|
|
capaddr_t scp_root = get_croot_addr(src);
|
|
// Address of source capability
|
|
capaddr_t scp_addr = get_cap_addr(src);
|
|
|
|
/*return invoke_monitor_remote_cap_retype(rootcap_addr, rootcap_level, src, offset,
|
|
newtype, objsize, count, to, slot, level);*/
|
|
return invoke_monitor_remote_cap_retype(scp_root, scp_addr, offset, newtype, objsize, count, dcs_addr, dcn_addr,dest_start.slot ,dcn_level);
|
|
}
|
|
|
|
errval_t monitor_domcap_retype_remote_cap(struct domcapref dest_start, struct domcapref src, gensize_t offset, enum objtype newtype, gensize_t objsize, gensize_t count, capaddr_t slot) {
|
|
return invoke_monitor_remote_cap_retype(get_croot_addr(src.croot), src.cptr, offset, newtype, objsize, count, get_croot_addr(dest_start.croot), dest_start.cptr ,slot ,dest_start.level);
|
|
}
|
|
|
|
|
|
errval_t monitor_create_caps(struct capref src_root, struct capref dest_root,
|
|
enum objtype newtype, gensize_t objsize,
|
|
size_t count, capaddr_t src,
|
|
int src_level, size_t offset, capaddr_t dest_cn,
|
|
int dest_level, cslot_t dest_slot)
|
|
{
|
|
capaddr_t src_root_cptr = get_cap_addr(src_root);
|
|
capaddr_t dest_root_cptr = get_cap_addr(dest_root);
|
|
|
|
return invoke_monitor_remote_cap_retype(src_root_cptr, src, offset,
|
|
newtype, objsize, count,
|
|
dest_root_cptr, dest_cn,
|
|
dest_slot, dest_level);
|
|
}
|
|
|
|
errval_t monitor_copy_if_exists(struct capability* cap, struct capref dest)
|
|
{
|
|
capaddr_t croot = get_croot_addr(dest);
|
|
capaddr_t caddr = get_cnode_addr(dest);
|
|
uint8_t level = get_cnode_level(dest);
|
|
size_t slot = dest.slot;
|
|
|
|
return invoke_monitor_copy_existing((uint64_t*)cap, croot, caddr, level, slot);
|
|
}
|
|
|
|
/**
|
|
* \brief Determine the current owner of a cap and its copies.
|
|
*/
|
|
errval_t monitor_get_cap_owner(struct capref croot, capaddr_t cptr, int level, coreid_t *ret_owner)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
|
|
return invoke_monitor_get_cap_owner(root_addr, root_level, cptr, level, ret_owner);
|
|
}
|
|
|
|
/**
|
|
* \brief Change the owner of a cap and its copies.
|
|
*/
|
|
errval_t monitor_set_cap_owner(struct capref croot, capaddr_t cptr, int level, coreid_t owner)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
|
|
return invoke_monitor_set_cap_owner(root_addr, root_level, cptr, level, owner);
|
|
}
|
|
|
|
/**
|
|
* \brief Lock the cap and its copies
|
|
*/
|
|
errval_t monitor_lock_cap(struct capref croot, capaddr_t cptr, int level)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
|
|
return invoke_monitor_lock_cap(root_addr, root_level, cptr, level);
|
|
}
|
|
|
|
/**
|
|
* \brief Unlock the cap and its copies
|
|
*/
|
|
errval_t monitor_unlock_cap(struct capref croot, capaddr_t cptr, int level)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
|
|
return invoke_monitor_unlock_cap(root_addr, root_level, cptr, level);
|
|
}
|
|
|
|
errval_t monitor_has_descendants(struct capability *cap, bool *res)
|
|
{
|
|
return invoke_monitor_has_descendants((uint64_t*)cap, res);
|
|
}
|
|
|
|
errval_t monitor_is_retypeable(struct capability *cap, gensize_t offset,
|
|
gensize_t objsize, size_t count)
|
|
{
|
|
return invoke_monitor_is_retypeable((uint64_t*)cap, offset, objsize, count);
|
|
}
|
|
|
|
errval_t monitor_delete_last(struct capref croot, capaddr_t cptr, int level, struct capref ret_cap)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
capaddr_t ret_cn = get_cnode_addr(ret_cap);
|
|
uint8_t ret_cn_level = get_cnode_level(ret_cap);
|
|
cslot_t ret_slot = ret_cap.slot;
|
|
return invoke_monitor_delete_last(root_addr, root_level, cptr, level,
|
|
ret_cn, ret_cn_level, ret_slot);
|
|
}
|
|
|
|
errval_t monitor_delete_foreigns(struct capref cap)
|
|
{
|
|
capaddr_t cptr = get_cap_addr(cap);
|
|
uint8_t level = get_cap_level(cap);
|
|
return invoke_monitor_delete_foreigns(cptr, level);
|
|
}
|
|
|
|
errval_t monitor_revoke_mark_target(struct capref croot, capaddr_t cptr,
|
|
int level)
|
|
{
|
|
capaddr_t root_addr = get_cap_addr(croot);
|
|
uint8_t root_level = get_cap_level(croot);
|
|
return invoke_monitor_revoke_mark_target(root_addr, root_level, cptr, level);
|
|
}
|
|
|
|
errval_t monitor_revoke_mark_relations(struct capability *cap)
|
|
{
|
|
return invoke_monitor_revoke_mark_relations((uint64_t*)cap);
|
|
}
|
|
|
|
errval_t monitor_delete_step(struct capref ret_cap)
|
|
{
|
|
return invoke_monitor_delete_step(get_cnode_addr(ret_cap),
|
|
get_cnode_level(ret_cap),
|
|
ret_cap.slot);
|
|
}
|
|
|
|
errval_t monitor_clear_step(struct capref ret_cap)
|
|
{
|
|
return invoke_monitor_clear_step(get_cnode_addr(ret_cap),
|
|
get_cnode_level(ret_cap),
|
|
ret_cap.slot);
|
|
}
|