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. */
10static 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 */
55static 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
60static 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
68static 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
82static 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
88static 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
94static 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
105static 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