~jakub/helenos/ia64-revival

« back to all changes in this revision

Viewing changes to kernel/generic/src/ddi/ddi.c

  • Committer: Jakub Jermar
  • Date: 2011-04-13 14:45:41 UTC
  • mfrom: (527.1.397 main-clone)
  • Revision ID: jakub@jermar.eu-20110413144541-x0j3r1zxqhsljx1o
MergeĀ mainlineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#include <arch.h>
52
52
#include <align.h>
53
53
#include <errno.h>
 
54
#include <trace.h>
54
55
 
55
56
/** This lock protects the parea_btree. */
56
57
static mutex_t parea_lock;
98
99
 *         creating address space area.
99
100
 *
100
101
 */
101
 
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages,
 
102
NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages,
102
103
    unsigned int flags)
103
104
{
104
105
        ASSERT(TASK);
105
 
        ASSERT((pf % FRAME_SIZE) == 0);
106
 
        ASSERT((vp % PAGE_SIZE) == 0);
 
106
        
 
107
        if ((pf % FRAME_SIZE) != 0)
 
108
                return EBADMEM;
 
109
        
 
110
        if ((vp % PAGE_SIZE) != 0)
 
111
                return EBADMEM;
107
112
        
108
113
        /*
109
 
         * Make sure the caller is authorised to make this syscall.
 
114
         * Unprivileged tasks are only allowed to map pareas
 
115
         * which are explicitly marked as such.
110
116
         */
111
 
        cap_t caps = cap_get(TASK);
112
 
        if (!(caps & CAP_MEM_MANAGER))
113
 
                return EPERM;
 
117
        bool priv =
 
118
            ((cap_get(TASK) & CAP_MEM_MANAGER) == CAP_MEM_MANAGER);
114
119
        
115
120
        mem_backend_data_t backend_data;
116
121
        backend_data.base = pf;
121
126
        size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
122
127
        
123
128
        if (znum == (size_t) -1) {
124
 
                /* Frames not found in any zones
125
 
                 * -> assume it is hardware device and allow mapping
 
129
                /*
 
130
                 * Frames not found in any zone
 
131
                 * -> assume it is a hardware device and allow mapping
 
132
                 *    for privileged tasks.
126
133
                 */
127
134
                irq_spinlock_unlock(&zones.lock, true);
 
135
                
 
136
                if (!priv)
 
137
                        return EPERM;
 
138
                
128
139
                goto map;
129
140
        }
130
141
        
131
142
        if (zones.info[znum].flags & ZONE_FIRMWARE) {
132
 
                /* Frames are part of firmware */
 
143
                /*
 
144
                 * Frames are part of firmware
 
145
                 * -> allow mapping for privileged tasks.
 
146
                 */
133
147
                irq_spinlock_unlock(&zones.lock, true);
 
148
                
 
149
                if (!priv)
 
150
                        return EPERM;
 
151
                
134
152
                goto map;
135
153
        }
136
154
        
137
155
        if (zone_flags_available(zones.info[znum].flags)) {
138
156
                /*
139
 
                 * Frames are part of physical memory, check if the memory
140
 
                 * region is enabled for mapping.
 
157
                 * Frames are part of physical memory, check
 
158
                 * if the memory region is enabled for mapping.
141
159
                 */
142
160
                irq_spinlock_unlock(&zones.lock, true);
143
161
                
148
166
                
149
167
                if ((!parea) || (parea->frames < pages)) {
150
168
                        mutex_unlock(&parea_lock);
151
 
                        goto err;
 
169
                        return ENOENT;
 
170
                }
 
171
                
 
172
                if (!priv) {
 
173
                        if (!parea->unpriv) {
 
174
                                mutex_unlock(&parea_lock);
 
175
                                return EPERM;
 
176
                        }
152
177
                }
153
178
                
154
179
                mutex_unlock(&parea_lock);
156
181
        }
157
182
        
158
183
        irq_spinlock_unlock(&zones.lock, true);
159
 
        
160
 
err:
161
184
        return ENOENT;
162
185
        
163
186
map:
186
209
 *           syscall, ENOENT if there is no task matching the specified ID.
187
210
 *
188
211
 */
189
 
static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
 
212
NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr,
 
213
    size_t size)
190
214
{
191
215
        /*
192
216
         * Make sure the caller is authorised to make this syscall.
229
253
 * @return 0 on success, otherwise it returns error code found in errno.h
230
254
 *
231
255
 */
232
 
unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
233
 
    unative_t pages, unative_t flags)
 
256
sysarg_t sys_physmem_map(sysarg_t phys_base, sysarg_t virt_base,
 
257
    sysarg_t pages, sysarg_t flags)
234
258
{
235
 
        return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
 
259
        return (sysarg_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
236
260
            FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
237
261
            (size_t) pages, (int) flags);
238
262
}
244
268
 * @return 0 on success, otherwise it returns error code found in errno.h
245
269
 *
246
270
 */
247
 
unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
 
271
sysarg_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
248
272
{
249
273
        ddi_ioarg_t arg;
250
274
        int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
251
275
        if (rc != 0)
252
 
                return (unative_t) rc;
 
276
                return (sysarg_t) rc;
253
277
        
254
 
        return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
 
278
        return (sysarg_t) ddi_iospace_enable((task_id_t) arg.task_id,
255
279
            (uintptr_t) arg.ioaddr, (size_t) arg.size);
256
280
}
257
281
 
258
 
/** Disable or enable preemption.
259
 
 *
260
 
 * @param enable If non-zero, the preemption counter will be decremented,
261
 
 *               leading to potential enabling of preemption. Otherwise
262
 
 *               the preemption counter will be incremented, preventing
263
 
 *               preemption from occurring.
264
 
 *
265
 
 * @return Zero on success or EPERM if callers capabilities are not sufficient.
266
 
 *
267
 
 */
268
 
unative_t sys_preempt_control(int enable)
269
 
{
270
 
        if (!(cap_get(TASK) & CAP_PREEMPT_CONTROL))
271
 
                return EPERM;
272
 
        
273
 
        if (enable)
274
 
                preemption_enable();
275
 
        else
276
 
                preemption_disable();
277
 
        
278
 
        return 0;
279
 
}
280
 
 
281
282
/** @}
282
283
 */