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

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [generic/] [space.c] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Addess space related routines.
3
 *
4
 * Copyright (C) 2008 Bahadir Balban
5
 */
6
#include INC_GLUE(memory.h)
7
#include INC_GLUE(mapping.h)
8
#include INC_GLUE(memlayout.h)
9
#include INC_ARCH(exception.h)
10
#include INC_SUBARCH(mm.h)
11
#include <l4/generic/space.h>
12
#include <l4/generic/container.h>
13
#include <l4/generic/tcb.h>
14
#include <l4/api/space.h>
15
#include <l4/api/errno.h>
16
#include <l4/api/kip.h>
17
#include <l4/lib/idpool.h>
18
 
19
void init_address_space_list(struct address_space_list *space_list)
20
{
21
        memset(space_list, 0, sizeof(*space_list));
22
 
23
        link_init(&space_list->list);
24
        mutex_init(&space_list->lock);
25
}
26
 
27
void address_space_attach(struct ktcb *tcb, struct address_space *space)
28
{
29
        tcb->space = space;
30
        space->ktcb_refs++;
31
}
32
 
33
struct address_space *address_space_find(l4id_t spid)
34
{
35
        struct address_space *space;
36
 
37
        list_foreach_struct(space, &curcont->space_list.list, list)
38
                if (space->spid == spid)
39
                        return space;
40
        return 0;
41
}
42
 
43
void address_space_add(struct address_space *space)
44
{
45
        BUG_ON(!list_empty(&space->list));
46
        list_insert(&space->list, &curcont->space_list.list);
47
        BUG_ON(!++curcont->space_list.count);
48
}
49
 
50
void address_space_remove(struct address_space *space, struct container *cont)
51
{
52
        BUG_ON(list_empty(&space->list));
53
        BUG_ON(--cont->space_list.count < 0);
54
        list_remove_init(&space->list);
55
}
56
 
57
/* Assumes address space reflock is already held */
58
void address_space_delete(struct address_space *space,
59
                          struct ktcb *task_accounted)
60
{
61
        BUG_ON(space->ktcb_refs);
62
 
63
        /* Traverse the page tables and delete private pmds */
64
        delete_page_tables(space);
65
 
66
        /* Return the space id */
67
        id_del(&kernel_resources.space_ids, space->spid);
68
 
69
        /* Deallocate the space structure */
70
        free_space(space, task_accounted);
71
}
72
 
73
struct address_space *address_space_create(struct address_space *orig)
74
{
75
        struct address_space *space;
76
        pgd_table_t *pgd;
77
        int err;
78
 
79
        /* Allocate space structure */
80
        if (!(space = alloc_space()))
81
                return PTR_ERR(-ENOMEM);
82
 
83
        /* Allocate pgd */
84
        if (!(pgd = alloc_pgd())) {
85
                free_space(space, current);
86
                return PTR_ERR(-ENOMEM);
87
        }
88
 
89
        /* Initialize space structure */
90
        link_init(&space->list);
91
        cap_list_init(&space->cap_list);
92
        mutex_init(&space->lock);
93
        space->pgd = pgd;
94
 
95
        /* Copy all kernel entries */
96
        arch_copy_pgd_kernel_entries(pgd);
97
 
98
        /*
99
         * Set up space id: Always allocate a new one. Specifying a space id
100
         * is not allowed since spid field is used to indicate the space to
101
         * copy from.
102
         */
103
        space->spid = id_new(&kernel_resources.space_ids);
104
 
105
        /* If an original space is supplied */
106
        if (orig) {
107
                /* Copy its user entries/tables */
108
                if ((err = copy_user_tables(space, orig)) < 0) {
109
                        free_pgd(pgd);
110
                        free_space(space, current);
111
                        return PTR_ERR(err);
112
                }
113
        }
114
 
115
        return space;
116
}
117
 
118
/*
119
 * FIXME: This does not guarantee that a kernel can access a user pointer.
120
 * A pager could map an address as requested by the kernel, and unmap it
121
 * before the kernel has accessed that user address. In order to fix this,
122
 * per-pte locks (via a bitmap) should be introduced, and map syscalls can
123
 * check if a pte is locked before going forward with a request.
124
 */
125
 
126
int check_access_task(unsigned long vaddr, unsigned long size,
127
                      unsigned int flags, int page_in, struct ktcb *task)
128
{
129
        int err;
130
        unsigned long start, end, mapsize;
131
 
132
        /* Get lower and upper page boundaries */
133
        start = page_align(vaddr);
134
        end = page_align_up(vaddr + size);
135
        mapsize = end - start;
136
 
137
        /* Check if the address is mapped with given flags */
138
        if (!check_mapping_pgd(start, mapsize, flags, TASK_PGD(task))) {
139
                /*
140
                 * Is a page in requested?
141
                 *
142
                 * Only allow page-in from current task,
143
                 * since on-behalf-of type of ipc is
144
                 * complicated and we don't do it.
145
                 */
146
                if (page_in && task == current) {
147
                        /* Ask pager if paging in is possible */
148
                        if((err = pager_pagein_request(start, mapsize,
149
                                                       flags)) < 0)
150
                                return err;
151
                } else
152
                        return -EFAULT;
153
        }
154
 
155
        return 0;
156
}
157
 
158
/*
159
 * Checks whether the given user address is a valid userspace address.
160
 * If so, whether it is currently mapped into its own address space.
161
 * If its not mapped-in, it generates a page-in request to the thread's
162
 * pager. If fault hasn't cleared, aborts.
163
 */
164
int check_access(unsigned long vaddr, unsigned long size,
165
                 unsigned int flags, int page_in)
166
{
167
        return check_access_task(vaddr, size, flags, page_in, current);
168
}
169
 

powered by: WebSVN 2.1.0

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