seL4 is always in the top of memory, so the high bits of pointers are always 1. The autogenerated unpacking code doesn't know that, however, so will try to conditionally sign extend (in 64-bit mode), which wastes cycles in the fast path. Instead, we can do the unpacking ourselves and explicitly set the high bits.
103 lines
2.9 KiB
C
103 lines
2.9 KiB
C
/*
|
|
* Copyright 2014, General Dynamics C4 Systems
|
|
*
|
|
* This software may be distributed and modified according to the terms of
|
|
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
|
* See "LICENSE_GPLv2.txt" for details.
|
|
*
|
|
* @TAG(GD_GPL)
|
|
*/
|
|
|
|
#ifndef __FASTPATH_H
|
|
#define __FASTPATH_H
|
|
|
|
/* Fastpath cap lookup. Returns a null_cap on failure. */
|
|
static inline cap_t FORCE_INLINE
|
|
lookup_fp(cap_t cap, cptr_t cptr)
|
|
{
|
|
word_t cptr2;
|
|
cte_t *slot;
|
|
word_t guardBits, radixBits, bits;
|
|
word_t radix, capGuard;
|
|
|
|
bits = 0;
|
|
|
|
if (unlikely(! cap_capType_equals(cap, cap_cnode_cap))) {
|
|
return cap_null_cap_new();
|
|
}
|
|
|
|
do {
|
|
guardBits = cap_cnode_cap_get_capCNodeGuardSize(cap);
|
|
radixBits = cap_cnode_cap_get_capCNodeRadix(cap);
|
|
cptr2 = cptr << bits;
|
|
|
|
capGuard = cap_cnode_cap_get_capCNodeGuard(cap);
|
|
|
|
/* Check the guard. Depth mismatch check is deferred.
|
|
The 32MinusGuardSize encoding contains an exception
|
|
when the guard is 0, when 32MinusGuardSize will be
|
|
reported as 0 also. In this case we skip the check */
|
|
if (likely(guardBits) && unlikely(cptr2 >> (wordBits - guardBits) != capGuard)) {
|
|
return cap_null_cap_new();
|
|
}
|
|
|
|
radix = cptr2 << guardBits >> (wordBits - radixBits);
|
|
slot = cap_cnode_cap_get_capCNodePtr_fp(cap) + radix;
|
|
|
|
cap = slot->cap;
|
|
bits += guardBits + radixBits;
|
|
|
|
} while (unlikely(bits < wordBits && cap_capType_equals(cap, cap_cnode_cap)));
|
|
|
|
if (unlikely(bits > wordBits)) {
|
|
/* Depth mismatch. We've overshot wordBits bits. The lookup we've done is
|
|
safe, but wouldn't be allowed by the slowpath. */
|
|
return cap_null_cap_new();
|
|
}
|
|
|
|
return cap;
|
|
}
|
|
/* make sure the fastpath functions conform with structure_*.bf */
|
|
static inline void
|
|
thread_state_ptr_set_tsType_np(thread_state_t *ts_ptr, word_t tsType)
|
|
{
|
|
ts_ptr->words[0] = tsType;
|
|
}
|
|
|
|
static inline void
|
|
thread_state_ptr_mset_blockingObject_tsType(thread_state_t *ts_ptr,
|
|
word_t ep_ref,
|
|
word_t tsType)
|
|
{
|
|
ts_ptr->words[0] = ep_ref | tsType;
|
|
}
|
|
|
|
static inline void
|
|
cap_reply_cap_ptr_new_np(cap_t *cap_ptr, word_t capReplyMaster,
|
|
word_t capTCBPtr)
|
|
{
|
|
#ifdef __KERNEL_64__
|
|
cap_ptr->words[1] = (word_t)capTCBPtr;
|
|
cap_ptr->words[0] = (capReplyMaster) | ((word_t)cap_reply_cap << 59);
|
|
#else
|
|
cap_ptr->words[0] = TCB_REF(capTCBPtr) | (capReplyMaster << 4) |
|
|
cap_reply_cap ;
|
|
#endif
|
|
}
|
|
|
|
static inline void
|
|
endpoint_ptr_mset_epQueue_tail_state(endpoint_t *ep_ptr, word_t epQueue_tail,
|
|
word_t state)
|
|
{
|
|
ep_ptr->words[0] = epQueue_tail | state;
|
|
}
|
|
|
|
static inline void
|
|
endpoint_ptr_set_epQueue_head_np(endpoint_t *ep_ptr, word_t epQueue_head)
|
|
{
|
|
ep_ptr->words[1] = epQueue_head;
|
|
}
|
|
|
|
#include <arch/fastpath/fastpath.h>
|
|
|
|
#endif
|