};
cap IPI is_always_copy {};
+
+cap ProcessManager is_always_copy {
+ // Capability to act as process manager, i.e. create new domain caps.
+};
+
+cap Domain from ProcessManager {
+ eq coreid coreid; /* Core where the domain was created. */
+ eq uint32 core_local_id; /* Core-local ID of the domain. */
+};
\ No newline at end of file
// ID capability
failure ID_SPACE_EXHAUSTED "ID space exhausted",
+ // Domain capability
+ failure DOMAIN_SPACE_EXHAUSTED "Domain space exhausted",
+
// I2C driver
// XXX: should not be in kernel
failure I2C_UNINITIALIZED "Trying to use uninitialized i2c controller",
failure COPY_PERF_MON "Error copying performance monitoring cap",
failure COPY_KERNEL_CAP "Error copying Kernel cap",
failure COPY_INHERITCN_CAP "Error copying capability from inherited cnode",
+ failure COPY_PROC_MNG_CAP "Error copying ProcessManager cap",
// make_runnable
failure DISPATCHER_SETUP "Dispatcher setup",
failure COPY_KERNEL_CAP "Failed to copy kernel cap to monitor",
failure COPY_BSP_KCB "Error copying BSP KernelControlBlock",
failure COPY_IPI "Failed to copy IPI cap to monitor",
+ failure COPY_PROC_MNG_CAP "Failed to copy ProcessManager cap to monitor",
failure COPY_PERF_MON "Failed to copy performance monitoring cap to monitor",
failure COPY_MODULECN_CAP "Failed to copy module CNode cap to monitor",
failure COPY_PACN_CAP "Failed to copy phys addr CNode cap to monitor",
/* well-known capabilities */
extern struct capref cap_root, cap_monitorep, cap_irq, cap_io, cap_dispatcher,
cap_selfep, cap_kernel, cap_initep, cap_perfmon, cap_dispframe,
- cap_sessionid, cap_ipi, cap_vroot, cap_argcn;
+ cap_sessionid, cap_ipi, cap_vroot, cap_argcn, cap_procmng;
/**
* \brief Returns the depth in the CSpace address of a cap
static inline bool type_is_vnode(enum objtype type)
{
- STATIC_ASSERT(48 == ObjType_Num, "Check VNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
return (type == ObjType_VNode_x86_64_pml4 ||
type == ObjType_VNode_x86_64_pdpt ||
static inline bool type_is_vroot(enum objtype type)
{
- STATIC_ASSERT(48 == ObjType_Num, "Check VNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
return (type == ObjType_VNode_x86_64_pml4 ||
#ifdef CONFIG_PAE
static inline size_t vnode_objbits(enum objtype type)
{
// This function should be emitted by hamlet or somesuch.
- STATIC_ASSERT(48 == ObjType_Num, "Check VNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
if (type == ObjType_VNode_x86_64_pml4 ||
type == ObjType_VNode_x86_64_pdpt ||
static inline size_t vnode_objsize(enum objtype type)
{
// This function should be emitted by hamlet or somesuch.
- STATIC_ASSERT(48 == ObjType_Num, "Check VNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
if (type == ObjType_VNode_x86_64_pml4 ||
type == ObjType_VNode_x86_64_pdpt ||
*/
static inline size_t vnode_entry_bits(enum objtype type) {
// This function should be emitted by hamlet or somesuch.
- STATIC_ASSERT(48 == ObjType_Num, "Check VNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
if (type == ObjType_VNode_x86_64_pml4 ||
type == ObjType_VNode_x86_64_pdpt ||
* @return Number of page table entries in bits
*/
static inline size_t cnode_get_slots(struct capability *cnode) {
- STATIC_ASSERT(48 == ObjType_Num, "Check CNode definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check CNode definitions");
switch (cnode->type) {
case ObjType_L1CNode:
static inline enum objtype get_mapping_type(enum objtype captype)
{
- STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all mapping types");
+ STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mapping types");
switch (captype) {
case ObjType_Frame:
static inline bool type_is_mapping(enum objtype type)
{
- STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all mapping types");
+ STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mapping types");
switch (type) {
case ObjType_Frame_Mapping:
static inline bool type_is_mappable(enum objtype type)
{
- STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all mappable types");
+ STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mappable types");
switch (type) {
case ObjType_Frame:
* Predicates related to sharing capabilities
*/
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static inline bool
distcap_needs_locality(enum objtype type)
{
}
}
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static inline bool
distcap_is_moveable(enum objtype type)
{
#define TASKCN_SLOT_SYSMEM 15 ///< ???
#define TASKCN_SLOT_COREBOOT 16 ///< Copy of realmode section used to bootstrap a core
#define TASKCN_SLOT_IPI 17 ///< Copy of IPI cap
-#define TASKCN_SLOTS_USER 18 ///< First free slot in taskcn for user
+#define TASKCN_SLOT_PROC_MNG 18 ///< Cap for the process manager
+#define TASKCN_SLOTS_USER 19 ///< First free slot in taskcn for user
/* Page CNode */
#define PAGECN_SLOT_VROOT 0 ///< First slot of page cnode is root page table
/**
* \brief Cleanup the last cap copy for an object and the object itself
*/
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all RAM-backed cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all RAM-backed cap types");
static errval_t
cleanup_last(struct cte *cte, struct cte *ret_ram_cap)
{
struct capability monitor_ep;
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
int sprint_cap(char *buf, size_t len, struct capability *cap)
{
switch (cap->type) {
return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
" core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
cap->u.id.core_local_id);
+ case ObjType_ProcessManager:
+ return snprintf(buf, len, "Process manager capability");
+
+ case ObjType_Domain:
+ return snprintf(buf, len, "Domain capability (coreid 0x%" PRIxCOREID
+ " core_local_id 0x%" PRIx32 ")", cap->u.domain.coreid,
+ cap->u.domain.core_local_id);
case ObjType_PerfMon:
return snprintf(buf, len, "PerfMon cap");
static uint32_t id_cap_counter = 1;
/**
+ * Domain capability core_local_id counter.
+ */
+static uint32_t domain_cap_counter = 1;
+
+/**
* Sets #dest equal to #src
*
* #dest cannot be in use.
// If you create more capability types you need to deal with them
// in the table below.
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static size_t caps_max_numobjs(enum objtype type, gensize_t srcsize, gensize_t objsize)
{
switch(type) {
case ObjType_Notify_IPI:
case ObjType_PerfMon:
case ObjType_IPI:
+ case ObjType_ProcessManager:
+ case ObjType_Domain:
case ObjType_VNode_ARM_l1_Mapping:
case ObjType_VNode_ARM_l2_Mapping:
case ObjType_VNode_AARCH64_l0_Mapping:
*
* For the meaning of the parameters, see the 'caps_create' function.
*/
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static errval_t caps_zero_objects(enum objtype type, lpaddr_t lpaddr,
gensize_t objsize, size_t count)
*/
// If you create more capability types you need to deal with them
// in the table below.
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, gensize_t size,
gensize_t objsize, size_t count, coreid_t owner,
err = set_cap(&dest_caps->cap, &temp_cap);
break;
+ case ObjType_Domain:
+ // Domain type does not refer to a kernel object
+ assert(lpaddr == 0);
+ assert(size == 0);
+ assert(objsize == 0);
+ assert(count == 1);
+
+ // Prevent wrap around
+ if (domain_cap_counter >= UINT32_MAX) {
+ return SYS_ERR_DOMAIN_SPACE_EXHAUSTED;
+ }
+
+ // Generate a new ID, core_local_id monotonically increases
+ temp_cap.u.domain.coreid = my_core_id;
+ temp_cap.u.domain.core_local_id = domain_cap_counter++;
+
+ // Insert the capability
+ err = set_cap(&dest_caps->cap, &temp_cap);
+ break;
case ObjType_IO:
temp_cap.u.io.start = 0;
temp_cap.u.io.end = 65535;
case ObjType_EndPoint:
case ObjType_Notify_IPI:
case ObjType_PerfMon:
+ case ObjType_ProcessManager:
// These types do not refer to a kernel object
assert(lpaddr == 0);
assert(size == 0);
//{{{1 Capability creation
/// check arguments, return true iff ok
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static bool check_caps_create_arguments(enum objtype type,
size_t bytes, size_t objsize,
bool exact)
return SYS_ERR_OK;
}
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
/// Retype caps
/// Create `count` new caps of `type` from `offset` in src, and put them in
/// `dest_cnode` starting at `dest_slot`.
src_cap->type == ObjType_Dispatcher ||
src_cap->type == ObjType_Frame ||
src_cap->type == ObjType_DevFrame ||
- src_cap->type == ObjType_IRQSrc);
+ src_cap->type == ObjType_IRQSrc ||
+ src_cap->type == ObjType_ProcessManager);
if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
base = get_address(src_cap);
/* check that we can create `count` objs from `offset` in source, and
* update base accordingly */
- if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc) {
+ if (src_cap->type != ObjType_Dispatcher && src_cap->type != ObjType_IRQSrc
+ && src_cap->type != ObjType_Domain) {
// TODO: convince ourselves that this is the only condition on offset
if (offset + count * objsize > get_size(src_cap)) {
debug(SUBSYS_CAPS, "caps_retype: cannot create all %zu objects"
}
/// Create copies to a cte
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
errval_t caps_copy_to_cte(struct cte *dest_cte, struct cte *src_cte, bool mint,
uintptr_t param1, uintptr_t param2)
{
static inline size_t caps_get_mapping_offset(struct capability *cap) {
// This function should be emitted by hamlet or somesuch.
- STATIC_ASSERT(48 == ObjType_Num, "Check Mapping definitions");
+ STATIC_ASSERT(50 == ObjType_Num, "Check Mapping definitions");
switch (cap->type) {
case ObjType_VNode_AARCH64_l3_Mapping:
* Cap tracing
*/
#ifdef TRACE_PMEM_CAPS
-STATIC_ASSERT(48 == ObjType_Num, "knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "knowledge of all cap types");
STATIC_ASSERT(64 >= ObjType_Num, "cap types fit in uint64_t bitfield");
#define MAPPING_TYPES \
((1ull<<ObjType_VNode_x86_64_pml4_Mapping) | \
err = caps_create_new(ObjType_IPI, 0, 0, 0, my_core_id, ipicap_cte);
assert(err_is_ok(err));
+ // Create process manager capability
+ struct cte *procmngcap_cte = caps_locate_slot(CNODE(st->taskcn),
+ TASKCN_SLOT_PROC_MNG);
+ err = caps_create_new(ObjType_ProcessManager, 0, 0, 0, my_core_id,
+ procmngcap_cte);
+ assert(err_is_ok(err));
+
/* Initialize dispatcher */
dispatcher_handle_t init_handle
= local_phys_to_mem(init_dispframe_cte->cap.u.frame.base);
.slot = TASKCN_SLOT_SESSIONID
};
+/// Process manager cap, allows creating domains.
+struct capref cap_procmng = {
+ .cnode = TASK_CNODE_INIT,
+ .slot = TASKCN_SLOT_PROC_MNG
+};
+
/// Root PML4 VNode
struct capref cap_vroot = {
.cnode = PAGE_CNODE_INIT,
/**
* \brief Function to do the actual printing based on the type of capability
*/
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
int debug_print_cap(char *buf, size_t len, struct capability *cap)
{
switch (cap->type) {
" core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
cap->u.id.core_local_id);
+ case ObjType_ProcessManager:
+ return snprintf(buf, len, "Process manager capability");
+
+ case ObjType_Domain:
+ return snprintf(buf, len, "Domain capability (coreid 0x%" PRIxCOREID
+ " core_local_id 0x%" PRIx32 ")", cap->u.domain.coreid,
+ cap->u.domain.core_local_id);
+
case ObjType_PerfMon:
return snprintf(buf, len, "PerfMon cap");
mdb_dump(mdb_root, 0);
}
-STATIC_ASSERT(48 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all cap types");
static void print_cte(struct cte *cte, char *indent_buff)
{
struct mdbnode *node = N(cte);
return err_push(err, INIT_ERR_COPY_IPI);
}
+ /* Give monitor the ProcessManager capability */
+ dest.cnode = si->taskcn;
+ dest.slot = TASKCN_SLOT_PROC_MNG;
+ src.cnode = cnode_task;
+ src.slot = TASKCN_SLOT_PROC_MNG;
+ err = cap_copy(dest, src);
+ if (err_is_fail(err)) {
+ return err_push(err, INIT_ERR_COPY_PROC_MNG_CAP);
+ }
+
/* Give monitor modulecn */
dest.cnode = si->rootcn;
dest.slot = ROOTCN_SLOT_MODULECN;
}
}
+ if (!strcmp(name, "proc_mgmt")) {
+ // Pass ProcessManager cap.
+ dest.cnode = si->taskcn;
+ dest.slot = TASKCN_SLOT_PROC_MNG;
+ src = cap_procmng;
+ err = cap_copy(dest, src);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "Can not give ProcessManager cap");
+ return err_push(err, SPAWN_ERR_COPY_PROC_MNG_CAP);
+ }
+ }
+
#ifdef __k1om__
if (!strcmp(name, "xeon_phi")) {
dest.cnode = si->taskcn;
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "nameservice_register failed");
}
+
+ // Try to create a few domains?
+ // TODO(razvan): Remove this.
+ size_t num_domains = 5;
+ struct capref domain_caps[num_domains];
+ for (size_t i = 1; i <= num_domains; ++i) {
+ err = slot_alloc(&domain_caps[i]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "slot_alloc domain_cap");
+ }
+ err = cap_retype(domain_caps[i], cap_procmng, 0, ObjType_Domain, 0, 1);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "cap_retype domain_cap from cap_procmng");
+ }
+ struct capability ret;
+ err = debug_cap_identify(domain_caps[i], &ret);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "cap identify domain_cap");
+ }
+ debug_printf("Process manager successfully created domain { .coreid=%u,"
+ " .core_local_id=%u } (%lu/%lu)\n", ret.u.domain.coreid,
+ ret.u.domain.core_local_id, i, num_domains);
+ }
}
static errval_t connect_cb(void *st, struct proc_mgmt_binding *b)