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