1 |
2 |
drasko |
/*
|
2 |
|
|
* Userspace system call interface.
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 2007 - 2009 Bahadir Balban
|
5 |
|
|
*/
|
6 |
|
|
#include L4LIB_INC_ARCH(asm.h)
|
7 |
|
|
#include L4LIB_INC_ARCH(utcb.h)
|
8 |
|
|
#include
|
9 |
|
|
#include
|
10 |
|
|
#include INC_GLUE(message.h)
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
#if defined (CONFIG_ARCH_ARM) && defined (CONFIG_SUBARCH_V7)
|
14 |
|
|
/* ARMv7 uses a special per-cpu register to keep thread-local utcb pointer */
|
15 |
|
|
.macro utcb_address rx
|
16 |
|
|
mrc p15, 0, \rx, c13, c0, 3 @ Read user-RO thread register TPIDRURO
|
17 |
|
|
.endm
|
18 |
|
|
#else /* End of ARMv7 */
|
19 |
|
|
/* Get it from KIP page by double dereference */
|
20 |
|
|
.macro utcb_address rx
|
21 |
|
|
ldr \rx, =kip_utcb_ref @ First get pointer to utcb pointer in KIP
|
22 |
|
|
ldr \rx, [\rx] @ Get pointer to UTCB address from UTCB pointer in KIP
|
23 |
|
|
ldr \rx, [\rx] @ Get the utcb address
|
24 |
|
|
.endm
|
25 |
|
|
#endif
|
26 |
|
|
|
27 |
|
|
BEGIN_PROC(l4_thread_switch)
|
28 |
|
|
ldr r12, =__l4_thread_switch
|
29 |
|
|
ldr pc, [r12] @ Jump into the SWI. Kernel returns to LR_USR, which is the caller.
|
30 |
|
|
END_PROC(l4_thread_switch)
|
31 |
|
|
|
32 |
|
|
/*
|
33 |
|
|
* The syscall returns process ids. This function saves the returned values in the
|
34 |
|
|
* arguments passed by reference. @r0 = struct task_ids *
|
35 |
|
|
*/
|
36 |
|
|
BEGIN_PROC(l4_getid)
|
37 |
|
|
ldr r12, =__l4_getid @ See l4_kdata_read for why its so simple.
|
38 |
|
|
ldr pc, [r12] @ Return.
|
39 |
|
|
END_PROC(l4_getid)
|
40 |
|
|
|
41 |
|
|
/*
|
42 |
|
|
* For clone() we need special assembler handling
|
43 |
|
|
* Same signature as ipc(): @r0 = to, @r1 = from @r2 = flags
|
44 |
|
|
*
|
45 |
|
|
* NOTE: Note that this breaks l4 system call interface,
|
46 |
|
|
* this should be moved elsewhere and modified using existing l4 mechanisms.
|
47 |
|
|
*/
|
48 |
|
|
BEGIN_PROC(arch_clone)
|
49 |
|
|
stmfd sp!, {r4-r8,lr} @ Save context.
|
50 |
|
|
utcb_address r12 @ Get utcb address.
|
51 |
|
|
ldmia r12!, {r3-r8} @ Load 6 Message registers from utcb. MR0-MR5
|
52 |
|
|
|
53 |
|
|
ldr r12, =__l4_ipc
|
54 |
|
|
mov lr, pc
|
55 |
|
|
ldr pc, [r12] @ Perform the ipc()
|
56 |
|
|
|
57 |
|
|
/*
|
58 |
|
|
* At this moment:
|
59 |
|
|
* - MR_RETURN tells us whether we are parent or child (or have failed).
|
60 |
|
|
* - Child has new SP set, with |func_ptr|arg1|{End of stack}SP<-| on stack.
|
61 |
|
|
* - Child needs exit logic when its function is finished.
|
62 |
|
|
*/
|
63 |
|
|
cmp r0, #0 @ Check ipc success
|
64 |
|
|
blt ipc_failed
|
65 |
|
|
cmp MR_RETURN_REGISTER, #0 @ Check ipc return register MR_RETURN.
|
66 |
|
|
blt clone_failed @ Ipc was ok but clone() failed.
|
67 |
|
|
bgt parent_return @ It has child pid, goto parent return.
|
68 |
|
|
child:
|
69 |
|
|
ldr r0, [sp, #-4]! @ Load child's first argument.
|
70 |
|
|
mov lr, pc @ Save return address
|
71 |
|
|
ldr pc, [sp, #-4]! @ Load function pointer from stack
|
72 |
|
|
child_exit:
|
73 |
|
|
b child_exit @ We infinitely loop for now.
|
74 |
|
|
|
75 |
|
|
@ Return with normal ipc return sequence
|
76 |
|
|
parent_return:
|
77 |
|
|
clone_failed:
|
78 |
|
|
ipc_failed:
|
79 |
|
|
utcb_address r12 @ Get utcb
|
80 |
|
|
stmia r12, {r3-r8} @ Store mrs.
|
81 |
|
|
ldmfd sp!, {r4-r8,pc} @ Return restoring pc and context.
|
82 |
|
|
END_PROC(arch_clone)
|
83 |
|
|
|
84 |
|
|
/*
|
85 |
|
|
* Inter-process communication. Loads message registers as arguments before the call,
|
86 |
|
|
* and stores them as results after the call. @r0 = to, @r1 = from.
|
87 |
|
|
*/
|
88 |
|
|
BEGIN_PROC(l4_ipc)
|
89 |
|
|
stmfd sp!, {r4-r8,lr} @ Save context.
|
90 |
|
|
utcb_address r12 @ Get utcb address.
|
91 |
|
|
ldmia r12!, {r3-r8} @ Load 6 Message registers from utcb. MR0-MR5
|
92 |
|
|
ldr r12, =__l4_ipc
|
93 |
|
|
mov lr, pc
|
94 |
|
|
ldr pc, [r12]
|
95 |
|
|
utcb_address r12 @ Get utcb address.
|
96 |
|
|
stmia r12, {r3-r8} @ Store 6 Message registers to utcb. MR0-MR5
|
97 |
|
|
ldmfd sp!, {r4-r8,pc} @ Return restoring pc, and context.
|
98 |
|
|
END_PROC(l4_ipc)
|
99 |
|
|
|
100 |
|
|
/*
|
101 |
|
|
* System call that maps an area of memory into the given address space.
|
102 |
|
|
* @r0 = physical address, @r1 = virtual address, @r2 = map size in pages,
|
103 |
|
|
* @r3 = map flags, @r4 = The tgid of the address space to map.
|
104 |
|
|
*/
|
105 |
|
|
BEGIN_PROC(l4_map)
|
106 |
|
|
stmfd sp!, {r4, lr}
|
107 |
|
|
ldr r4, [sp, #8] @ FIXME: Is this right?
|
108 |
|
|
ldr r12, =__l4_map
|
109 |
|
|
mov lr, pc @ We must return here to restore r4.
|
110 |
|
|
ldr pc, [r12]
|
111 |
|
|
ldmfd sp!, {r4, pc}
|
112 |
|
|
END_PROC(l4_map)
|
113 |
|
|
|
114 |
|
|
/*
|
115 |
|
|
* Reads/manipulates capabilities of a thread, particularly a pager.
|
116 |
|
|
* @r0 = request type, @r1 = request flags, @r2 = Capability buffer pointer
|
117 |
|
|
*/
|
118 |
|
|
BEGIN_PROC(l4_capability_control)
|
119 |
|
|
stmfd sp!, {lr}
|
120 |
|
|
ldr r12, =__l4_capability_control
|
121 |
|
|
mov lr, pc
|
122 |
|
|
ldr pc, [r12]
|
123 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
124 |
|
|
END_PROC(l4_capability_control)
|
125 |
|
|
|
126 |
|
|
/*
|
127 |
|
|
* System call that unmaps an area of memory into the given address space.
|
128 |
|
|
* @r0 = virtual, @r1 = pages, @r2 = tid of address space to unmap
|
129 |
|
|
*/
|
130 |
|
|
BEGIN_PROC(l4_unmap)
|
131 |
|
|
stmfd sp!, {lr}
|
132 |
|
|
ldr r12, =__l4_unmap
|
133 |
|
|
mov lr, pc
|
134 |
|
|
ldr pc, [r12]
|
135 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
136 |
|
|
END_PROC(l4_unmap)
|
137 |
|
|
|
138 |
|
|
/*
|
139 |
|
|
* System call that controls containers and their parameters.
|
140 |
|
|
* @r0 = request type, @r1 = request flags, @r2 = io buffer ptr
|
141 |
|
|
*/
|
142 |
|
|
BEGIN_PROC(l4_container_control)
|
143 |
|
|
stmfd sp!, {lr}
|
144 |
|
|
ldr r12, =__l4_container_control
|
145 |
|
|
mov lr, pc
|
146 |
|
|
ldr pc, [r12]
|
147 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
148 |
|
|
END_PROC(l4_container_control)
|
149 |
|
|
|
150 |
|
|
/*
|
151 |
|
|
* System call that gets or sets the time info structure.
|
152 |
|
|
* @r0 = ptr to time structure @r1 = set or get. set = 1, get = 0.
|
153 |
|
|
*/
|
154 |
|
|
BEGIN_PROC(l4_time)
|
155 |
|
|
stmfd sp!, {lr}
|
156 |
|
|
ldr r12, =__l4_time
|
157 |
|
|
mov lr, pc
|
158 |
|
|
ldr pc, [r12]
|
159 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
160 |
|
|
END_PROC(l4_time)
|
161 |
|
|
|
162 |
|
|
/*
|
163 |
|
|
* System call that controls thread creation, destruction and modification.
|
164 |
|
|
* @r0 = thread action, @r1 = &ids, @r2 = utcb address
|
165 |
|
|
*/
|
166 |
|
|
BEGIN_PROC(l4_thread_control)
|
167 |
|
|
stmfd sp!, {lr}
|
168 |
|
|
ldr r12, =__l4_thread_control
|
169 |
|
|
mov lr, pc
|
170 |
|
|
ldr pc, [r12]
|
171 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
172 |
|
|
END_PROC(l4_thread_control)
|
173 |
|
|
|
174 |
|
|
/*
|
175 |
|
|
* System call that modifies ipc blocked sender lists of receivers.
|
176 |
|
|
* @r0 = Action (e.g. block/unblock), @r1 = sender id, @r2 = sender tag
|
177 |
|
|
*/
|
178 |
|
|
BEGIN_PROC(l4_ipc_control)
|
179 |
|
|
stmfd sp!, {lr}
|
180 |
|
|
ldr r12, =__l4_ipc_control
|
181 |
|
|
mov lr, pc
|
182 |
|
|
ldr pc, [r12]
|
183 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
184 |
|
|
END_PROC(l4_ipc_control)
|
185 |
|
|
|
186 |
|
|
/*
|
187 |
|
|
* Manipulates address spaces, e.g. sets up shared memory areas between threads
|
188 |
|
|
* @r0 = operation code, @r1 = operation flags, @r2 = An id (irqnum, or capid)
|
189 |
|
|
*/
|
190 |
|
|
BEGIN_PROC(l4_irq_control)
|
191 |
|
|
stmfd sp!, {lr}
|
192 |
|
|
ldr r12, =__l4_irq_control
|
193 |
|
|
mov lr, pc
|
194 |
|
|
ldr pc, [r12]
|
195 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
196 |
|
|
END_PROC(l4_irq_control)
|
197 |
|
|
|
198 |
|
|
/*
|
199 |
|
|
* Locks/unlocks a userspace mutex.
|
200 |
|
|
* @r0 = mutex virtual address, @r1 = mutex operation code
|
201 |
|
|
*/
|
202 |
|
|
BEGIN_PROC(l4_mutex_control)
|
203 |
|
|
stmfd sp!, {lr}
|
204 |
|
|
ldr r12, =__l4_mutex_control
|
205 |
|
|
mov lr, pc
|
206 |
|
|
ldr pc, [r12]
|
207 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
208 |
|
|
END_PROC(l4_mutex_control)
|
209 |
|
|
|
210 |
|
|
/*
|
211 |
|
|
* Sets registers of a thread and its pager.
|
212 |
|
|
* @r0 = ptr to exregs_data structure, @r1 = tid of thread.
|
213 |
|
|
*/
|
214 |
|
|
BEGIN_PROC(l4_exchange_registers)
|
215 |
|
|
stmfd sp!, {lr}
|
216 |
|
|
ldr r12, =__l4_exchange_registers
|
217 |
|
|
mov lr, pc
|
218 |
|
|
ldr pc, [r12]
|
219 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
220 |
|
|
END_PROC(l4_exchange_registers)
|
221 |
|
|
|
222 |
|
|
/*
|
223 |
|
|
* System call that manipulates caches and tlbs.
|
224 |
|
|
*
|
225 |
|
|
* @r0 = starting virtual address (inclusive),
|
226 |
|
|
* @r1 = ending virtual address (exclusive),
|
227 |
|
|
* @r3 = cache operation
|
228 |
|
|
*/
|
229 |
|
|
BEGIN_PROC(l4_cache_control)
|
230 |
|
|
stmfd sp!, {lr}
|
231 |
|
|
ldr r12, =__l4_cache_control
|
232 |
|
|
mov lr, pc
|
233 |
|
|
ldr pc, [r12]
|
234 |
|
|
ldmfd sp!, {pc} @ Restore original lr and return.
|
235 |
|
|
END_PROC(l4_cache_control)
|