1/**
2 * \file
3 * \brief remote delete test
4 */
5
6/*
7 * Copyright (c) 2016, 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, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <barrelfish/barrelfish.h>
16#include <if/test_defs.h>
17
18#include "test.h"
19
20__attribute__((unused))
21static void debug_capref(const char *prefix, struct capref cap)
22{
23    char buf[128];
24    debug_print_capref(buf, 128, cap);
25    printf("%s capref = %s\n", prefix, buf);
26}
27
28enum server_op {
29    // Setup CNode in server's cspace
30    SERVER_OP_CREATE_COPY,
31    // Check that CNode was deleted in server's cspace
32    SERVER_OP_CHECK_CNODE_DELETED,
33    // Exit server
34    SERVER_OP_EXIT,
35};
36
37enum client_op {
38    // Access cap in CNode when CNode exists on server, then delete our copy
39    // of CNode -> ownership should transfer to server core
40    CLIENT_OP_ACCESS_1,
41    // Exit client
42    CLIENT_OP_EXIT,
43};
44
45//{{{1 Server-side cap operations
46
47struct server_state {
48    struct capref cnode;
49};
50
51void init_server(struct test_binding *b)
52{
53    b->st = malloc(sizeof(struct server_state));
54    assert(b->st);
55    if (!b->st) {
56        USER_PANIC("state malloc() in server");
57    }
58}
59
60void server_do_test(struct test_binding *b, uint32_t test, struct capref cap)
61{
62    errval_t err;
63    struct server_state *st = b->st;
64
65    switch(test) {
66        case SERVER_OP_CREATE_COPY:
67            // First call: store copy of received cnode
68            err = slot_alloc(&st->cnode);
69            PANIC_IF_ERR(err, "slot alloc in root cnode in server");
70            err = cap_copy(st->cnode, cap);
71            PANIC_IF_ERR(err, "cap copy to root cnode");
72
73            printf("distops_delete: deleting one cnode copy on foreign core\n");
74            err = cap_destroy(cap);
75            if (err_is_fail(err)) {
76                printf("distops_delete: delete failed: %s\n", err_getcode(err));
77            }
78            PANIC_IF_ERR(err, "cap destroy of received cap");
79
80            err = test_basic__tx(b, NOP_CONT, CLIENT_OP_ACCESS_1);
81            PANIC_IF_ERR(err, "server: triggering access on client");
82            break;
83
84        case SERVER_OP_CHECK_CNODE_DELETED:
85            printf("server: check that cnode deleted (CNodes are not moveable)\n");
86
87            err = cap_destroy(st->cnode);
88            if (err_no(err) != SYS_ERR_CAP_NOT_FOUND) {
89                printf("distops_delete: delete failed: %s\n", err_getcode(err));
90            }
91
92            err = test_basic__tx(b, NOP_CONT, CLIENT_OP_EXIT);
93            PANIC_IF_ERR(err, "sending exit to client");
94            printf("distops_delete: test done\n");
95            exit(0);
96
97        default:
98            USER_PANIC("server: Unknown test %"PRIu32"\n", test);
99    }
100}
101
102//{{{1 Client-side cap operations
103
104struct client_state {
105    struct capref cnode;
106    struct capref cap;
107};
108
109void init_client(struct test_binding *b)
110{
111    errval_t err;
112
113    // Allocate client state struct
114    b->st = malloc(sizeof(struct client_state));
115    assert(b->st);
116    if (!b->st) {
117        USER_PANIC("state malloc() in client");
118    }
119    struct client_state *cst = b->st;
120
121    // Allocate RAM cap
122    err = cnode_create_l2(&cst->cnode, &cst->cap.cnode);
123    PANIC_IF_ERR(err, "in client: cnode_create_l2");
124
125    cst->cap.slot = 0;
126
127    struct capref cap = cst->cap;
128
129    for (; cap.slot < 4; cap.slot ++) {
130        err = cap_copy(cap, cap_vroot);
131        PANIC_IF_ERR(err, "in client: copying into our cnode, slot=%"PRIuCSLOT, cap.slot);
132    }
133
134    // Trigger Server
135    err = test_caps__tx(b, NOP_CONT, SERVER_OP_CREATE_COPY, cst->cnode, NULL_CAP);
136    PANIC_IF_ERR(err, "in client: sending cnode to server");
137}
138
139void client_do_test(struct test_binding *b, uint32_t test, struct capref cap)
140{
141    errval_t err;
142    struct vnode_identity vi;
143    struct client_state *st = b->st;
144    assert(st);
145
146    switch(test) {
147        // Do retype while copies exist on other core
148        case CLIENT_OP_ACCESS_1:
149            printf("client: access cap in cnode\n");
150            err = invoke_vnode_identify(st->cap, &vi);
151            if (err_is_fail(err)) {
152                printf("distops_delete: invoke failed: %s\n", err_getcode(err));
153            }
154            PANIC_IF_ERR(err, "cannot identify vnode in slot 0 of cnode");
155
156            printf("client: delete cnode\n");
157            err = cap_destroy(st->cnode);
158            if (err_is_fail(err)) {
159                printf("distops_delete: delete failed: %s\n", err_getcode(err));
160            }
161            PANIC_IF_ERR(err, "client: deleting cnode");
162
163            err = test_basic__tx(b, NOP_CONT, SERVER_OP_CHECK_CNODE_DELETED);
164            PANIC_IF_ERR(err, "client: trigger first retype on server");
165            break;
166
167        case CLIENT_OP_EXIT:
168            printf("client: exit\n");
169            exit(0);
170
171        default:
172            USER_PANIC("client: Unknown test %"PRIu32"\n", test);
173    }
174}
175