1/* 2 * Copyright 2017, 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 BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#ifndef __LIBSEL4_SEL4_ARCH_SYSCALLS_H 14#define __LIBSEL4_SEL4_ARCH_SYSCALLS_H 15 16#include <autoconf.h> 17#include <sel4/arch/functions.h> 18#include <sel4/types.h> 19 20/* 21 * To simplify the definition of the various seL4 syscalls/syscall-wrappers we define 22 * some helper assembly functions. These functions are designed to cover the different 23 * cases of sending/receiving data in registers to/from the kernel. The most 'complex' 24 * version is arm_sys_send_recv, and all other functions are limited versions that allow 25 * for registers to not be unnecessarily clobbered 26 * 27 * arm_sys_send: Fills all registers into the kernel, expects nothing to be sent back 28 * by the kernel. Used for direction one way sends that contain data (e.g. seL4_Send, 29 * seL4_NBSend) 30 * 31 * arm_sys_send_null: Only fills metadata registers into the kernel (skips message 32 * registers). Expects nothing to be sent back by the kernel. Used by directional 33 * one way sends that do not contain data (e.g. seL4_Notify) 34 * 35 * arm_sys_reply: Similar to arm_sys_send except it does not take a word for the 36 * destination register. Used for undirected one way sends that contain data 37 * (e.g. seL4_Reply) 38 * 39 * arm_sys_recv: Sends one register (destination) to the kernel and expects all 40 * registers to be returned by the kernel. Used for directed receives that return 41 * data (e.g. seL4_Recv) 42 * 43 * arm_sys_send_recv: Fills all registers into the kernel and expects all of them 44 * to be filled on return by the kernel. Used for directed send+receives 45 * where data flows both directions (e.g. seL4_Call, seL4_ReplyWait) 46 * 47 * arm_sys_null: Does not send any registers to the kernel or expect anything to 48 * be returned from the kernel. Used to trigger implicit kernel actions without 49 * any data (e.g. seL4_Yield) 50 */ 51 52static inline void 53arm_sys_send(seL4_Word sys, seL4_Word dest, seL4_Word info_arg, seL4_Word mr0, seL4_Word mr1, seL4_Word mr2, seL4_Word mr3) 54{ 55 register seL4_Word destptr asm("r0") = dest; 56 register seL4_Word info asm("r1") = info_arg; 57 58 /* Load beginning of the message into registers. */ 59 register seL4_Word msg0 asm("r2") = mr0; 60 register seL4_Word msg1 asm("r3") = mr1; 61 register seL4_Word msg2 asm("r4") = mr2; 62 register seL4_Word msg3 asm("r5") = mr3; 63 64 /* Perform the system call. */ 65 register seL4_Word scno asm("r7") = sys; 66 asm volatile ( 67 "swi $0" 68 : "+r" (destptr), "+r" (msg0), "+r" (msg1), "+r" (msg2), 69 "+r" (msg3), "+r" (info) 70 : "r"(scno) 71 ); 72} 73 74static inline void 75arm_sys_reply(seL4_Word sys, seL4_Word info_arg, seL4_Word mr0, seL4_Word mr1, seL4_Word mr2, seL4_Word mr3) 76{ 77 register seL4_Word info asm("r1") = info_arg; 78 79 /* Load beginning of the message into registers. */ 80 register seL4_Word msg0 asm("r2") = mr0; 81 register seL4_Word msg1 asm("r3") = mr1; 82 register seL4_Word msg2 asm("r4") = mr2; 83 register seL4_Word msg3 asm("r5") = mr3; 84 85 /* Perform the system call. */ 86 register seL4_Word scno asm("r7") = sys; 87 asm volatile ( 88 "swi $0" 89 : "+r" (msg0), "+r" (msg1), "+r" (msg2), "+r" (msg3), 90 "+r" (info) 91 : "r"(scno) 92 ); 93} 94 95static inline void 96arm_sys_send_null(seL4_Word sys, seL4_Word src, seL4_Word info_arg) 97{ 98 register seL4_Word destptr asm("r0") = src; 99 register seL4_Word info asm("r1") = info_arg; 100 101 /* Perform the system call. */ 102 register seL4_Word scno asm("r7") = sys; 103 asm volatile ( 104 "swi $0" 105 : "+r" (destptr), "+r" (info) 106 : "r"(scno) 107 ); 108} 109 110static inline void 111arm_sys_recv(seL4_Word sys, seL4_Word src, seL4_Word *out_badge, seL4_Word *out_info, seL4_Word *out_mr0, seL4_Word *out_mr1, seL4_Word *out_mr2, seL4_Word *out_mr3) 112{ 113 register seL4_Word src_and_badge asm("r0") = src; 114 register seL4_Word info asm("r1"); 115 116 /* Incoming message registers. */ 117 register seL4_Word msg0 asm("r2"); 118 register seL4_Word msg1 asm("r3"); 119 register seL4_Word msg2 asm("r4"); 120 register seL4_Word msg3 asm("r5"); 121 122 /* Perform the system call. */ 123 register seL4_Word scno asm("r7") = sys; 124 asm volatile ( 125 "swi $0" 126 : "=r" (msg0), "=r" (msg1), "=r" (msg2), "=r" (msg3), 127 "=r" (info), "+r" (src_and_badge) 128 : "r"(scno) 129 : "memory" 130 ); 131 *out_badge = src_and_badge; 132 *out_info = info; 133 *out_mr0 = msg0; 134 *out_mr1 = msg1; 135 *out_mr2 = msg2; 136 *out_mr3 = msg3; 137} 138 139static inline void 140arm_sys_send_recv(seL4_Word sys, seL4_Word dest, seL4_Word *out_badge, seL4_Word info_arg, seL4_Word *out_info, seL4_Word *in_out_mr0, seL4_Word *in_out_mr1, seL4_Word *in_out_mr2, seL4_Word *in_out_mr3) 141{ 142 register seL4_Word destptr asm("r0") = dest; 143 register seL4_Word info asm("r1") = info_arg; 144 145 /* Load beginning of the message into registers. */ 146 register seL4_Word msg0 asm("r2") = *in_out_mr0; 147 register seL4_Word msg1 asm("r3") = *in_out_mr1; 148 register seL4_Word msg2 asm("r4") = *in_out_mr2; 149 register seL4_Word msg3 asm("r5") = *in_out_mr3; 150 151 /* Perform the system call. */ 152 register seL4_Word scno asm("r7") = sys; 153 asm volatile ( 154 "swi $0" 155 : "+r" (msg0), "+r" (msg1), "+r" (msg2), "+r" (msg3), 156 "+r" (info), "+r" (destptr) 157 : "r"(scno) 158 : "memory" 159 ); 160 *out_info = info; 161 *out_badge = destptr; 162 *in_out_mr0 = msg0; 163 *in_out_mr1 = msg1; 164 *in_out_mr2 = msg2; 165 *in_out_mr3 = msg3; 166} 167 168static inline void 169arm_sys_null(seL4_Word sys) 170{ 171 register seL4_Word scno asm("r7") = sys; 172 asm volatile ( 173 "swi $0" 174 : /* no outputs */ 175 : "r"(scno) 176 ); 177} 178 179#endif /* __LIBSEL4_SEL4_ARCH_SYSCALLS_H */ 180