1/**
2 * \file
3 * \brief Code for managing VSpace of a new domain when it is spawned
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <barrelfish/barrelfish.h>
16#include <spawndomain/spawndomain.h>
17#include "spawn.h"
18
19/**
20 * \brief Initialize the vspace for the domain being spawned
21 *
22 * \param vnode The pml4 cap for the new domain
23 *
24 * \bug architecture specific
25 */
26errval_t spawn_vspace_init(struct spawninfo *si, struct capref vnode,
27                           enum cpu_type cpu_type)
28{
29    errval_t err;
30    struct pmap *pmap = NULL;
31
32    si->vspace = malloc(sizeof (struct vspace));
33    if (si->vspace == NULL) {
34        err = LIB_ERR_MALLOC_FAIL;
35        goto error;
36    }
37    pmap = malloc(ARCH_DEFAULT_PMAP_SIZE);
38    if (!pmap) {
39        err = LIB_ERR_MALLOC_FAIL;
40        goto error;
41    }
42
43    err = pmap_init(pmap, si->vspace, vnode, &si->pagecn_slot_alloc.a);
44    if (err_is_fail(err)) {
45        err = err_push(err, LIB_ERR_PMAP_INIT);
46        goto error;
47    }
48
49    err = vspace_init(si->vspace, pmap);
50    if (err_is_fail(err)) {
51        err = err_push(err, LIB_ERR_VSPACE_INIT);
52        goto error;
53    }
54
55    return SYS_ERR_OK;
56
57 error: // XXX: proper cleanup
58    if (si->vspace) {
59        free(si->vspace);
60    }
61    if (pmap) {
62        free(pmap);
63    }
64    return err;
65}
66
67/**
68 * \brief Map one frame anywhere
69 */
70errval_t spawn_vspace_map_one_frame(struct spawninfo *si, genvaddr_t *retaddr,
71                                    struct capref frame, size_t size)
72{
73    errval_t err;
74    struct vregion *vregion = NULL;
75    struct memobj_one_frame *memobj = NULL;
76
77    vregion = malloc(sizeof(struct vregion));
78    if (!vregion) {
79        err = LIB_ERR_MALLOC_FAIL;
80        goto error;
81    }
82    memobj = malloc(sizeof(struct memobj_one_frame));
83    if (!memobj) {
84        err = LIB_ERR_MALLOC_FAIL;
85        goto error;
86    }
87
88    err = memobj_create_one_frame(memobj, size, 0);
89    if (err_is_fail(err)) {
90        err = err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON);
91        goto error;
92    }
93    err = memobj->m.f.fill(&memobj->m, 0, frame, size);
94    if (err_is_fail(err)) {
95        err = err_push(err, LIB_ERR_MEMOBJ_FILL);
96        goto error;
97    }
98    err = vregion_map(vregion, si->vspace, &memobj->m, 0, size,
99                      VREGION_FLAGS_READ_WRITE);
100    if (err_is_fail(err)) {
101        err = err_push(err, LIB_ERR_VSPACE_MAP);
102        goto error;
103    }
104    err = memobj->m.f.pagefault(&memobj->m, vregion, 0, 0);
105    if (err_is_fail(err)) {
106        err = err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER);
107        goto error;
108    }
109
110    *retaddr = vregion_get_base_addr(vregion);
111    return SYS_ERR_OK;
112
113 error: // XXX: proper cleanup
114    if (vregion) {
115        free(vregion);
116    }
117    if (memobj) {
118        free(memobj);
119    }
120    return err;
121}
122
123/**
124 * \brief Map one frame at the given addr
125 */
126errval_t spawn_vspace_map_fixed_one_frame(struct spawninfo *si, genvaddr_t addr,
127                                          struct capref frame, size_t size)
128{
129    errval_t err;
130    struct vregion *vregion = NULL;
131    struct memobj_one_frame *memobj = NULL;
132
133    vregion = malloc(sizeof(struct vregion));
134    if (!vregion) {
135        err = LIB_ERR_MALLOC_FAIL;
136        goto error;
137    }
138    memobj = malloc(sizeof(struct memobj_one_frame));
139    if (!memobj) {
140        err = LIB_ERR_MALLOC_FAIL;
141        goto error;
142    }
143
144    err = memobj_create_one_frame(memobj, size, 0);
145    if (err_is_fail(err)) {
146        err = err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON);
147        goto error;
148    }
149    err = memobj->m.f.fill(&memobj->m, 0, frame, size);
150    if (err_is_fail(err)) {
151        err = err_push(err, LIB_ERR_MEMOBJ_FILL);
152        goto error;
153    }
154    err = vregion_map_fixed(vregion, si->vspace, &memobj->m, 0, size, addr,
155                            VREGION_FLAGS_READ_WRITE);
156    if (err_is_fail(err)) {
157        err = err_push(err, LIB_ERR_VSPACE_MAP);
158        goto error;
159    }
160    err = memobj->m.f.pagefault(&memobj->m, vregion, 0, 0);
161    if (err_is_fail(err)) {
162        err = err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER);
163        goto error;
164    }
165
166    return SYS_ERR_OK;
167
168 error: // XXX: proper cleanup
169    if (vregion) {
170        free(vregion);
171    }
172    if (memobj) {
173        free(memobj);
174    }
175    return err;
176}
177
178/**
179 * \brief Return memobj and vregion for anonymous type mapping
180 */
181errval_t spawn_vspace_map_anon_fixed_attr(struct spawninfo *si, genvaddr_t addr,
182                                          size_t size, struct vregion **vregion,
183                                          struct memobj **memobj,
184                                          vregion_flags_t flags)
185{
186    errval_t err;
187
188    // Allocate space
189    *vregion = malloc(sizeof(struct vregion));
190    if (!*vregion) {
191        err = LIB_ERR_MALLOC_FAIL;
192        goto error;
193    }
194    *memobj = malloc(sizeof(struct memobj_anon));
195    if (!*memobj) {
196        err = LIB_ERR_MALLOC_FAIL;
197        goto error;
198    }
199
200    // Create the objects
201    err = memobj_create_anon((struct memobj_anon*)*memobj, size, 0);
202    if (err_is_fail(err)) {
203        err = err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON);
204        goto error;
205    }
206    err = vregion_map_fixed(*vregion, si->vspace, *memobj, 0, size, addr,
207                            flags);
208    if (err_is_fail(err)) {
209        // err = LIB_ERR_VSPACE_MAP;
210        goto error;
211    }
212
213    return SYS_ERR_OK;
214
215 error: // XXX: proper cleanup
216    if (*vregion) {
217        free(*vregion);
218    }
219    if (*memobj) {
220        free(*memobj);
221    }
222    return err;
223}
224