1/**
2 * Tests cross core cap management
3 *
4 *
5 * Copyright (c) 2010, ETH Zurich.
6 * All rights reserved.
7 *
8 * This file is distributed under the terms in the attached LICENSE file.
9 * If you do not find this file, copies can be found by writing to:
10 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
11 */
12#include <barrelfish/barrelfish.h>
13#include <stdio.h>
14#include <if/xcorecap_defs.h>
15#include <barrelfish/nameservice_client.h>
16#include <trace/trace.h>
17#include <trace_definitions/trace_defs.h>
18#include "xcorecap.h"
19
20/* --- Binding handlers --- */
21static void state_machine(struct xcorecap_binding *b);
22
23struct xcorecap_rx_vtbl rx_vtbl = {
24    .send_done = state_machine,
25};
26
27/* --- Client functions --- */
28static void create_ram_cap(struct capref * ram_cap) {
29    errval_t err;
30
31    // allocate some ram
32    err = ram_alloc(ram_cap, ALLOC_BITS);
33    if (err_is_fail(err)) {
34        DEBUG_ERR(err, "xcorecap: RAM alloc failed\n");
35    }
36}
37
38static errval_t retype_cap(struct capref * ram_cap, struct capref * frame_cap)
39{
40    errval_t err;
41
42    // retype this to a frame
43    err = slot_alloc(frame_cap);
44    if (err_is_fail(err)) {
45        DEBUG_ERR(err, "xcorecap: Frame slot alloc failed\n");
46    }
47
48    err = cap_retype(*frame_cap, *ram_cap, 0, ObjType_Frame, 1UL << ALLOC_BITS, 1);
49    if (err_is_fail(err)) {
50        DEBUG_ERR(err, "xcorecap: Retype to frame failed\n");
51    }
52
53    return err;
54}
55
56/* --- Globals used by stack-ripped functions --- */
57struct capref ram_cap, frame_cap;
58
59/* --- Stack-ripped message handlers --- */
60static void send_cap(struct xcorecap_binding *b)
61{
62    create_ram_cap(&ram_cap);
63
64    trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 1);
65
66    /* send cap */
67    errval_t err = b->tx_vtbl.send_cap(b, NOP_CONT, ram_cap);
68
69    if (err_is_fail(err)) {
70        DEBUG_ERR(err, "sendcap failed");
71        abort();
72    }
73}
74
75static void trigger_remote_retype(void *arg)
76{
77    struct xcorecap_binding *b = arg;
78    /* Trigger remote retype */
79     errval_t err = b->tx_vtbl.retype_cap(b, NOP_CONT);
80
81    if (err_is_fail(err)) {
82        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
83            struct waitset *ws = get_default_waitset();
84            err = b->register_send(b, ws, MKCONT(trigger_remote_retype, b));
85            if (err_is_fail(err)) {
86                // note that only one continuation may be registered at a time
87                DEBUG_ERR(err, "register_send on binding failed!");
88                abort();
89            }
90        } else {
91            DEBUG_ERR(err, "trigger retype failed");
92            abort();
93        }
94    }
95}
96
97static void trigger_remote_delete(void *arg)
98{
99    struct xcorecap_binding *b = arg;
100
101    /* Trigger remote delete */
102     errval_t err = b->tx_vtbl.delete_cap(b, NOP_CONT);
103
104    if (err_is_fail(err)) {
105        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
106            struct waitset *ws = get_default_waitset();
107            err = b->register_send(b, ws, MKCONT(trigger_remote_delete,b));
108            if (err_is_fail(err)) {
109                // note that only one continuation may be registered at a time
110                DEBUG_ERR(err, "register_send on binding failed!");
111                abort();
112            }
113        } else {
114            DEBUG_ERR(err, "trigger retype failed");
115            abort();
116        }
117    }
118}
119
120static void trigger_remote_revoke(void *arg)
121{
122    struct xcorecap_binding *b = arg;
123
124    /* Trigger remote revoke */
125     errval_t err = b->tx_vtbl.revoke_cap(b, NOP_CONT);
126
127    if (err_is_fail(err)) {
128        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
129            struct waitset *ws = get_default_waitset();
130            err = b->register_send(b, ws, MKCONT(trigger_remote_revoke, b));
131            if (err_is_fail(err)) {
132                // note that only one continuation may be registered at a time
133                DEBUG_ERR(err, "register_send on binding failed!");
134                abort();
135            }
136        } else {
137            DEBUG_ERR(err, "trigger retype failed");
138            abort();
139        }
140    }
141}
142
143
144static void state_machine(struct xcorecap_binding *b)
145{
146    static int state = 0;
147
148    switch(state) {
149    case 0:
150        printf("xcorecap sending cap\n");
151        send_cap(b);
152        state++;
153        break;
154
155    case 1:
156        printf("xcorecap performing local retype\n");
157        errval_t err = retype_cap(&ram_cap, &frame_cap);
158        if (err_is_fail(err)) {
159            DEBUG_ERR(err, "retype failed");
160            abort();
161        }
162        printf("xcorecap trigger remote cap retype\n");
163        trigger_remote_retype(b);
164        state++;
165        break;
166
167    case 2:
168        printf("xcorecap trigger remote cap revoke\n");
169        trigger_remote_revoke(b);
170        state++;
171        break;
172
173    case 3:
174        printf("xcorecap sending another cap\n");
175        send_cap(b);
176        state++;
177        break;
178
179    case 4:
180        printf("xcorecap delete remote cap\n");
181        trigger_remote_delete(b);
182        state++;
183        break;
184
185    case 5:
186        printf("xcorecap on core %i done\n", disp_get_core_id());
187        exit(0);
188        break;
189
190    default:
191        printf("got into incorrect state of %d\n", state);
192        break;
193    }
194}
195
196static void bind_cb(void *st, errval_t err, struct xcorecap_binding *b)
197{
198    printf ("xcorecap: connected to server...\n");
199    b->rx_vtbl = rx_vtbl;
200
201    // start test
202    state_machine(b);
203}
204
205/* --- Setup functions --- */
206static void init(void) {
207    errval_t err;
208    iref_t iref;
209
210    err = nameservice_blocking_lookup(my_service_name, &iref);
211    if (err_is_fail(err)) {
212        fprintf(stderr, "xcorecap: could not connect to the xcorecap server.\n"
213                        "Terminating.\n");
214        abort();
215    }
216
217    err = xcorecap_bind(iref, bind_cb, NULL, get_default_waitset(),
218                        IDC_BIND_FLAGS_DEFAULT);
219    if (err_is_fail(err)) {
220        DEBUG_ERR(err, "bind failed");
221        abort();
222    }
223}
224
225
226int main (int argc, char* argv[])
227{
228    errval_t err;
229
230    printf("Starting xcorecap on core %i\n", disp_get_core_id());
231
232    init();
233
234    struct waitset *ws = get_default_waitset();
235    while (1) {
236        err = event_dispatch(ws);
237        if (err_is_fail(err)) {
238            DEBUG_ERR(err, "in event_dispatch");
239            break;
240        }
241    }
242
243    return EXIT_FAILURE;
244}
245