1/**
2 * \file
3 * \brief remote retype 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    SERVER_OP_CREATE_COPY,
30    // Create a BASE_PAGE_SIZEd Frame cap of last page in RAM
31    SERVER_OP_RETYPE_1,
32    // Try to create a BASE_PAGE_SIZEd Frame cap of first page in RAM
33    SERVER_OP_RETYPE_2,
34};
35
36enum client_op {
37    // do a retype on client while server holds copies of cap but no
38    // descendants
39    CLIENT_OP_RETYPE_1,
40    // Do retype (overlapping and non-overlapping) on client while server
41    // holds copies of cap and Frame of last page in region
42    CLIENT_OP_RETYPE_2,
43    // Exit client
44    CLIENT_OP_EXIT,
45};
46
47//{{{1 Server-side cap operations
48
49struct server_state {
50    struct capref ram;
51    struct capref copy;
52    struct capref frame1;
53};
54
55void init_server(struct test_binding *b)
56{
57    b->st = malloc(sizeof(struct server_state));
58    assert(b->st);
59    if (!b->st) {
60        USER_PANIC("state malloc() in server");
61    }
62}
63
64void server_do_test(struct test_binding *b, uint32_t test, struct capref cap)
65{
66    errval_t err;
67    struct server_state *st = b->st;
68
69    switch(test) {
70        case SERVER_OP_CREATE_COPY:
71            // First call: store RAM cap in our state
72            st->ram = cap;
73            printf("server: creating a copy\n");
74            err = slot_alloc(&st->copy);
75            PANIC_IF_ERR(err, "slot alloc for copy in server");
76
77            err = cap_copy(st->copy, cap);
78            PANIC_IF_ERR(err, "copy in server");
79
80            err = test_basic__tx(b, NOP_CONT, CLIENT_OP_RETYPE_1);
81            PANIC_IF_ERR(err, "server: triggering 1st retype on client");
82            break;
83
84        case SERVER_OP_RETYPE_1:
85            printf("server: retype last page\n");
86
87            server_test_retype(st->copy, &st->frame1, RAM_SIZE - BASE_PAGE_SIZE,
88                               BASE_PAGE_SIZE, 1, SYS_ERR_OK);
89
90            printf("server: triggering 2nd set of retypes in client\n");
91            err = test_basic__tx(b, NOP_CONT, CLIENT_OP_RETYPE_2);
92            PANIC_IF_ERR(err, "server: triggering 2nd set of retypes on client");
93            break;
94
95        case SERVER_OP_RETYPE_2:
96            printf("server: retype first frame, expected to fail\n");
97            err = cap_delete(st->frame1);
98            PANIC_IF_ERR(err, "cap delete for result of first retype");
99
100            server_test_retype(st->copy, &st->frame1, 0, BASE_PAGE_SIZE, 1,
101                    SYS_ERR_REVOKE_FIRST);
102
103            err = test_basic__tx(b, NOP_CONT, CLIENT_OP_EXIT);
104            printf("distops_retype: test done\n");
105            printf("server: exit\n");
106            exit(0);
107
108        default:
109            USER_PANIC("server: Unknown test %"PRIu32"\n", test);
110    }
111}
112
113//{{{1 Client-side cap operations
114
115struct client_state {
116    struct capref ram;
117    struct capref frame;
118};
119
120void init_client(struct test_binding *b)
121{
122    errval_t err;
123
124    // Allocate client state struct
125    b->st = malloc(sizeof(struct client_state));
126    assert(b->st);
127    if (!b->st) {
128        USER_PANIC("state malloc() in client");
129    }
130    struct client_state *cst = b->st;
131
132    // Allocate RAM cap
133    err = ram_alloc(&cst->ram, RAM_BITS);
134    PANIC_IF_ERR(err, "in client: ram_alloc");
135
136    // Trigger Server
137    err = test_caps__tx(b, NOP_CONT, SERVER_OP_CREATE_COPY, cst->ram, NULL_CAP);
138    PANIC_IF_ERR(err, "in client: sending cap to server");
139}
140
141void client_do_test(struct test_binding *b, uint32_t test, struct capref cap)
142{
143    errval_t err;
144    struct client_state *st = b->st;
145    assert(st);
146
147    switch(test) {
148        // Do retype while copies exist on other core
149        case CLIENT_OP_RETYPE_1:
150            printf("client: retype #1\n");
151            printf("   retype first page: should succeed\n");
152            client_test_retype(st->ram, NULL, 0, BASE_PAGE_SIZE, 1, SYS_ERR_OK);
153            err = test_basic__tx(b, NOP_CONT, SERVER_OP_RETYPE_1);
154            PANIC_IF_ERR(err, "client: trigger first retype on server");
155            break;
156
157        case CLIENT_OP_RETYPE_2:
158            printf("client: retype #2\n");
159            printf("   retype last page: should fail\n");
160            client_test_retype(st->ram, NULL, RAM_SIZE - BASE_PAGE_SIZE, BASE_PAGE_SIZE, 1,
161                    SYS_ERR_REVOKE_FIRST);
162
163            printf("   retype first page: should succeed\n");
164            client_test_retype(st->ram, &st->frame, 0, BASE_PAGE_SIZE, 1, SYS_ERR_OK);
165
166            printf("   retype 2nd last page: should succeed\n");
167            client_test_retype(st->ram, NULL, RAM_SIZE - 2*BASE_PAGE_SIZE,
168                               BASE_PAGE_SIZE, 1, SYS_ERR_OK);
169
170            err = test_basic__tx(b, NOP_CONT, SERVER_OP_RETYPE_2);
171            PANIC_IF_ERR(err, "client: trigger 2nd set of retypes on server");
172            break;
173
174        case CLIENT_OP_EXIT:
175            printf("client: exit\n");
176            exit(0);
177
178        default:
179            USER_PANIC("client: Unknown test %"PRIu32"\n", test);
180    }
181}
182