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

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [libl4/] [include/] [l4lib/] [arch/] [arm/] [syslib.h] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Helper functions that wrap raw l4 syscalls.
3
 *
4
 * Copyright (C) 2007-2009 Bahadir Bilgehan Balban
5
 */
6
 
7
#ifndef __L4LIB_SYSLIB_H__
8
#define __L4LIB_SYSLIB_H__
9
 
10
#include <stdio.h>
11
#include <l4/macros.h>
12
#include L4LIB_INC_ARCH(syscalls.h)
13
 
14
/*
15
 * NOTE:
16
 * Its best to use these wrappers because they generalise the way
17
 * common ipc data like sender id, error, ipc tag are passed
18
 * between ipc parties.
19
 *
20
 * The arguments to l4_ipc() are used by the microkernel to initiate
21
 * the ipc. Any data passed in message registers may or may not be
22
 * a duplicate of this data, but the distinction is that anything
23
 * that is passed via the mrs are meant to be used by the other party
24
 * participating in the ipc.
25
 */
26
 
27
/* For system call arguments */
28
#define L4SYS_ARG0      (MR_UNUSED_START)
29
#define L4SYS_ARG1      (MR_UNUSED_START + 1)
30
#define L4SYS_ARG2      (MR_UNUSED_START + 2)
31
#define L4SYS_ARG3      (MR_UNUSED_START + 3)
32
 
33
 
34
#define L4_IPC_TAG_MASK                 0x00000FFF
35
 
36
 
37
/*
38
 * Servers get sender.
39
 */
40
static inline l4id_t l4_get_sender(void)
41
{
42
        return (l4id_t)read_mr(MR_SENDER);
43
}
44
 
45
/*
46
 * When doing an ipc the sender never has to be explicitly set in
47
 * the utcb via this function since this information is found out
48
 * by the microkernel by checking the system caller's id. This is
49
 * only used for restoring the sender on the utcb in order to
50
 * complete an earlier ipc.
51
 */
52
static inline void l4_set_sender(l4id_t sender)
53
{
54
        write_mr(MR_SENDER, sender);
55
}
56
 
57
static inline unsigned int l4_set_ipc_size(unsigned int word, unsigned int size)
58
{
59
        word &= ~L4_IPC_FLAGS_SIZE_MASK;
60
        word |= ((size << L4_IPC_FLAGS_SIZE_SHIFT) & L4_IPC_FLAGS_SIZE_MASK);
61
        return word;
62
}
63
 
64
static inline unsigned int l4_get_ipc_size(unsigned int word)
65
{
66
        return (word & L4_IPC_FLAGS_SIZE_MASK) >> L4_IPC_FLAGS_SIZE_SHIFT;
67
}
68
 
69
static inline unsigned int l4_set_ipc_msg_index(unsigned int word, unsigned int index)
70
{
71
        /* FIXME: Define MR_PRIMARY_TOTAL, MR_TOTAL etc. and use MR_TOTAL HERE! */
72
        BUG_ON(index > UTCB_SIZE);
73
 
74
        word &= ~L4_IPC_FLAGS_MSG_INDEX_MASK;
75
        word |= (index << L4_IPC_FLAGS_MSG_INDEX_SHIFT) &
76
                 L4_IPC_FLAGS_MSG_INDEX_MASK;
77
        return word;
78
}
79
 
80
static inline unsigned int l4_get_ipc_msg_index(unsigned int word)
81
{
82
        return (word & L4_IPC_FLAGS_MSG_INDEX_MASK)
83
               >> L4_IPC_FLAGS_MSG_INDEX_SHIFT;
84
}
85
 
86
static inline unsigned int l4_set_ipc_flags(unsigned int word, unsigned int flags)
87
{
88
        word &= ~L4_IPC_FLAGS_TYPE_MASK;
89
        word |= flags & L4_IPC_FLAGS_TYPE_MASK;
90
        return word;
91
}
92
 
93
static inline unsigned int l4_get_ipc_flags(unsigned int word)
94
{
95
        return word & L4_IPC_FLAGS_TYPE_MASK;
96
}
97
 
98
static inline unsigned int l4_get_tag(void)
99
{
100
        return read_mr(MR_TAG) & L4_IPC_TAG_MASK;
101
}
102
 
