1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libipc/lib/src/util_ipc.c Wed Aug 25 01:28:08 2021 +0200
1.3 @@ -0,0 +1,224 @@
1.4 +/*
1.5 + * Interprocess communication abstractions.
1.6 + *
1.7 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <l4/re/env.h>
1.26 +#include <l4/util/util.h>
1.27 +#include <l4/sys/factory.h>
1.28 +#include <l4/sys/irq.h>
1.29 +
1.30 +#include "cap_alloc.h"
1.31 +#include "mem_ipc.h"
1.32 +#include "util_ipc.h"
1.33 +
1.34 +
1.35 +
1.36 +/* Declare expected capabilities. */
1.37 +
1.38 +long _expect_capabilities(l4_buf_regs_t *bregs, int number)
1.39 +{
1.40 + int i;
1.41 + long err;
1.42 +
1.43 + for (i = 0; i < number; i++)
1.44 + {
1.45 + err = _expect_capability(bregs, i);
1.46 + if (err)
1.47 + return err;
1.48 + }
1.49 +
1.50 + return L4_EOK;
1.51 +}
1.52 +
1.53 +/* Indicate that a capability is expected at the given position. */
1.54 +
1.55 +long _expect_capability(l4_buf_regs_t *bregs, int item)
1.56 +{
1.57 + l4_cap_idx_t future = ipc_cap_alloc();
1.58 +
1.59 + if (l4_is_invalid_cap(future))
1.60 + return -L4_ENOENT;
1.61 +
1.62 + /* Indicate the expectation of a capability in return. */
1.63 +
1.64 + bregs->bdr = 0;
1.65 + bregs->br[item] = L4_RCV_ITEM_SINGLE_CAP | future;
1.66 +
1.67 + return L4_EOK;
1.68 +}
1.69 +
1.70 +/* Export in the message at the given position the given capability. */
1.71 +
1.72 +void _export_capability(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_cap_idx_t ref)
1.73 +{
1.74 + int words = l4_msgtag_words(tag);
1.75 +
1.76 + mregs->mr[words + item * 2] = 0 | L4_ITEM_MAP;
1.77 + mregs->mr[words + item * 2 + 1] = l4_obj_fpage(ref, 0, L4_FPAGE_RWX).raw;
1.78 +}
1.79 +
1.80 +/* Export a flexpage at the given position in the message. Here, the snd_base
1.81 + member of the flexpage structure is used to hold the "hot spot" value. */
1.82 +
1.83 +void _export_fpage(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t fpage)
1.84 +{
1.85 + int words = l4_msgtag_words(tag);
1.86 +
1.87 + mregs->mr[words + item * 2] = l4_map_control(fpage.snd_base, L4_FPAGE_CACHEABLE, 0);
1.88 + mregs->mr[words + item * 2 + 1] = fpage.fpage.raw;
1.89 +}
1.90 +
1.91 +/* Export a flexpage at the given position in the message. */
1.92 +
1.93 +void _export_page(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_umword_t hot_spot, l4_fpage_t fpage)
1.94 +{
1.95 + int words = l4_msgtag_words(tag);
1.96 +
1.97 + mregs->mr[words + item * 2] = l4_map_control(hot_spot, L4_FPAGE_CACHEABLE, 0);
1.98 + mregs->mr[words + item * 2 + 1] = fpage.raw;
1.99 +}
1.100 +
1.101 +/* Free expected capabilities held by the buffer registers. */
1.102 +
1.103 +void _free_expected_capabilities(l4_buf_regs_t *bregs, int number)
1.104 +{
1.105 + int i;
1.106 + l4_cap_idx_t cap;
1.107 +
1.108 + for (i = 0; i < number; i++)
1.109 + {
1.110 + cap = bregs->br[i] & L4_CAP_MASK;
1.111 + if (l4_is_valid_cap(cap))
1.112 + ipc_cap_free_um(cap);
1.113 + }
1.114 +}
1.115 +
1.116 +/* Import from the message the capability at the given item position. */
1.117 +
1.118 +long _import_capability(l4_msgtag_t tag, l4_buf_regs_t *bregs,
1.119 + l4_msg_regs_t *mregs, int item, l4_cap_idx_t *ref)
1.120 +{
1.121 + l4_snd_fpage_t fpage;
1.122 + long err = _import_fpage(tag, bregs, mregs, item, &fpage);
1.123 +
1.124 + if (err)
1.125 + return err;
1.126 +
1.127 + /* Check for a received capability. */
1.128 +
1.129 + if ((fpage.snd_base & 0x3e) != 0x38)
1.130 + return -L4_EIO;
1.131 +
1.132 + /* Update the supplied capability index. */
1.133 +
1.134 + *ref = bregs->br[item] & L4_CAP_MASK;
1.135 +
1.136 + return L4_EOK;
1.137 +}
1.138 +
1.139 +/* Import from the message a dataspace, mapping it to an address. */
1.140 +
1.141 +long _import_dataspace(l4_msgtag_t tag, l4_buf_regs_t *bregs,
1.142 + l4_msg_regs_t *mregs, int item, l4re_ds_t *mem,
1.143 + l4_addr_t *addr)
1.144 +{
1.145 + long err;
1.146 + unsigned long size;
1.147 +
1.148 + *mem = ipc_cap_alloc();
1.149 +
1.150 + err = _import_capability(tag, bregs, mregs, item, mem);
1.151 +
1.152 + if (err)
1.153 + {
1.154 + ipc_cap_free_um(*mem);
1.155 + return err;
1.156 + }
1.157 +
1.158 + /* Attach the dataspace to a region. */
1.159 +
1.160 + err = ipc_dataspace_size(*mem, &size);
1.161 + if (err)
1.162 + {
1.163 + ipc_cap_free_um(*mem);
1.164 + return err;
1.165 + }
1.166 +
1.167 + err = ipc_attach_dataspace(*mem, size, (void **) addr);
1.168 + if (err)
1.169 + {
1.170 + ipc_cap_free_um(*mem);
1.171 + return err;
1.172 + }
1.173 +
1.174 + return L4_EOK;
1.175 +}
1.176 +
1.177 +/* Import from the message the flexpage at the given item position. */
1.178 +
1.179 +long _import_fpage(l4_msgtag_t tag, l4_buf_regs_t *bregs,
1.180 + l4_msg_regs_t *mregs, int item, l4_snd_fpage_t *fpage)
1.181 +{
1.182 + int words = l4_msgtag_words(tag);
1.183 +
1.184 + /* NOTE: Currently, this function does not interact with the received items,
1.185 + but instead just returns the flexpage details from the message
1.186 + words. */
1.187 +
1.188 + (void) bregs;
1.189 +
1.190 + /* Obtain the item details for the capability. */
1.191 +
1.192 + if (item >= (int) l4_msgtag_items(tag))
1.193 + return -L4_EIO;
1.194 +
1.195 + /* Received items should start at zero. */
1.196 +
1.197 + fpage->snd_base = mregs->mr[words + item * 2];
1.198 + fpage->fpage.raw = mregs->mr[words + item * 2 + 1];
1.199 +
1.200 + return L4_EOK;
1.201 +}
1.202 +
1.203 +
1.204 +
1.205 +/* Convenience operations. */
1.206 +
1.207 +/* Send a reply to a call using the given message tag. */
1.208 +
1.209 +l4_msgtag_t util_ipc_reply(l4_msgtag_t tag)
1.210 +{
1.211 + return l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_NEVER);
1.212 +}
1.213 +
1.214 +/* Send a request using a call with the given message tag to the indicated
1.215 + endpoint. */
1.216 +
1.217 +l4_msgtag_t util_ipc_request(l4_msgtag_t tag, l4_cap_idx_t endpoint)
1.218 +{
1.219 + return l4_ipc_call(endpoint, l4_utcb(), tag, L4_IPC_NEVER);
1.220 +}
1.221 +
1.222 +/* Send data with the given message tag to the indicated endpoint. */
1.223 +
1.224 +l4_msgtag_t util_ipc_send(l4_msgtag_t tag, l4_cap_idx_t endpoint)
1.225 +{
1.226 + return l4_ipc_send(endpoint, l4_utcb(), tag, L4_IPC_NEVER);
1.227 +}