1 /*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #pragma once
8
9 /* Fastpath cap lookup. Returns a null_cap on failure. */
lookup_fp(cap_t cap,cptr_t cptr)10 static inline cap_t FORCE_INLINE lookup_fp(cap_t cap, cptr_t cptr)
11 {
12 word_t cptr2;
13 cte_t *slot;
14 word_t guardBits, radixBits, bits;
15 word_t radix, capGuard;
16
17 bits = 0;
18
19 if (unlikely(! cap_capType_equals(cap, cap_cnode_cap))) {
20 return cap_null_cap_new();
21 }
22
23 do {
24 guardBits = cap_cnode_cap_get_capCNodeGuardSize(cap);
25 radixBits = cap_cnode_cap_get_capCNodeRadix(cap);
26 cptr2 = cptr << bits;
27
28 capGuard = cap_cnode_cap_get_capCNodeGuard(cap);
29
30 /* Check the guard. Depth mismatch check is deferred.
31 The 32MinusGuardSize encoding contains an exception
32 when the guard is 0, when 32MinusGuardSize will be
33 reported as 0 also. In this case we skip the check */
34 if (likely(guardBits) && unlikely(cptr2 >> (wordBits - guardBits) != capGuard)) {
35 return cap_null_cap_new();
36 }
37
38 radix = cptr2 << guardBits >> (wordBits - radixBits);
39 slot = CTE_PTR(cap_cnode_cap_get_capCNodePtr(cap)) + radix;
40
41 cap = slot->cap;
42 bits += guardBits + radixBits;
43
44 } while (unlikely(bits < wordBits && cap_capType_equals(cap, cap_cnode_cap)));
45
46 if (unlikely(bits > wordBits)) {
47 /* Depth mismatch. We've overshot wordBits bits. The lookup we've done is
48 safe, but wouldn't be allowed by the slowpath. */
49 return cap_null_cap_new();
50 }
51
52 return cap;
53 }
54 /* make sure the fastpath functions conform with structure_*.bf */
thread_state_ptr_set_tsType_np(thread_state_t * ts_ptr,word_t tsType)55 static inline void thread_state_ptr_set_tsType_np(thread_state_t *ts_ptr, word_t tsType)
56 {
57 ts_ptr->words[0] = tsType;
58 }
59
thread_state_ptr_mset_blockingObject_tsType(thread_state_t * ts_ptr,word_t ep_ref,word_t tsType)60 static inline void thread_state_ptr_mset_blockingObject_tsType(thread_state_t *ts_ptr,
61 word_t ep_ref,
62 word_t tsType)
63 {
64 ts_ptr->words[0] = ep_ref | tsType;
65 }
66
67 #ifndef CONFIG_KERNEL_MCS
cap_reply_cap_ptr_new_np(cap_t * cap_ptr,word_t capReplyCanGrant,word_t capReplyMaster,word_t capTCBPtr)68 static inline void cap_reply_cap_ptr_new_np(cap_t *cap_ptr, word_t capReplyCanGrant,
69 word_t capReplyMaster, word_t capTCBPtr)
70 {
71 #ifdef __KERNEL_64__
72 cap_ptr->words[1] = (word_t)capTCBPtr;
73 cap_ptr->words[0] = (capReplyMaster) | (capReplyCanGrant << 1) |
74 ((word_t)cap_reply_cap << 59);
75 #else
76 cap_ptr->words[0] = TCB_REF(capTCBPtr) | (capReplyMaster << 4) |
77 (capReplyCanGrant << 5) | cap_reply_cap ;
78 #endif
79 }
80 #endif
81
endpoint_ptr_mset_epQueue_tail_state(endpoint_t * ep_ptr,word_t epQueue_tail,word_t state)82 static inline void endpoint_ptr_mset_epQueue_tail_state(endpoint_t *ep_ptr, word_t epQueue_tail,
83 word_t state)
84 {
85 ep_ptr->words[0] = epQueue_tail | state;
86 }
87
endpoint_ptr_set_epQueue_head_np(endpoint_t * ep_ptr,word_t epQueue_head)88 static inline void endpoint_ptr_set_epQueue_head_np(endpoint_t *ep_ptr, word_t epQueue_head)
89 {
90 ep_ptr->words[1] = epQueue_head;
91 }
92
93 #ifdef CONFIG_KERNEL_MCS
thread_state_ptr_set_replyObject_np(thread_state_t * ts_ptr,word_t reply)94 static inline void thread_state_ptr_set_replyObject_np(thread_state_t *ts_ptr, word_t reply)
95 {
96 assert(!thread_state_ptr_get_tcbQueued(ts_ptr));
97 assert(!thread_state_ptr_get_tcbInReleaseQueue(ts_ptr));
98 #if CONFIG_WORD_SIZE == 64
99 thread_state_ptr_set_replyObject(ts_ptr, REPLY_REF(reply));
100 #else
101 ts_ptr->words[1] = REPLY_REF(reply);
102 #endif
103 }
104
thread_state_get_replyObject_np(thread_state_t ts)105 static inline reply_t *thread_state_get_replyObject_np(thread_state_t ts)
106 {
107 assert(!thread_state_get_tcbQueued(ts));
108 assert(!thread_state_get_tcbInReleaseQueue(ts));
109 #if CONFIG_WORD_SIZE == 64
110 return REPLY_PTR(thread_state_get_replyObject(ts));
111 #else
112 return REPLY_PTR(ts.words[1]);
113 #endif
114 }
115 #endif
116
117 #include <arch/fastpath/fastpath.h>
118
119