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

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [posix/] [mm0/] [mm/] [utcb.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Management of task utcb regions and own utcb.
3
 *
4
 * Copyright (C) 2007-2009 Bahadir Bilgehan Balban
5
 */
6
 
7
#include <l4/macros.h>
8
#include INC_GLUE(memlayout.h)
9
#include L4LIB_INC_ARCH(utcb.h)
10
#include <mmap.h>
11
#include <utcb.h>
12
#include <malloc/malloc.h>
13
#include <vm_area.h>
14
#include <memory.h>
15
 
16
/*
17
 * UTCB management in Codezero
18
 */
19
 
20
/* Globally disjoint utcb virtual region pool */
21
static struct address_pool utcb_region_pool;
22
 
23
int utcb_pool_init()
24
{
25
        int err;
26
 
27
        /* Initialise the global shm virtual address pool */
28
        if ((err =
29
             address_pool_init(&utcb_region_pool,
30
                               __pfn_to_addr(cont_mem_regions.utcb->start),
31
                               __pfn_to_addr(cont_mem_regions.utcb->end)))
32
            < 0) {
33
                printf("UTCB address pool initialisation failed.\n");
34
                return err;
35
        }
36
        return 0;
37
}
38
 
39
void *utcb_new_address(int npages)
40
{
41
        return address_new(&utcb_region_pool, npages);
42
}
43
 
44
int utcb_delete_address(void *utcb_address, int npages)
45
{
46
        return address_del(&utcb_region_pool, utcb_address, npages);
47
}
48
 
49
/* Return an empty utcb slot in this descriptor */
50
unsigned long utcb_new_slot(struct utcb_desc *desc)
51
{
52
        int slot;
53
 
54
        if ((slot = id_new(desc->slots)) < 0)
55
                return 0;
56
        else
57
                return desc->utcb_base + (unsigned long)slot * UTCB_SIZE;
58
}
59
 
60
int utcb_delete_slot(struct utcb_desc *desc, unsigned long address)
61
{
62
        BUG_ON(id_del(desc->slots, (address - desc->utcb_base)
63
                      / UTCB_SIZE) < 0);
64
        return 0;
65
}
66
 
67
unsigned long task_new_utcb_desc(struct tcb *task)
68
{
69
        struct utcb_desc *d;
70
 
71
        /* Allocate a new descriptor */
72
        if (!(d = kzalloc(sizeof(*d))))
73
                return 0;
74
 
75
        link_init(&d->list);
76
 
77
        /* We currently assume UTCB is smaller than PAGE_SIZE */
78
       BUG_ON(UTCB_SIZE > PAGE_SIZE);
79
 
80
       /* Initialise utcb slots */
81
       d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE);
82
 
83
       /* Obtain a new and unique utcb base */
84
        /* FIXME: Use variable size than a page */
85
       d->utcb_base = (unsigned long)utcb_new_address(1);
86
 
87
       /* Add descriptor to tcb's chain */
88
       list_insert(&d->list, &task->utcb_head->list);
89
 
90
       /* Obtain and return first slot */
91
       return utcb_new_slot(d);
92
}
93
 
94
int task_delete_utcb_desc(struct tcb *task, struct utcb_desc *d)
95
{
96
        /* Unlink desc from its list */
97
        list_remove_init(&d->list);
98
 
99
        /* Unmap the descriptor region */
100
        do_munmap(task, d->utcb_base, 1);
101
 
102
        /* Return descriptor address */
103
        utcb_delete_address((void *)d->utcb_base, 1);
104
 
105
        /* Free the descriptor */
106
        kfree(d);
107
 
108
        return 0;
109
}
110
 
111
/*
112
 * Upon fork, the utcb descriptor list is replaced by a new one, since it is a new
113
 * address space. A new utcb is allocated and mmap'ed for the child task
114
 * running in the newly created address space.
115
 *
116
 * The original privately mmap'ed regions for thread-local utcbs remain
117
 * as copy-on-write on the new task, just like mmap'ed the stacks for cloned
118
 * threads in the parent address space.
119
 *
120
 * Upon clone, naturally the utcb descriptor chain and vm_areas remain to be
121
 * shared. A new utcb slot is allocated either by using an empty one in one of
122
 * the existing mmap'ed utcb regions, or by mmaping a new utcb region.
123
 */
124
int task_setup_utcb(struct tcb *task)
125
{
126
        struct utcb_desc *udesc;
127
        unsigned long slot;
128
        void *err;
129
 
130
        /* Setting this up twice is a bug */
131
        BUG_ON(task->utcb_address);
132
 
133
        /* Search for an empty utcb slot already allocated to this space */
134
        list_foreach_struct(udesc, &task->utcb_head->list, list)
135
                if ((slot = utcb_new_slot(udesc)))
136
                        goto out;
137
 
138
        /* Allocate a new utcb memory region and return its base */
139
        slot = task_new_utcb_desc(task);
140
out:
141
 
142
        /* Check if utcb is already mapped (in case of multiple threads) */
143
        if (!find_vma(slot, &task->vm_area_head->list)) {
144
                /* Map this region as private to current task */
145
                if (IS_ERR(err = do_mmap(0, 0, task, slot,
146
                                         VMA_ANONYMOUS | VMA_PRIVATE |
147
                                         VMA_FIXED | VM_READ | VM_WRITE, 1))) {
148
                        printf("UTCB: mmapping failed with %d\n", (int)err);
149
                        return (int)err;
150
                }
151
        }
152
 
153
        /* Assign task's utcb address */
154
        task->utcb_address = slot;
155
        // printf("UTCB created at 0x%x.\n", slot);
156
 
157
        return 0;
158
}
159
 
160
/*
161
 * Deletes a utcb slot by first deleting the slot entry, the descriptor
162
 * address if emptied, the mapping of the descriptor, and the descriptor itself
163
 */
164
int task_destroy_utcb(struct tcb *task)
165
{
166
        struct utcb_desc *udesc;
167
 
168
        // printf("UTCB: Destroying 0x%x\n", task->utcb_address);
169
 
170
        /* Find the utcb descriptor slot first */
171
        list_foreach_struct(udesc, &task->utcb_head->list, list) {
172
                /* FIXME: Use variable alignment than a page */
173
                /* Detect matching slot */
174
                if (page_align(task->utcb_address) == udesc->utcb_base) {
175
 
176
                        /* Delete slot from the descriptor */
177
                        utcb_delete_slot(udesc, task->utcb_address);
178
 
179
                        /* Is the desc completely empty now? */
180
                        if (id_is_empty(udesc->slots))
181
                                /* Delete the descriptor */
182
                                task_delete_utcb_desc(task, udesc);
183
                        return 0; /* Finished */
184
                }
185
        }
186
        BUG();
187
}
188
 
189
 

powered by: WebSVN 2.1.0

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