1/**
2 * \file
3 * \brief
4 */
5
6/*
7 * Copyright (c) 2007, 2008, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef ARCH_X86_64_BARRELFISH_LMP_CHAN_H
16#define ARCH_X86_64_BARRELFISH_LMP_CHAN_H
17
18#include <barrelfish/syscall_arch.h>
19#include <barrelfish/caddr.h>
20#include <barrelfish/cspace.h>
21#include <barrelfish_kpi/lmp.h>
22
23/**
24 * \brief Send a message on the given LMP endpoint, if possible
25 *
26 * Non-blocking, may fail if there is no space in the receiver's endpoint.
27 *
28 * \param ep Remote endpoint
29 * \param flags LMP send flags
30 * \param send_cap (Optional) capability to send with the message
31 * \param length_words Length of the message in words; payload beyond this
32 *                      size will not be delivered
33 * \param arg1..N Message payload
34 */
35static inline errval_t lmp_ep_send(struct capref ep, lmp_send_flags_t flags,
36                                   struct capref send_cap, uint8_t length_words,
37                                   uint64_t arg1, uint64_t arg2, uint64_t arg3,
38                                   uint64_t arg4, uint64_t arg5, uint64_t arg6,
39                                   uint64_t arg7, uint64_t arg8, uint64_t arg9,
40                                   uint64_t arg10)
41{
42    uint8_t send_level = get_cap_level(send_cap);
43    capaddr_t send_cptr = get_cap_addr(send_cap);
44
45    if(debug_notify_syscall) {
46        printf("memcached: lmp_ep_send while forbidden from %p, %p, %p\n",
47               __builtin_return_address(0),
48               __builtin_return_address(1),
49               __builtin_return_address(2));
50    }
51
52#ifndef TRACE_DISABLE_LRPC
53    // Do an LRPC if possible
54    if (send_cptr == 0 && send_level == 0          // Not sending a cap
55        && (flags & LMP_FLAG_SYNC) != 0           // sync option
56        && length_words <= LRPC_MSG_LENGTH) {     // Check length
57
58        assert(LRPC_MSG_LENGTH == 4);
59        assert(get_croot_addr(ep) == CPTR_ROOTCN);
60        return syscall6(SYSCALL_LRPC, get_cap_addr(ep), arg1, arg2, arg3, arg4).error;
61    }
62#endif
63
64    uint8_t invoke_level = get_cap_level(ep);
65    capaddr_t invoke_cptr = get_cap_addr(ep);
66
67    return syscall(SYSCALL_INVOKE,
68                   (uint64_t)invoke_cptr << 32 | (uint64_t)send_level << 24 |
69                   (uint64_t)invoke_level << 16 | (uint64_t)length_words << 8 |
70                   flags, send_cptr,
71                   arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
72                   arg10).error;
73}
74
75#define lmp_ep_send10(ep, flags, send_cap, a, b, c, d, e, f, g, h, i, j) \
76  lmp_ep_send((ep), (flags), (send_cap), 10, (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))
77#define lmp_ep_send9(ep, flags, send_cap, a, b, c, d, e, f, g, h, i) \
78  lmp_ep_send((ep), (flags), (send_cap), 9, (a), (b), (c), (d), (e), (f), (g), (h), (i), 0)
79#define lmp_ep_send8(ep, flags, send_cap, a, b, c, d, e, f, g, h) \
80  lmp_ep_send((ep), (flags), (send_cap), 8, (a), (b), (c), (d), (e), (f), (g), (h), 0, 0)
81#define lmp_ep_send7(ep, flags, send_cap, a, b, c, d, e, f, g) \
82  lmp_ep_send((ep), (flags), (send_cap), 7, (a), (b), (c), (d), (e), (f), (g), 0, 0, 0)
83#define lmp_ep_send6(ep, flags, send_cap, a, b, c, d, e, f) \
84  lmp_ep_send((ep), (flags), (send_cap), 6, (a), (b), (c), (d), (e), (f), 0, 0, 0, 0)
85#define lmp_ep_send5(ep, flags, send_cap, a, b, c, d, e) \
86  lmp_ep_send((ep), (flags), (send_cap), 5, (a), (b), (c), (d), (e), 0, 0, 0, 0, 0)
87#define lmp_ep_send4(ep, flags, send_cap, a, b, c, d) \
88  lmp_ep_send((ep), (flags), (send_cap), 4, (a), (b), (c), (d), 0, 0, 0, 0, 0, 0)
89#define lmp_ep_send3(ep, flags, send_cap, a, b, c) \
90  lmp_ep_send((ep), (flags), (send_cap), 3, (a), (b), (c), 0, 0, 0, 0, 0, 0, 0)
91#define lmp_ep_send2(ep, flags, send_cap, a, b) \
92  lmp_ep_send((ep), (flags), (send_cap), 2, (a), (b), 0, 0, 0, 0, 0, 0, 0, 0)
93#define lmp_ep_send1(ep, flags, send_cap, a) \
94  lmp_ep_send((ep), (flags), (send_cap), 1, (a), 0, 0, 0, 0, 0, 0, 0, 0, 0)
95#define lmp_ep_send0(ep, flags, send_cap) \
96  lmp_ep_send((ep), (flags), (send_cap), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
97
98#define lmp_chan_send(lc, flags, send_cap, len, a, b, c, d, e, f, g, h, i, j) \
99  lmp_ep_send((lc)->remote_cap, (flags), (send_cap), (len), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))
100
101#define lmp_chan_send10(lc, flags, send_cap, a, b, c, d, e, f, g, h, i, j) \
102  lmp_ep_send10((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))
103#define lmp_chan_send9(lc, flags, send_cap, a, b, c, d, e, f, g, h, i) \
104  lmp_ep_send9((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e), (f), (g), (h), (i))
105#define lmp_chan_send8(lc, flags, send_cap, a, b, c, d, e, f, g, h) \
106  lmp_ep_send8((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e), (f), (g), (h))
107#define lmp_chan_send7(lc, flags, send_cap, a, b, c, d, e, f, g) \
108  lmp_ep_send7((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e), (f), (g))
109#define lmp_chan_send6(lc, flags, send_cap, a, b, c, d, e, f) \
110  lmp_ep_send6((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e), (f))
111#define lmp_chan_send5(lc, flags, send_cap, a, b, c, d, e) \
112  lmp_ep_send5((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d), (e))
113#define lmp_chan_send4(lc, flags, send_cap, a, b, c, d) \
114  lmp_ep_send4((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d))
115#define lmp_chan_send3(lc, flags, send_cap, a, b, c) \
116  lmp_ep_send3((lc)->remote_cap, (flags), (send_cap), (a), (b), (c))
117#define lmp_chan_send2(lc, flags, send_cap, a, b) \
118  lmp_ep_send2((lc)->remote_cap, (flags), (send_cap), (a), (b))
119#define lmp_chan_send1(lc, flags, send_cap, a) \
120  lmp_ep_send1((lc)->remote_cap, (flags), (send_cap), (a))
121#define lmp_chan_send0(lc, flags, send_cap) \
122  lmp_ep_send0((lc)->remote_cap, (flags), (send_cap))
123
124#endif // ARCH_X86_64_BARRELFISH_LMP_CHAN_H
125