OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [generic/] [container.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Containers defined for current build.
3
 *
4
 * Copyright (C) 2009 Bahadir Balban
5
 */
6
#include <l4/generic/container.h>
7
#include <l4/generic/resource.h>
8
#include <l4/generic/capability.h>
9
#include <l4/generic/cap-types.h>
10
#include <l4/generic/bootmem.h>
11
#include <l4/generic/thread.h>
12
#include <l4/api/errno.h>
13
#include INC_GLUE(memory.h)
14
#include INC_GLUE(mapping.h)
15
#include INC_SUBARCH(mm.h)
16
#include INC_ARCH(linker.h)
17
 
18
int container_init(struct container *c)
19
{
20
        /* Allocate new container id */
21
        c->cid = id_new(&kernel_resources.container_ids);
22
 
23
        /* Init data structures */
24
        link_init(&c->pager_list);
25
        init_address_space_list(&c->space_list);
26
        init_ktcb_list(&c->ktcb_list);
27
        init_mutex_queue_head(&c->mutex_queue_head);
28
        cap_list_init(&c->cap_list);
29
 
30
        /* Init pager structs */
31
        c->pager = alloc_bootmem(sizeof(c->pager[0]) *
32
                                 CONFIG_MAX_PAGERS_USED, 0);
33
        for (int i = 0; i < CONFIG_MAX_PAGERS_USED; i++)
34
                cap_list_init(&c->pager[i].cap_list);
35
 
36
 
37
        return 0;
38
}
39
 
40
struct container *container_create(void)
41
{
42
        struct container *c = alloc_container();
43
 
44
        container_init(c);
45
 
46
        return c;
47
}
48
 
49
void kres_insert_container(struct container *c,
50
                            struct kernel_resources *kres)
51
{
52
        spin_lock(&kres->containers.lock);
53
        list_insert(&c->list, &kres->containers.list);
54
        kres->containers.ncont++;
55
        spin_unlock(&kres->containers.lock);
56
}
57
 
58
struct container *container_find(struct kernel_resources *kres, l4id_t cid)
59
{
60
        struct container *c;
61
 
62
        spin_lock(&kres->containers.lock);
63
        list_foreach_struct(c, &kres->containers.list, list) {
64
                if (c->cid == cid) {
65
                        spin_unlock(&kres->containers.lock);
66
                        return c;
67
                }
68
        }
69
        spin_unlock(&kres->containers.lock);
70
        return 0;
71
}
72
 
73
/*
74
 * TODO:
75
 *
76
 * Create a purer address_space_create that takes
77
 * flags for extra ops such as copying kernel tables,
78
 * user tables of an existing pgd etc.
79
 */
80
 
81
/*
82
 * Inspects pager parameters defined in the container,
83
 * and sets up an execution environment for the pager.
84
 *
85
 * This involves setting up pager's ktcb, space, utcb,
86
 * all ids, registers, and mapping its (perhaps) first
87
 * few pages in order to make it runnable.
88
 */
89
int init_pager(struct pager *pager, struct container *cont)
90
{
91
        struct ktcb *task;
92
        struct address_space *space;
93
 
94
        /*
95
         * Set up dummy current cap_list so that cap accounting
96
         * can be done to this pager. Note, that we're still on
97
         * idle task stack.
98
         */
99
        cap_list_move(&current->cap_list, &pager->cap_list);
100
 
101
        /* Setup dummy container pointer so that curcont works */
102
        current->container = cont;
103
 
104
        /* New ktcb allocation is needed */
105
        task = tcb_alloc_init(cont->cid);
106
 
107
        space = address_space_create(0);
108
        address_space_attach(task, space);
109
 
110
        /* Initialize ktcb */
111
        task_init_registers(task, pager->start_address);
112
 
113
        /* Initialize container/pager relationships */
114
        task->pagerid = task->tid;
115
        task->tgid = task->tid;
116
        task->container = cont;
117
 
118
        /* Set cpu affinity */
119
        thread_setup_affinity(task);
120
 
121
        /* Add the address space to container space list */
122
        address_space_add(task->space);
123
 
124
#if 0
125
        printk("%s: Mapping 0x%lx bytes (%lu pages) "
126
               "from 0x%lx to 0x%lx for %s\n",
127
               __KERNELNAME__, pager->memsize,
128
               __pfn(page_align_up(pager->memsize)),
129
               pager->start_lma, pager->start_vma, cont->name);
130
 
131
        /* Map the task's space */
132
        add_mapping_pgd(pager->start_lma, pager->start_vma,
133
                        page_align_up(pager->memsize),
134
                        MAP_USR_RWX, TASK_PGD(task));
135
#else
136
        /*
137
         * Map pager with appropriate section flags
138
         * We do page_align_down() to do a page alignment for
139
         * various kinds of sections, this automatically
140
         * takes care of the case where we have different kinds of
141
         * data lying on same page, eg: RX, RO etc.
142
         * Here one assumption made is, starting of first
143
         * RW section will be already page aligned, if this is
144
         * not true then we have to take special care of this.
145
         */
146
        if(pager->rx_sections_end >= pager->rw_sections_start) {
147
                pager->rx_sections_end = page_align(pager->rx_sections_end);
148
                pager->rw_sections_start = page_align(pager->rw_sections_start);
149
        }
150
 
151
        unsigned long size = 0;
152
        if((size = page_align_up(pager->rx_sections_end) -
153
            page_align_up(pager->rx_sections_start))) {
154
                add_mapping_pgd(page_align_up(pager->rx_sections_start -
155
                                              pager->start_vma +
156
                                              pager->start_lma),
157
                                page_align_up(pager->rx_sections_start),
158
                                size, MAP_USR_RX, TASK_PGD(task));
159
 
160
                printk("%s: Mapping 0x%lx bytes as RX "
161
                       "from 0x%lx to 0x%lx for %s\n",
162
                       __KERNELNAME__, size,
163
                       page_align_up(pager->rx_sections_start -
164
                       pager->start_vma + pager->start_lma),
165
                       page_align_up(pager->rx_sections_start),
166
                       cont->name);
167
        }
168
 
169
        if((size = page_align_up(pager->rw_sections_end) -
170
            page_align_up(pager->rw_sections_start))) {
171
                add_mapping_pgd(page_align_up(pager->rw_sections_start -
172
                                              pager->start_vma +
173
                                              pager->start_lma),
174
                                page_align_up(pager->rw_sections_start),
175
                                size, MAP_USR_RW, TASK_PGD(task));
176
 
177
                printk("%s: Mapping 0x%lx bytes as RW "
178
                       "from 0x%lx to 0x%lx for %s\n",
179
                       __KERNELNAME__, size,
180
                       page_align_up(pager->rw_sections_start -
181
                       pager->start_vma + pager->start_lma),
182
                       page_align_up(pager->rw_sections_start),
183
                       cont->name);
184
        }
185
 
186
#endif
187
 
188
        /* Move capability list from dummy to task's space cap list */
189
        cap_list_move(&task->space->cap_list, &current->cap_list);
190
 
191
        /* Initialize task scheduler parameters */
192
        sched_init_task(task, TASK_PRIO_PAGER);
193
 
194
        /* Give it a kick-start tick and make runnable */
195
        task->ticks_left = 1;
196
        sched_resume_async(task);
197
 
198
        /* Container list that keeps all tasks */
199
        tcb_add(task);
200
 
201
        return 0;
202
}
203
 
204
/*
205
 * All first-level dynamically allocated resources
206
 * are initialized, which includes the pager thread ids
207
 * and pager space ids.
208
 *
209
 * This updates all capability target ids where the target
210
 * is a run-time allocated resource with a new resource id.
211
 */
212
int update_dynamic_capids(struct kernel_resources *kres)
213
{
214
        struct ktcb *pager, *tpager;
215
        struct container *cont, *tcont;
216
        struct capability *cap;
217
 
218
        /* Containers */
219
        list_foreach_struct(cont, &kres->containers.list, list) {
220
                /* Pagers */
221
                list_foreach_struct(pager, &cont->ktcb_list.list, task_list) {
222
                        /* Capabilities */
223
                        list_foreach_struct(cap,
224
                                            &pager->space->cap_list.caps,
225
                                            list) {
226
 
227
                                /* They all shall be owned by their pager */
228
                                cap->owner = pager->tid;
229
 
230
                                /*
231
                                 * Pager Space/Thread targets need updating
232
                                 * from the given static container id to their
233
                                 * run-time allocated ids.
234
                                 */
235
 
236
                                /* Quantity caps don't have target ids */
237
                                if (cap_type(cap) == CAP_TYPE_QUANTITY)
238
                                        cap->resid = CAP_RESID_NONE;
239
 
240
                                /*
241
                                 * Space _always_ denotes current pager's
242
                                 * space. Other containers are not addressable
243
                                 * by space ids.
244
                                 */
245
                                if (cap_rtype(cap) == CAP_RTYPE_SPACE)
246
                                        cap->resid = pager->space->spid;
247
 
248
                                /*
249
                                 * Thread _always_denotes another container's
250
                                 * pager. There is simply no other reasonable
251
                                 * thread target in the system.
252
                                 */
253
                                if (cap_rtype(cap) == CAP_RTYPE_THREAD) {
254
 
255
                                        /* Find target container */
256
                                        if (!(tcont =
257
                                              container_find(kres,
258
                                                             cap->resid))) {
259
                                                printk("FATAL: Capability "
260
                                                       "configured to target "
261
                                                       "non-existent "
262
                                                       "container.\n");
263
                                                BUG();
264
 
265
                                        }
266
 
267
                                        /* Find its pager */
268
                                        if (list_empty(&tcont->ktcb_list.list)) {
269
                                                printk("FATAL: Pager"
270
                                                       "does not exist in "
271
                                                       "container %d.\n",
272
                                                       tcont->cid);
273
                                                BUG();
274
                                        }
275
 
276
                                        tpager =
277
                                        link_to_struct(
278
                                                tcont->ktcb_list.list.next,
279
                                                struct ktcb, task_list);
280
 
281
                                        /* Assign pager's thread id to cap */
282
                                        cap->resid = tpager->tid;
283
                                }
284
                        }
285
                }
286
        }
287
 
288
        return 0;
289
}
290
 
291
/*
292
 * Initialize all containers with their initial set of tasks,
293
 * spaces, scheduler parameters such that they can be started.
294
 */
295
int container_init_pagers(struct kernel_resources *kres)
296
{
297
        struct container *cont;
298
        struct pager *pager;
299
 
300
        list_foreach_struct(cont, &kres->containers.list, list) {
301
                for (int i = 0; i < cont->npagers; i++) {
302
                        pager = &cont->pager[i];
303
                        init_pager(pager, cont);
304
                }
305
        }
306
 
307
        /* Update any capability fields that were dynamically allocated */
308
        update_dynamic_capids(kres);
309
 
310
        return 0;
311
}
312
 
313
 
314
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.