103
static inline void l4_set_tag(unsigned int tag)
104
{
105
        unsigned int tag_flags = read_mr(MR_TAG);
106
 
107
        tag_flags &= ~L4_IPC_TAG_MASK;
108
        tag_flags |= tag & L4_IPC_TAG_MASK;
109
 
110
        write_mr(MR_TAG, tag_flags);
111
}
112
 
113
/* Servers:
114
 * Sets the message register for returning errors back to client task.
115
 * These are usually posix error codes.
116
 */
117
static inline void l4_set_retval(int retval)
118
{
119
        write_mr(MR_RETURN, retval);
120
}
121
 
122
/* Clients:
123
 * Learn result of request.
124
 */
125
static inline int l4_get_retval(void)
126
{
127
        return read_mr(MR_RETURN);
128
}
129
 
130
/*
131
 * This is useful for stacked IPC. A stacked IPC happens
132
 * when a new IPC is initiated before concluding the current
133
 * one.
134
 *
135
 * This saves the last ipc's parameters such as the sender
136
 * and tag information. Any previously saved data in save
137
 * slots are destroyed. This is fine as IPC stacking is only
138
 * useful if done once.
139
 */
140
static inline void l4_save_ipcregs(void)
141
{
142
        l4_get_utcb()->saved_sender = l4_get_sender();
143
        l4_get_utcb()->saved_tag = l4_get_tag();
144
}
145
 
146
static inline void l4_restore_ipcregs(void)
147
{
148
        l4_set_tag(l4_get_utcb()->saved_tag);
149
        l4_set_sender(l4_get_utcb()->saved_sender);
150
}
151
 
152
#define TASK_CID_MASK                   0xFF000000
153
#define TASK_ID_MASK                    0x00FFFFFF
154
#define TASK_CID_SHIFT                  24
155
 
156
static inline l4id_t __raw_tid(l4id_t tid)
157
{
158
        return tid & TASK_ID_MASK;
159
}
160
 
161
static inline l4id_t __cid(l4id_t tid)
162
{
163
        return (tid & TASK_CID_MASK) >> TASK_CID_SHIFT;
164
}
165
 
166
static inline l4id_t self_tid(void)
167
{
168
        struct task_ids ids;
169
 
170
        l4_getid(&ids);
171
        return ids.tid;
172
}
173
 
174
static inline l4id_t __raw_self_tid(void)
175
{
176
        return __raw_tid(self_tid());
177
}
178
 
179
static inline int l4_send_full(l4id_t to, unsigned int tag)
180
{
181
        l4_set_tag(tag);
182
        return l4_ipc(to, L4_NILTHREAD, L4_IPC_FLAGS_FULL);
183
}
184
 
185
static inline int l4_receive_full(l4id_t from)
186
{
187
        return l4_ipc(L4_NILTHREAD, from, L4_IPC_FLAGS_FULL);
188
}
189
 
190
static inline int l4_sendrecv_full(l4id_t to, l4id_t from, unsigned int tag)
191
{
192
        int err;
193
 
194
        BUG_ON(to == L4_NILTHREAD || from == L4_NILTHREAD);
195
        l4_set_tag(tag);
196
 
197
        err = l4_ipc(to, from, L4_IPC_FLAGS_FULL);
198
 
199
        return err;
200
}
201
 
202
static inline int l4_send_extended(l4id_t to, unsigned int tag,
203
                                   unsigned int size, void *buf)
204
{
205
        unsigned int flags = 0;
206
 
207
        l4_set_tag(tag);
208
 
209
        /* Set up flags word for extended ipc */
210
        flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
211
        flags = l4_set_ipc_size(flags, size);
212
        flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
213
 
214
        /* Write buffer pointer to MR index that we specified */
215
        write_mr(L4SYS_ARG0, (unsigned long)buf);
216
 
217
        return l4_ipc(to, L4_NILTHREAD, flags);
218
}
219
 
220
static inline int l4_receive_extended(l4id_t from, unsigned int size, void *buf)
221
{
222
        unsigned int flags = 0;
223
 
224
        /* Indicate extended receive */
225
        flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
226
 
227
        /* How much data is accepted */
228
        flags = l4_set_ipc_size(flags, size);
229
 
230
        /* Indicate which MR index buffer pointer is stored */
231
        flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
232
 
233
        /* Set MR with buffer to receive data */
234
        write_mr(L4SYS_ARG0, (unsigned long)buf);
235
 
236
        return l4_ipc(L4_NILTHREAD, from, flags);
237
}
238
 
