CNodes本质是一个结构体数组,该数组的元素是cte(capability table entry),cte中包含一个cap_t结构体和mdb_node_t结构体。CNodes的cte称为slot,下面是slot的结构体:
struct cte {
cap_t cap;
mdb_node_t cteMDBNode;
};
CNodes本身是一个内核对象,也有相应的cap。下面是CNode cap的结构体:
block cnode_cap(capCNodeRadix, capCNodeGuardSize, capCNodeGuard, capCNodePtr, capType) {
field capCNodeGuard 64
field capType 5
field capCNodeGuardSize 6
field capCNodeRadix 6
field_high capCNodePtr 47
}
capability的结构体的大小是16字节,它包含两部分,一部分是seL4_CapRights,另一部分是指向具体对象cap的指针。下面是cap的结构体和seL4_CapRights结构体:
struct cap {
uint64_t words[2];
};
block seL4_CapRights {
padding 32
padding 28
field capAllowGrantReply 1
field capAllowGrant 1
field capAllowRead 1
field capAllowWrite 1
}
sel4定义了如下几类cap(不同的架构可能会不同,本例是arm32架构):
enum cap_tag {
cap_null_cap = 0,
cap_untyped_cap = 2,
cap_endpoint_cap = 4,
cap_notification_cap = 6,
cap_reply_cap = 8,
cap_cnode_cap = 10,
cap_thread_cap = 12,
cap_small_frame_cap = 1,
cap_frame_cap = 3,
cap_asid_pool_cap = 5,
cap_page_table_cap = 7,
cap_page_directory_cap = 9,
cap_asid_control_cap = 11,
cap_irq_control_cap = 14,
cap_irq_handler_cap = 30,
cap_zombie_cap = 46,
cap_domain_cap = 62
};
从上面可以看出每一类cap里面具体包含了一些私有的访问控制规则,以endpoint为例:endpoint cap里面包含了四项权限,分别是:capCanGrantReply()、capCanGrant()、capCanReceive(该endpoint能否接受消息)、capCanSend(该endpoint能否发送消息)。
同时cap_t也包含三个通用的规则,分别是 capAllowGrantReply、capAllowGrant、capAllowRead和capAllowWrite。
下面是endpoint cap结构体:
block endpoint_cap(capEPBadge, capCanGrantReply, capCanGrant, capCanSend,
capCanReceive, capEPPtr, capType) {
field capEPBadge 64
field capType 5
field capCanGrantReply 1
field capCanGrant 1
field capCanReceive 1
field capCanSend 1
padding 7
field_high capEPPtr 48
}
seL4_CNode_Copy
seL4_CNode_Delete
seL4_CNode_Mint
seL4_CNode_Move
seL4_CNode_Mutate
seL4_CNode_Revoke
seL4_CNode_Rotate
seL4_CNode_SaveCaller
以seL4_CNode_Mint为例,该函数的参数有:
seL4_CNode_Mint函数具体工作流程如下:
resolveAddressBits根据CNode(nodeCap)、index(capptr)和depth(n_bits)找到slot。具体流程如下:
index和n_bits位数是一致的。
resolveAddressBits_ret_t resolveAddressBits(cap_t nodeCap, cptr_t capptr, word_t n_bits)
{
......
while (1) {
radixBits = cap_cnode_cap_get_capCNodeRadix(nodeCap);
guardBits = cap_cnode_cap_get_capCNodeGuardSize(nodeCap);
levelBits = radixBits + guardBits;
capGuard = cap_cnode_cap_get_capCNodeGuard(nodeCap);
guard = (capptr >> ((n_bits - guardBits) & MASK(wordRadix))) & MASK(guardBits);
if (unlikely(guardBits > n_bits || guard != capGuard)) {
current_lookup_fault =
lookup_fault_guard_mismatch_new(capGuard, n_bits, guardBits);
ret.status = EXCEPTION_LOOKUP_FAULT;
return ret;
}
if (unlikely(levelBits > n_bits)) {
current_lookup_fault =
lookup_fault_depth_mismatch_new(levelBits, n_bits);
ret.status = EXCEPTION_LOOKUP_FAULT;
return ret;
}
offset = (capptr >> (n_bits - levelBits)) & MASK(radixBits);
slot = CTE_PTR(cap_cnode_cap_get_capCNodePtr(nodeCap)) + offset;
if (likely(n_bits <= levelBits)) {
ret.status = EXCEPTION_NONE;
ret.slot = slot;
ret.bitsRemaining = 0;
return ret;
}
/** GHOSTUPD: "(\<acute>levelBits > 0, id)" */
n_bits -= levelBits;
nodeCap = slot->cap;
if (unlikely(cap_get_capType(nodeCap) != cap_cnode_cap)) {
ret.status = EXCEPTION_NONE;
ret.slot = slot;
ret.bitsRemaining = n_bits;
return ret;
}
}
ret.status = EXCEPTION_NONE;
return ret;
}
sel4提供cdt来保存cap的变化过程,其本质是一个双向链表。比如:在删除某一个cap时,如果有其他的cap是通过该cap mint创建的,则也需要删除。
//mapping database
block mdb_node {
padding 16
field_high mdbNext 46
field mdbRevocable 1
field mdbFirstBadged 1
field mdbPrev 64
}
sel4源码解析(一) - sel4内核对象
sel4源码解析(二) - CSpace
sel4源码解析(三) - sel4系统调用处理流程
sel4源码解析(四) - ipc
sel4源码解析(五) - Notification
sel4源码解析(六) - 进程
sel4源码解析(七) - vspace