1/*
2 * Copyright 2018, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
8 * See "LICENSE_GPLv2.txt" for details.
9 *
10 * @TAG(DATA61_GPL)
11 */
12
13/*
14 *
15 * Copyright 2016, 2017 Hesham Almatary, Data61/CSIRO <hesham.almatary@data61.csiro.au>
16 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com>
17 */
18
19#ifndef __LIBSEL4_ARCH_SYSCALLS_H
20#define __LIBSEL4_ARCH_SYSCALLS_H
21
22#include <autoconf.h>
23#include <sel4/arch/functions.h>
24#include <sel4/sel4_arch/syscalls.h>
25#include <sel4/types.h>
26
27static inline void
28riscv_sys_send(seL4_Word sys, seL4_Word dest, seL4_Word info_arg, seL4_Word mr0, seL4_Word mr1,
29               seL4_Word mr2, seL4_Word mr3)
30{
31    register seL4_Word destptr asm("a0") = dest;
32    register seL4_Word info asm("a1") = info_arg;
33
34    /* Load beginning of the message into registers. */
35    register seL4_Word msg0 asm("a2") = mr0;
36    register seL4_Word msg1 asm("a3") = mr1;
37    register seL4_Word msg2 asm("a4") = mr2;
38    register seL4_Word msg3 asm("a5") = mr3;
39
40    /* Perform the system call. */
41    register seL4_Word scno asm("a7") = sys;
42    asm volatile (
43        "ecall"
44        : "+r" (destptr), "+r" (msg0), "+r" (msg1), "+r" (msg2),
45        "+r" (msg3), "+r" (info)
46        : "r"(scno)
47    );
48}
49
50static inline void
51riscv_sys_reply(seL4_Word sys, seL4_Word info_arg, seL4_Word mr0, seL4_Word mr1, seL4_Word mr2,
52                seL4_Word mr3)
53{
54    register seL4_Word info asm("a1") = info_arg;
55
56    /* Load beginning of the message into registers. */
57    register seL4_Word msg0 asm("a2") = mr0;
58    register seL4_Word msg1 asm("a3") = mr1;
59    register seL4_Word msg2 asm("a4") = mr2;
60    register seL4_Word msg3 asm("a5") = mr3;
61
62    /* Perform the system call. */
63    register seL4_Word scno asm("a7") = sys;
64    asm volatile (
65        "ecall"
66        : "+r" (msg0), "+r" (msg1), "+r" (msg2), "+r" (msg3),
67        "+r" (info)
68        : "r"(scno)
69    );
70}
71
72static inline void
73riscv_sys_send_null(seL4_Word sys, seL4_Word src, seL4_Word info_arg)
74{
75    register seL4_Word destptr asm("a0") = src;
76    register seL4_Word info asm("a1") = info_arg;
77
78    /* Perform the system call. */
79    register seL4_Word scno asm("a7") = sys;
80    asm volatile (
81        "ecall"
82        : "+r" (destptr), "+r" (info)
83        : "r"(scno)
84    );
85}
86
87static inline void
88riscv_sys_recv(seL4_Word sys, seL4_Word src, seL4_Word *out_badge, seL4_Word *out_info, seL4_Word
89               *out_mr0, seL4_Word *out_mr1, seL4_Word *out_mr2, seL4_Word *out_mr3)
90{
91    register seL4_Word src_and_badge asm("a0") = src;
92    register seL4_Word info asm("a1");
93
94    /* Incoming message registers. */
95    register seL4_Word msg0 asm("a2");
96    register seL4_Word msg1 asm("a3");
97    register seL4_Word msg2 asm("a4");
98    register seL4_Word msg3 asm("a5");
99
100    /* Perform the system call. */
101    register seL4_Word scno asm("a7") = sys;
102    asm volatile (
103        "ecall"
104        : "=r" (msg0), "=r" (msg1), "=r" (msg2), "=r" (msg3),
105        "=r" (info), "+r" (src_and_badge)
106        : "r"(scno)
107        : "memory"
108    );
109    *out_badge = src_and_badge;
110    *out_info = info;
111    *out_mr0 = msg0;
112    *out_mr1 = msg1;
113    *out_mr2 = msg2;
114    *out_mr3 = msg3;
115}
116
117static inline void
118riscv_sys_null(seL4_Word sys)
119{
120    register seL4_Word scno asm("a7") = sys;
121    asm volatile (
122        "ecall"
123        : /* no outputs */
124        : "r"(scno)
125    );
126}
127
128static inline void
129riscv_sys_send_recv(seL4_Word sys, seL4_Word dest, seL4_Word *out_badge, seL4_Word info_arg,
130                    seL4_Word
131                    *out_info, seL4_Word *in_out_mr0, seL4_Word *in_out_mr1, seL4_Word *in_out_mr2,
132                    seL4_Word
133                    *in_out_mr3)
134{
135    register seL4_Word destptr asm("a0") = dest;
136    register seL4_Word info asm("a1") = info_arg;
137
138    /* Load beginning of the message into registers. */
139    register seL4_Word msg0 asm("a2") = *in_out_mr0;
140    register seL4_Word msg1 asm("a3") = *in_out_mr1;
141    register seL4_Word msg2 asm("a4") = *in_out_mr2;
142    register seL4_Word msg3 asm("a5") = *in_out_mr3;
143
144    /* Perform the system call. */
145    register seL4_Word scno asm("a7") = sys;
146    asm volatile (
147        "ecall"
148        : "+r" (msg0), "+r" (msg1), "+r" (msg2), "+r" (msg3),
149        "+r" (info), "+r" (destptr)
150        : "r"(scno)
151        : "memory"
152    );
153    *out_info = info;
154    *out_badge = destptr;
155    *in_out_mr0 = msg0;
156    *in_out_mr1 = msg1;
157    *in_out_mr2 = msg2;
158    *in_out_mr3 = msg3;
159}
160
161static inline void
162seL4_Send(seL4_CPtr dest, seL4_MessageInfo_t msgInfo)
163{
164    riscv_sys_send(seL4_SysSend, dest, msgInfo.words[0], seL4_GetMR(0), seL4_GetMR(1),
165                   seL4_GetMR(2), seL4_GetMR(3));
166}
167
168static inline void
169seL4_SendWithMRs(seL4_CPtr dest, seL4_MessageInfo_t msgInfo,
170                 seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
171{
172    riscv_sys_send(seL4_SysSend, dest, msgInfo.words[0],
173                   mr0 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr0 : 0,
174                   mr1 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr1 : 0,
175                   mr2 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr2 : 0,
176                   mr3 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr3 : 0
177                  );
178
179}
180
181static inline void
182seL4_NBSend(seL4_CPtr dest, seL4_MessageInfo_t msgInfo)
183{
184    riscv_sys_send(seL4_SysNBSend, dest, msgInfo.words[0], seL4_GetMR(0), seL4_GetMR(1),
185                   seL4_GetMR(2), seL4_GetMR(3));
186
187}
188
189static inline void
190seL4_NBSendWithMRs(seL4_CPtr dest, seL4_MessageInfo_t msgInfo,
191                   seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
192{
193    riscv_sys_send(seL4_SysNBSend, dest, msgInfo.words[0],
194                   mr0 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr0 : 0,
195                   mr1 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr1 : 0,
196                   mr2 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr2 : 0,
197                   mr3 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr3 : 0
198                  );
199
200}
201
202static inline void
203seL4_Reply(seL4_MessageInfo_t msgInfo)
204{
205    riscv_sys_reply(seL4_SysReply, msgInfo.words[0], seL4_GetMR(0), seL4_GetMR(1), seL4_GetMR(2),
206                    seL4_GetMR(3));
207}
208
209static inline void
210seL4_ReplyWithMRs(seL4_MessageInfo_t msgInfo,
211                  seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
212{
213    riscv_sys_reply(seL4_SysReply, msgInfo.words[0],
214                    mr0 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr0 : 0,
215                    mr1 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr1 : 0,
216                    mr2 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr2 : 0,
217                    mr3 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0 ? *mr3 : 0
218                   );
219
220}
221
222static inline void
223seL4_Signal(seL4_CPtr dest)
224{
225    riscv_sys_send_null(seL4_SysSend, dest, seL4_MessageInfo_new(0, 0, 0, 0).words[0]);
226}
227
228static inline seL4_MessageInfo_t
229seL4_Recv(seL4_CPtr src, seL4_Word* sender)
230{
231    seL4_MessageInfo_t info;
232    seL4_Word badge;
233    seL4_Word msg0;
234    seL4_Word msg1;
235    seL4_Word msg2;
236    seL4_Word msg3;
237
238    riscv_sys_recv(seL4_SysRecv, src, &badge, &info.words[0], &msg0, &msg1, &msg2, &msg3);
239
240    seL4_SetMR(0, msg0);
241    seL4_SetMR(1, msg1);
242    seL4_SetMR(2, msg2);
243    seL4_SetMR(3, msg3);
244
245    /* Return back sender and message information. */
246    if (sender) {
247        *sender = badge;
248    }
249    return info;
250
251}
252
253static inline seL4_MessageInfo_t
254seL4_RecvWithMRs(seL4_CPtr src, seL4_Word* sender,
255                 seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
256{
257    seL4_MessageInfo_t info;
258    seL4_Word badge;
259    seL4_Word msg0 = 0;
260    seL4_Word msg1 = 0;
261    seL4_Word msg2 = 0;
262    seL4_Word msg3 = 0;
263
264    riscv_sys_recv(seL4_SysRecv, src, &badge, &info.words[0], &msg0, &msg1, &msg2, &msg3);
265
266    /* Write the message back out to memory. */
267    if (mr0 != seL4_Null) {
268        *mr0 = msg0;
269    }
270    if (mr1 != seL4_Null) {
271        *mr1 = msg1;
272    }
273    if (mr2 != seL4_Null) {
274        *mr2 = msg2;
275    }
276    if (mr3 != seL4_Null) {
277        *mr3 = msg3;
278    }
279
280    /* Return back sender and message information. */
281    if (sender) {
282        *sender = badge;
283    }
284    return info;
285}
286
287static inline seL4_MessageInfo_t
288seL4_NBRecv(seL4_CPtr src, seL4_Word* sender)
289{
290    seL4_MessageInfo_t info;
291    seL4_Word badge;
292    seL4_Word msg0;
293    seL4_Word msg1;
294    seL4_Word msg2;
295    seL4_Word msg3;
296
297    riscv_sys_recv(seL4_SysNBRecv, src, &badge, &info.words[0], &msg0, &msg1, &msg2, &msg3);
298
299    seL4_SetMR(0, msg0);
300    seL4_SetMR(1, msg1);
301    seL4_SetMR(2, msg2);
302    seL4_SetMR(3, msg3);
303
304    /* Return back sender and message information. */
305    if (sender) {
306        *sender = badge;
307    }
308    return info;
309
310}
311
312static inline seL4_MessageInfo_t
313seL4_Call(seL4_CPtr dest, seL4_MessageInfo_t msgInfo)
314{
315    seL4_MessageInfo_t info;
316    seL4_Word msg0 = seL4_GetMR(0);
317    seL4_Word msg1 = seL4_GetMR(1);
318    seL4_Word msg2 = seL4_GetMR(2);
319    seL4_Word msg3 = seL4_GetMR(3);
320
321    riscv_sys_send_recv(seL4_SysCall, dest, &dest, msgInfo.words[0], &info.words[0], &msg0, &msg1,
322                        &msg2, &msg3);
323
324    /* Write out the data back to memory. */
325    seL4_SetMR(0, msg0);
326    seL4_SetMR(1, msg1);
327    seL4_SetMR(2, msg2);
328    seL4_SetMR(3, msg3);
329
330    return info;
331}
332
333static inline void
334seL4_Wait(seL4_CPtr src, seL4_Word *sender)
335{
336    seL4_Recv(src, sender);
337}
338
339static inline seL4_MessageInfo_t
340seL4_Poll(seL4_CPtr src, seL4_Word *sender)
341{
342    return seL4_NBRecv(src, sender);
343}
344
345static inline seL4_MessageInfo_t
346seL4_CallWithMRs(seL4_CPtr dest, seL4_MessageInfo_t msgInfo,
347                 seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
348{
349    seL4_MessageInfo_t info;
350    seL4_Word msg0 = 0;
351    seL4_Word msg1 = 0;
352    seL4_Word msg2 = 0;
353    seL4_Word msg3 = 0;
354
355    if (mr0 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0) {
356        msg0 = *mr0;
357    }
358    if (mr1 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 1) {
359        msg1 = *mr1;
360    }
361    if (mr2 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 2) {
362        msg2 = *mr2;
363    }
364    if (mr3 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 3) {
365        msg3 = *mr3;
366    }
367
368    riscv_sys_send_recv(seL4_SysCall, dest, &dest, msgInfo.words[0], &info.words[0], &msg0, &msg1,
369                        &msg2, &msg3);
370
371    if (mr0 != seL4_Null) {
372        *mr0 = msg0;
373    }
374    if (mr1 != seL4_Null) {
375        *mr1 = msg1;
376    }
377    if (mr2 != seL4_Null) {
378        *mr2 = msg2;
379    }
380    if (mr3 != seL4_Null) {
381        *mr3 = msg3;
382    }
383
384    return info;
385}
386
387static inline seL4_MessageInfo_t
388seL4_ReplyRecv(seL4_CPtr src, seL4_MessageInfo_t msgInfo, seL4_Word *sender)
389{
390    seL4_MessageInfo_t info;
391    seL4_Word badge;
392    seL4_Word msg0;
393    seL4_Word msg1;
394    seL4_Word msg2;
395    seL4_Word msg3;
396
397    /* Load beginning of the message into registers. */
398    msg0 = seL4_GetMR(0);
399    msg1 = seL4_GetMR(1);
400    msg2 = seL4_GetMR(2);
401    msg3 = seL4_GetMR(3);
402
403    riscv_sys_send_recv(seL4_SysReplyRecv, src, &badge, msgInfo.words[0], &info.words[0], &msg0,
404                        &msg1, &msg2, &msg3);
405
406    /* Write the message back out to memory. */
407    seL4_SetMR(0, msg0);
408    seL4_SetMR(1, msg1);
409    seL4_SetMR(2, msg2);
410    seL4_SetMR(3, msg3);
411
412    /* Return back sender and message information. */
413    if (sender) {
414        *sender = badge;
415    }
416
417    return info;
418
419}
420
421static inline seL4_MessageInfo_t
422seL4_ReplyRecvWithMRs(seL4_CPtr src, seL4_MessageInfo_t msgInfo, seL4_Word *sender,
423                      seL4_Word *mr0, seL4_Word *mr1, seL4_Word *mr2, seL4_Word *mr3)
424{
425    seL4_MessageInfo_t info;
426    seL4_Word badge;
427    seL4_Word msg0 = 0;
428    seL4_Word msg1 = 0;
429    seL4_Word msg2 = 0;
430    seL4_Word msg3 = 0;
431
432    if (mr0 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 0) {
433        msg0 = *mr0;
434    }
435    if (mr1 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 1) {
436        msg1 = *mr1;
437    }
438    if (mr2 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 2) {
439        msg2 = *mr2;
440    }
441    if (mr3 != seL4_Null && seL4_MessageInfo_get_length(msgInfo) > 3) {
442        msg3 = *mr3;
443    }
444
445    riscv_sys_send_recv(seL4_SysReplyRecv, src, &badge, msgInfo.words[0], &info.words[0], &msg0,
446                        &msg1, &msg2, &msg3);
447
448    /* Write out the data back to memory. */
449    if (mr0 != seL4_Null) {
450        *mr0 = msg0;
451    }
452    if (mr1 != seL4_Null) {
453        *mr1 = msg1;
454    }
455    if (mr2 != seL4_Null) {
456        *mr2 = msg2;
457    }
458    if (mr3 != seL4_Null) {
459        *mr3 = msg3;
460    }
461
462    /* Return back sender and message information. */
463    if (sender) {
464        *sender = badge;
465    }
466
467    return info;
468}
469
470static inline void
471seL4_Yield(void)
472{
473    register seL4_Word scno asm("a7") = seL4_SysYield;
474    asm volatile ("ecall" :: "r"(scno));
475}
476
477#ifdef CONFIG_PRINTING
478static inline void
479seL4_DebugPutChar(char c)
480{
481    seL4_Word unused0 = 0;
482    seL4_Word unused1 = 0;
483    seL4_Word unused2 = 0;
484    seL4_Word unused3 = 0;
485    seL4_Word unused4 = 0;
486    seL4_Word unused5 = 0;
487
488    riscv_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, &unused3,
489                        &unused4, &unused5);
490}
491
492LIBSEL4_INLINE_FUNC void
493seL4_DebugDumpScheduler(void)
494{
495    seL4_Word unused0 = 0;
496    seL4_Word unused1 = 0;
497    seL4_Word unused2 = 0;
498    seL4_Word unused3 = 0;
499    seL4_Word unused4 = 0;
500    seL4_Word unused5 = 0;
501
502    riscv_sys_send_recv(seL4_SysDebugDumpScheduler, 0, &unused0, 0, &unused1, &unused2, &unused3,
503                        &unused4, &unused5);
504}
505#endif
506
507#ifdef CONFIG_DEBUG_BUILD
508static inline void
509seL4_DebugHalt(void)
510{
511    register seL4_Word scno asm("a7") = seL4_SysDebugHalt;
512    asm volatile ("ecall" :: "r"(scno) : "memory");
513}
514
515static inline void
516seL4_DebugSnapshot(void)
517{
518    register seL4_Word scno asm("a7") = seL4_SysDebugSnapshot;
519    asm volatile ("ecall" ::"r"(scno) : "memory");
520}
521
522static inline seL4_Uint32
523seL4_DebugCapIdentify(seL4_CPtr cap)
524{
525    seL4_Word unused0 = 0;
526    seL4_Word unused1 = 0;
527    seL4_Word unused2 = 0;
528    seL4_Word unused3 = 0;
529    seL4_Word unused4 = 0;
530
531    riscv_sys_send_recv(seL4_SysDebugCapIdentify, cap, &cap, 0, &unused0, &unused1, &unused2,
532                        &unused3, &unused4);
533    return (seL4_Uint32)cap;
534}
535
536char *strcpy(char *, const char *);
537LIBSEL4_INLINE_FUNC void
538seL4_DebugNameThread(seL4_CPtr tcb, const char *name)
539{
540    strcpy((char*)seL4_GetIPCBuffer()->msg, name);
541
542    seL4_Word unused0 = 0;
543    seL4_Word unused1 = 0;
544    seL4_Word unused2 = 0;
545    seL4_Word unused3 = 0;
546    seL4_Word unused4 = 0;
547    seL4_Word unused5 = 0;
548
549    riscv_sys_send_recv(seL4_SysDebugNameThread, tcb, &unused0, 0, &unused1, &unused2, &unused3,
550                        &unused4, &unused5);
551}
552#endif
553
554#ifdef SEL4_DANGEROUS_CODE_INJECTION_KERNEL
555static inline void
556seL4_DebugRun(void (* userfn) (void *), void* userarg)
557{
558    register seL4_Word arg1 asm("a0") = (seL4_Word)userfn;
559    register seL4_Word arg2 asm("a1") = (seL4_Word)userarg;
560    register seL4_Word scno asm("a7") = seL4_SysDebugRun;
561    asm volatile ("ecall" : "+r"(arg1) : "r"(arg2), "r"(scno));
562}
563#endif
564
565#endif
566