239
/*
240
 * Return result value as extended IPC.
241
 *
242
 * Extended IPC copies up to 2KB user address space buffers.
243
 * Along with such an ipc, a return value is sent using a primary
244
 * mr that is used as the return register.
245
 *
246
 * It may not be desirable to return a payload on certain conditions,
247
 * (such as an error return value) So a nopayload field is provided.
248
 */
249
static inline int l4_return_extended(int retval, unsigned int size,
250
                                     void *buf, int nopayload)
251
{
252
        unsigned int flags = 0;
253
        l4id_t sender = l4_get_sender();
254
 
255
        l4_set_retval(retval);
256
 
257
        /* Set up flags word for extended ipc */
258
        flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
259
        flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
260
 
261
        /* Write buffer pointer to MR index that we specified */
262
        write_mr(L4SYS_ARG0, (unsigned long)buf);
263
 
264
        if (nopayload)
265
                flags = l4_set_ipc_size(flags, 0);
266
        else
267
                flags = l4_set_ipc_size(flags, size);
268
 
269
        return l4_ipc(sender, L4_NILTHREAD, flags);
270
}
271
 
272
static inline int l4_sendrecv_extended(l4id_t to, l4id_t from,
273
                                       unsigned int tag, void *buf)
274
{
275
        /* Need to imitate sendrecv but with extended send/recv flags */
276
        return 0;
277
}
278
 
279
static inline int l4_send(l4id_t to, unsigned int tag)
280
{
281
        l4_set_tag(tag);
282
 
283
        return l4_ipc(to, L4_NILTHREAD, 0);
284
}
285
 
286
static inline int l4_sendrecv(l4id_t to, l4id_t from, unsigned int tag)
287
{
288
        int err;
289
 
290
        BUG_ON(to == L4_NILTHREAD || from == L4_NILTHREAD);
291
        l4_set_tag(tag);
292
 
293
        err = l4_ipc(to, from, 0);
294
 
295
        return err;
296
}
297
 
298
static inline int l4_receive(l4id_t from)
299
{
300
        return l4_ipc(L4_NILTHREAD, from, 0);
301
}
302
 
303
static inline void l4_print_mrs()
304
{
305
        printf("Message registers: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
306
               read_mr(0), read_mr(1), read_mr(2), read_mr(3),
307
               read_mr(4), read_mr(5));
308
}
309
 
310
/* Servers:
311
 * Return the ipc result back to requesting task.
312
 */
313
static inline int l4_ipc_return(int retval)
314
{
315
        l4id_t sender = l4_get_sender();
316
 
317
        l4_set_retval(retval);
318
 
319
        /* Setting the tag would overwrite retval so we l4_send without tagging */
320
        return l4_ipc(sender, L4_NILTHREAD, 0);
321
}
322
 
323
void *l4_new_virtual(int npages);
324
void *l4_del_virtual(void *virt, int npages);
325
 
326
/* A helper that translates and maps a physical address to virtual */
327
static inline void *l4_map_helper(void *phys, int npages)
328
{
329
        struct task_ids ids;
330
        int err;
331
 
332
        void *virt = l4_new_virtual(npages);
333
 
334
        l4_getid(&ids);
335
 
336
        if ((err = l4_map(phys, virt, npages,
337
                          MAP_USR_DEFAULT, ids.tid)) < 0)
338
                return PTR_ERR(err);
339
 
340
        return virt;
341
}
342
 
343
 
344
/* A helper that translates and maps a physical address to virtual */
345
static inline void *l4_unmap_helper(void *virt, int npages)
346
{
347
        struct task_ids ids;
348
 
349
        l4_getid(&ids);
350
        l4_unmap(virt, npages, ids.tid);
351
        l4_del_virtual(virt, npages);
352
        return 0;
353
}
354
 
355
#define L4_EXIT_MASK            0xFFFF
356
 
357
static inline void l4_exit(unsigned int exit_code)
358
{
359
        struct task_ids ids;
360
        l4_getid(&ids);
361
        l4_thread_control(THREAD_DESTROY |
362
                          (exit_code & L4_EXIT_MASK),
363
                          &ids);
364
}
365
 
366
#endif /* __L4LIB_SYSLIB_H__ */

powered by: WebSVN 2.1.0

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