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