1/**
2 * \file
3 * \brief Arch-generic capability invocation wrappers specific to the monitors
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include "monitor.h"
16
17bool monitor_can_send_cap(struct capability *cap)
18{
19    /* Cannot send caps of these types so send error */
20    return !((cap->type == ObjType_Null) || (cap->type == ObjType_EndPoint)
21        || (cap->type == ObjType_Dispatcher) || (cap->type == ObjType_Kernel)
22        || (cap->type == ObjType_IRQTable));
23}
24
25/**
26 * \brief Invoke the kernel cap to acquire the raw metadata of a cap.
27 *
28 * \param cap     The cap to identify
29 * \param out     Struct to return the metadata
30 */
31errval_t monitor_cap_identify(struct capref cap, struct capability *out)
32{
33    // If it's a NULL cap reference, return a fabricated Null cap
34    if(capref_is_null(cap)) {
35        goto nullcap;
36    }
37
38    uint8_t level = get_cap_level(cap);
39    capaddr_t caddr = get_cap_addr(cap);
40    errval_t err = invoke_monitor_identify_cap(caddr, level, out);
41    if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP &&
42        err_no(err>>10) == SYS_ERR_CAP_NOT_FOUND)
43    {
44        // XXX: is it ok to return a fabricated null cap when doing cap
45        // identify on an empty slot? -SG, 2013-07-31
46        goto nullcap;
47    }
48    return err;
49
50nullcap:
51    memset(out, 0, sizeof(struct capability));
52    out->type = ObjType_Null;
53    return SYS_ERR_OK;
54}
55
56
57/**
58 * \brief Invoke the kernel cap to acquire the raw metadata of a cap that is
59 * located off another domains root cnode
60 *
61 * \param croot   The root cnode of the process to which this cap belongs
62 * \param cap     The caddr of the cap to identify
63 * \param level   CSpace level of the cap to identify
64 * \param out     Struct to return the metadata
65 */
66errval_t monitor_domains_cap_identify(struct capref croot, capaddr_t cap,
67                                      int level, struct capability *out)
68{
69    assert (out != NULL);
70
71    uint8_t rootcap_level = get_cap_level(croot);
72    capaddr_t rootcap_addr = get_cap_addr(croot);
73
74    return invoke_monitor_identify_domains_cap(rootcap_addr, rootcap_level,
75                                               cap, level, out);
76}
77
78/**
79 * Let the kernel know that this capability has remote relations, and read the
80 * resulting remote relation flags.
81 */
82errval_t monitor_domcap_remote_relations(struct capref croot, capaddr_t cptr,
83                                         int level, uint8_t relations,
84                                         uint8_t mask, uint8_t *ret_relations)
85{
86    uint8_t rootcap_level = get_cap_level(croot);
87    capaddr_t rootcap_addr = get_cap_addr(croot);
88
89    return invoke_monitor_remote_relations(rootcap_addr, rootcap_level,
90                                           cptr, level, relations, mask,
91                                           ret_relations);
92}
93
94errval_t monitor_remote_relations(struct capref cap, uint8_t relations,
95                                  uint8_t mask, uint8_t *ret_relations)
96{
97    uint8_t level = get_cap_level(cap);
98    capaddr_t cptr = get_cap_addr(cap);
99    return monitor_domcap_remote_relations(cap_root, cptr, level, relations,
100                                           mask, ret_relations);
101}
102
103/**
104 *
105 */
106
107errval_t monitor_cap_has_relations(struct capref cap, uint8_t mask,
108                                   uint8_t *res)
109{
110    capaddr_t caddr = get_cap_addr(cap);
111    uint8_t level = get_cap_level(cap);
112    return invoke_monitor_cap_has_relations(caddr, level, mask, res);
113}
114
115/**
116 * \brief Invoke the kernel cap to set the type of #cap to null
117 */
118errval_t monitor_nullify_cap(struct capref cap)
119{
120    capaddr_t caddr = get_cap_addr(cap);
121    uint8_t level = get_cap_level(cap);
122    return invoke_monitor_nullify_cap(caddr, level);
123}
124
125/**
126 * \brief Invoke the kernel cap to create a new cap.
127 *
128 * \param dest     Location to place the new cap in.
129 * \param cap      Metadata of the cap to create
130 * \param owner    Core that currently owns the cap
131 */
132errval_t monitor_cap_create(struct capref dest, struct capability *cap,
133                            coreid_t owner)
134{
135    capaddr_t caddr = get_cnode_addr(dest);
136    uint8_t level = get_cnode_level(dest);
137    size_t  slot  = dest.slot;
138
139    return invoke_monitor_create_cap((uint64_t*)cap, caddr, level, slot, owner);
140}
141
142/**
143 * \brief Retype a capability on behalf of another domains.  Capabilities which
144 * are remote (cross-core) must be retyped through the monitor to maintain
145 * cross-core consistancy.
146 */
147errval_t monitor_retype_remote_cap(struct capref croot, capaddr_t src, gensize_t offset,
148                                   enum objtype newtype, gensize_t objsize,
149                                   gensize_t count, capaddr_t to, capaddr_t slot, int level)
150{
151    uint8_t rootcap_level = get_cap_level(croot);
152    capaddr_t rootcap_addr = get_cap_addr(croot);
153
154    return invoke_monitor_remote_cap_retype(rootcap_addr, rootcap_level, src, offset,
155                                            newtype, objsize, count, to, slot, level);
156}
157
158errval_t monitor_create_caps(struct capref src_root, struct capref dest_root,
159                             enum objtype newtype, gensize_t objsize,
160                             size_t count, capaddr_t src,
161                             int src_level, size_t offset, capaddr_t dest_cn,
162                             int dest_level, cslot_t dest_slot)
163{
164    capaddr_t src_root_cptr = get_cap_addr(src_root);
165    capaddr_t dest_root_cptr = get_cap_addr(dest_root);
166
167    return invoke_monitor_remote_cap_retype(src_root_cptr, src, offset,
168                                            newtype, objsize, count,
169                                            dest_root_cptr, dest_cn,
170                                            dest_slot, dest_level);
171}
172
173errval_t monitor_copy_if_exists(struct capability* cap, struct capref dest)
174{
175    capaddr_t croot = get_croot_addr(dest);
176    capaddr_t caddr = get_cnode_addr(dest);
177    uint8_t level = get_cnode_level(dest);
178    size_t  slot  = dest.slot;
179
180    return invoke_monitor_copy_existing((uint64_t*)cap, croot, caddr, level, slot);
181}
182
183/**
184 * \brief Determine the current owner of a cap and its copies.
185 */
186errval_t monitor_get_cap_owner(struct capref croot, capaddr_t cptr, int level, coreid_t *ret_owner)
187{
188    capaddr_t root_addr = get_cap_addr(croot);
189    uint8_t root_level = get_cap_level(croot);
190
191    return invoke_monitor_get_cap_owner(root_addr, root_level, cptr, level, ret_owner);
192}
193
194/**
195 * \brief Change the owner of a cap and its copies.
196 */
197errval_t monitor_set_cap_owner(struct capref croot, capaddr_t cptr, int level, coreid_t owner)
198{
199    capaddr_t root_addr = get_cap_addr(croot);
200    uint8_t root_level = get_cap_level(croot);
201
202    return invoke_monitor_set_cap_owner(root_addr, root_level, cptr, level, owner);
203}
204
205/**
206 * \brief Lock the cap and its copies
207 */
208errval_t monitor_lock_cap(struct capref croot, capaddr_t cptr, int level)
209{
210    capaddr_t root_addr = get_cap_addr(croot);
211    uint8_t root_level = get_cap_level(croot);
212
213    return invoke_monitor_lock_cap(root_addr, root_level, cptr, level);
214}
215
216/**
217 * \brief Unlock the cap and its copies
218 */
219errval_t monitor_unlock_cap(struct capref croot, capaddr_t cptr, int level)
220{
221    capaddr_t root_addr = get_cap_addr(croot);
222    uint8_t root_level = get_cap_level(croot);
223
224    return invoke_monitor_unlock_cap(root_addr, root_level, cptr, level);
225}
226
227errval_t monitor_has_descendants(struct capability *cap, bool *res)
228{
229    return invoke_monitor_has_descendants((uint64_t*)cap, res);
230}
231
232errval_t monitor_is_retypeable(struct capability *cap, gensize_t offset,
233                               gensize_t objsize, size_t count)
234{
235    return invoke_monitor_is_retypeable((uint64_t*)cap, offset, objsize, count);
236}
237
238errval_t monitor_delete_last(struct capref croot, capaddr_t cptr, int level, struct capref ret_cap)
239{
240    capaddr_t root_addr = get_cap_addr(croot);
241    uint8_t root_level = get_cap_level(croot);
242    capaddr_t ret_cn = get_cnode_addr(ret_cap);
243    uint8_t ret_cn_level = get_cnode_level(ret_cap);
244    cslot_t ret_slot = ret_cap.slot;
245    return invoke_monitor_delete_last(root_addr, root_level, cptr, level,
246                                      ret_cn, ret_cn_level, ret_slot);
247}
248
249errval_t monitor_delete_foreigns(struct capref cap)
250{
251    capaddr_t cptr = get_cap_addr(cap);
252    uint8_t level = get_cap_level(cap);
253    return invoke_monitor_delete_foreigns(cptr, level);
254}
255
256errval_t monitor_revoke_mark_target(struct capref croot, capaddr_t cptr,
257                                    int level)
258{
259    capaddr_t root_addr = get_cap_addr(croot);
260    uint8_t root_level = get_cap_level(croot);
261    return invoke_monitor_revoke_mark_target(root_addr, root_level, cptr, level);
262}
263
264errval_t monitor_revoke_mark_relations(struct capability *cap)
265{
266    return invoke_monitor_revoke_mark_relations((uint64_t*)cap);
267}
268
269errval_t monitor_delete_step(struct capref ret_cap)
270{
271    return invoke_monitor_delete_step(get_cnode_addr(ret_cap),
272                                      get_cnode_level(ret_cap),
273                                      ret_cap.slot);
274}
275
276errval_t monitor_clear_step(struct capref ret_cap)
277{
278    return invoke_monitor_clear_step(get_cnode_addr(ret_cap),
279                                     get_cnode_level(ret_cap),
280                                     ret_cap.slot);
281}
282