1/*
2 * Copyright (c) 2018, ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <barrelfish/barrelfish.h>
11#include <numa.h>
12
13#include "intel_vtd.h"
14
15errval_t vtd_root_table_create(struct vtd_root_table *rt, struct vtd *vtd)
16{
17    errval_t err;
18
19    INTEL_VTD_DEBUG_RTABLE("creating root table\n");
20
21    assert(capref_is_null(rt->rtcap));
22    assert(capref_is_null(rt->mappingcncap));
23
24    /* allocate slots for capability and */
25
26    err = slot_alloc_root(&rt->mappingcncap);
27    if (err_is_fail(err)) {
28        return err_push(err, LIB_ERR_SLOT_ALLOC);
29    }
30
31    err = slot_alloc(&rt->rtcap);
32    if (err_is_fail(err)) {
33        err = err_push(err, LIB_ERR_SLOT_ALLOC);
34        goto err_out_1;
35    }
36
37    struct capref ramcap;
38    err = numa_ram_alloc_on_node(&ramcap, BASE_PAGE_SIZE, vtd->proximity_domain,
39                                 NULL);
40    if (err_is_fail(err)) {
41        err = err_push(err, LIB_ERR_RAM_ALLOC);
42        goto err_out_2;
43    }
44
45    struct capref ramcap2;
46    err = numa_ram_alloc_on_node(&ramcap2, (1UL << (L2_CNODE_BITS + OBJBITS_CTE)),
47                                 vtd->proximity_domain, NULL);
48    if (err_is_fail(err)) {
49        err = err_push(err, LIB_ERR_RAM_ALLOC);
50        goto err_out_3;
51    }
52
53    err = cap_retype(rt->rtcap, ramcap, 0, ObjType_VNode_VTd_root_table,
54                     vnode_objsize(ObjType_VNode_VTd_root_table), 1);
55    if (err_is_fail(err)) {
56        err =  err_push(err, LIB_ERR_CAP_RETYPE);
57        goto err_out_4;
58    }
59
60    err = cnode_create_from_mem(rt->mappingcncap, ramcap2, ObjType_L2CNode,
61                                &rt->mappigncn, L2_CNODE_SLOTS);
62    if (err_is_fail(err)) {
63        err = err_push(err, LIB_ERR_CNODE_CREATE_FROM_MEM);
64        goto err_out_5;
65    }
66
67    /* clean up */
68
69    err = cap_destroy(ramcap);
70    if (err_is_fail(err)) {
71        err = err_push(err, LIB_ERR_CAP_DESTROY);
72        DEBUG_ERR(err, "ignoring destorying of ramcap\n");
73    }
74
75    err = cap_destroy(ramcap2);
76    if (err_is_fail(err)) {
77        err = err_push(err, LIB_ERR_CAP_DESTROY);
78        DEBUG_ERR(err, "ignoring destorying of ramcap\n");
79    }
80
81    rt->vtd = vtd;
82
83    return SYS_ERR_OK;
84
85    err_out_5:
86    cap_destroy(rt->rtcap);
87    err_out_4:
88    cap_destroy(ramcap2);
89    err_out_3:
90    cap_destroy(ramcap);
91    err_out_2:
92    slot_free(rt->rtcap);
93    err_out_1:
94    slot_free(rt->mappingcncap);
95    return err;
96}
97
98
99errval_t vtd_root_table_destroy(struct vtd_root_table *rt)
100{
101    INTEL_VTD_DEBUG_RTABLE("destroying root table\n");
102
103    errval_t err;
104
105    /* delete the cnode cap */
106    if (!capref_is_null(rt->rtcap)) {
107        err = cap_destroy(rt->rtcap);
108        assert(err_is_ok(err));
109    }
110
111    if (!capref_is_null(rt->mappingcncap)) {
112        err = cap_destroy(rt->mappingcncap);
113        assert(err_is_ok(err));
114    }
115
116    memset(rt, 0, sizeof(*rt));
117
118    return SYS_ERR_OK;
119}
120
121
122struct vtd_ctxt_table *vtd_root_table_get_context_table(struct vtd_root_table *rt,
123                                                        uint8_t idx)
124{
125    return rt->ctxt_tables[idx];
126}
127
128