/* Iris: micro-kernel for a capability-based operating system. * iris.h: C header file for userspace programs. * Copyright 2009 Bas Wijnen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __IRIS_H #define __IRIS_H // Without the standard library, we don't have this definition. // I preferred ((void*)0), but C++ has too strict type-checking to // make that work. #ifndef NULL #define NULL 0 #endif #ifdef __cplusplus extern "C" { #endif // Number of clock interrupts per second. #define HZ 20 #define PAGE_BITS (12) #define PAGE_SIZE (1 << PAGE_BITS) #define PAGE_MASK (~(PAGE_SIZE - 1)) enum Exception_code { ERR_WRITE_DENIED, ERR_UNMAPPED_READ, ERR_UNMAPPED_WRITE, ERR_INVALID_ADDRESS_READ, ERR_INVALID_ADDRESS_WRITE, ERR_RESERVED_INSTRUCTION, ERR_COPROCESSOR_UNUSABLE, ERR_OVERFLOW, ERR_TRAP, ERR_WATCHPOINT, ERR_NO_PAGE_DIRECTORY, ERR_NO_PAGE_TABLE, ERR_OUT_OF_MEMORY, NUM_EXCEPTION_CODES }; #ifndef NDEBUG static const char *exception_name[NUM_EXCEPTION_CODES] = { "write denied", "unmapped read", "unmapped write", "invalid address read", "invalid address write", "reserved instruction", "coprocessor unusable", "overflow", "trap", "watchpoint", "no page directory", "no page table", "out of memory" }; #endif #define KERNEL_MASK 0xfff #define CAPTYPE_MASK 0xe00 #define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK) #define CAPTYPE_RECEIVER 0x000 #define CAPTYPE_MEMORY 0x200 #define CAPTYPE_THREAD 0x400 #define CAPTYPE_PAGE 0x600 #define CAPTYPE_CAPABILITY 0x800 #define CAPTYPE_CAPPAGE 0xa00 /*#define CAPTYPE_??? 0xc00*/ /*#define CAPTYPE_??? 0xe00*/ /* This works on all kernel capabilities. */ #define CAP_DEGRADE 0 /* Operations */ #define CAP_RECEIVER_SET_OWNER 1 #define CAP_RECEIVER_CREATE_CAPABILITY 2 #define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3 #define CAP_RECEIVER_REPLY_PROTECTED_DATA 4 #define CAP_RECEIVER_ALARM 5 #define CAP_RECEIVER_ALL_RIGHTS 0x7f /* Not an operation; a capability with this bit set is a call capability. */ #define CAP_RECEIVER_CALL 7 /* Same thing for reply capability. */ #define CAP_RECEIVER_REPLY 8 /* If set on a call capability, waiting for only this reply is disabled. */ #define CAP_RECEIVER_CALL_ASYNC 1 #define CAP_MEMORY_CREATE 1 #define CAP_MEMORY_DESTROY 2 #define CAP_MEMORY_LIST 3 #define CAP_MEMORY_MAP 4 #define CAP_MEMORY_MAPPING 5 #define CAP_MEMORY_LIMIT 6 #define CAP_MEMORY_DROP 8 #define CAP_MEMORY_ALL_RIGHTS 0x1ff #define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */ #define CAP_THREAD_SCHEDULE 2 #define CAP_THREAD_ALLOC_RANGE 3 #define CAP_THREAD_PHYSICAL_ADDRESS 4 #define CAP_THREAD_ALLOC_PHYSICAL 5 #define CAP_THREAD_MAKE_PRIV 6 #define CAP_THREAD_GET_TOP_MEMORY 7 #define CAP_THREAD_REGISTER_INTERRUPT 8 #define CAP_THREAD_ALL_RIGHTS 0x07 #define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL) | (1 << CAP_THREAD_PHYSICAL_ADDRESS) | (1 << CAP_THREAD_ALLOC_RANGE)) /* These get/set_info are not arch-specific. */ #define CAP_THREAD_INFO_PC ~0 #define CAP_THREAD_INFO_SP ~1 #define CAP_THREAD_INFO_FLAGS ~2 /* Flag values for processor state */ #define THREAD_FLAG_PRIV 0x80000000 #define THREAD_FLAG_WAITING 0x40000000 #define THREAD_FLAG_RUNNING 0x20000000 #define THREAD_FLAG_USER 0x1fffffff #define CAP_PAGE_SHARE 1 #define CAP_PAGE_FLAGS 2 /* Not an operation; a capability without this bit cannot write to the page. */ #define CAP_PAGE_WRITE 3 #define CAP_PAGE_ALL_RIGHTS 0x1ff /* Operation details for PAGE_SHARE */ /* Forget the source page during the operation. This makes it a move. */ #define PAGE_SHARE_FORGET 0x10000 /* Make the target unwritable. */ #define PAGE_SHARE_READONLY 0x20000 /* Make the target independent of the source (make a copy if needed). */ #define PAGE_SHARE_COPY 0x40000 /* Flag values for Page and Cappage objects. */ /* A writable page can be written to. This flag can not be set while the frame is shared. */ #define PAGE_FLAG_WRITABLE 1 /* When paying, the memory's use is incremented. If a frame is held, it cannot be lost. Frames are lost when the last payer forgets them. */ #define PAGE_FLAG_PAYING 2 /* Set if this page has a frame associated with it. This flag is automatically reset if the frame is lost because of payment problems. */ #define PAGE_FLAG_FRAME 4 /* This is a read-only flag, which is set if the Page is shared. */ #define PAGE_FLAG_SHARED 8 /* This is a read-only flag, saying if this is physical memory, which mustn't be freed. */ #define PAGE_FLAG_PHYSICAL 0x10 /* This is a read-only flag, saying if this is uncachable memory. */ #define PAGE_FLAG_UNCACHED 0x20 #define CAP_CAPABILITY_GET 1 #define CAP_CAPABILITY_ALL_RIGHTS 0x1ff #define CAPPAGE_SIZE 102 /* Cappage has Page's operations as well. */ #define CAP_CAPPAGE_SET 4 #define CAP_CAPPAGE_ALL_RIGHTS 0x1ff #ifndef __KERNEL typedef unsigned Capability; extern Capability __my_receiver; extern Capability __my_thread; extern Capability __my_memory; extern Capability __my_call; extern Capability __my_parent; static Capability cap_copy (Capability src) { return src | 2; } static Capability cappage_cap (unsigned base, unsigned idx) { return base | (idx << 2) | 1; } typedef struct Message { unsigned data[4]; Capability cap[4]; unsigned protected_data; /* only used for receiving. */ } Message; static void invoke (Capability target, Message *msg) { unsigned ret; __asm__ volatile ("lw $v0, %0\n" "\tlw $a3, %1\n" "\tlw $t0, 0($a3)\n" "\tlw $t1, 4($a3)\n" "\tlw $t2, 8($a3)\n" "\tlw $t3, 12($a3)\n" "\tlw $a0, 16($a3)\n" "\tlw $a1, 20($a3)\n" "\tlw $a2, 24($a3)\n" "\tlw $a3, 28($a3)\n" "\tsyscall" : : "m"(target), "m"(msg) : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); } static void wait (Message *msg) { __asm__ volatile ("li $v0, 2\n" "\tsyscall\n" "\tlw $v1, %0\n" "\tsw $t0, 0($v1)\n" "\tsw $t1, 4($v1)\n" "\tsw $t2, 8($v1)\n" "\tsw $t3, 12($v1)\n" "\tsw $a0, 16($v1)\n" "\tsw $a1, 20($v1)\n" "\tsw $a2, 24($v1)\n" "\tsw $a3, 28($v1)\n" "\tsw $v0, 32($v1)" : : "m"(msg) : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); } static void call (Capability target, Message *msg) { Capability t = cap_copy (target); __asm__ volatile ("lw $v0, %0\n" "\tlw $v1, %1\n" "\tlw $t0, 0($v1)\n" "\tlw $t1, 4($v1)\n" "\tlw $t2, 8($v1)\n" "\tlw $t3, 12($v1)\n" "\tlw $a0, 16($v1)\n" "\tlw $a1, 20($v1)\n" "\tlw $a2, 24($v1)\n" "\tlw $a3, 28($v1)\n" "\tsyscall\n" "\tlw $v1, %1\n" "\tsw $t0, 0($v1)\n" "\tsw $t1, 4($v1)\n" "\tsw $t2, 8($v1)\n" "\tsw $t3, 12($v1)\n" "\tsw $a0, 16($v1)\n" "\tsw $a1, 20($v1)\n" "\tsw $a2, 24($v1)\n" "\tsw $a3, 28($v1)\n" "\tsw $v0, 32($v1)" : : "m"(t), "m"(msg) : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); } static void invoke_00 (Capability t) { Message msg; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[0] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_01 (Capability t, unsigned d) { Message msg; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[0] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_02 (Capability t, unsigned d0, unsigned d1) { Message msg; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[0] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_03 (Capability t, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; msg.cap[0] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3) { Message msg; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = d3; msg.cap[0] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_10 (Capability t, Capability c) { Message msg; msg.cap[0] = c; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_11 (Capability t, Capability c, unsigned d) { Message msg; msg.cap[0] = c; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_12 (Capability t, Capability c, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_13 (Capability t, Capability c, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_20 (Capability t, Capability c0, Capability c1) { Message msg; msg.cap[0] = c0; msg.cap[1] = c1; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_21 (Capability t, Capability c0, Capability c1, unsigned d) { Message msg; msg.cap[0] = c0; msg.cap[1] = c1; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_31 (Capability t, Capability c0, Capability c1, Capability c2, unsigned d) { Message msg; msg.cap[0] = c0; msg.cap[1] = c1; msg.cap[2] = c2; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[3] = 0; invoke (t, &msg); } static void invoke_41 (Capability t, Capability c0, Capability c1, Capability c2, Capability c3, unsigned d) { Message msg; msg.cap[0] = c0; msg.cap[1] = c1; msg.cap[2] = c2; msg.cap[3] = c3; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; invoke (t, &msg); } static void call_00 (Capability c) { Message msg; msg.cap[0] = c; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); } static unsigned call_n00 (Capability c) { Message msg; msg.cap[0] = c; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static Capability call_c00 (Capability c) { Message msg; msg.cap[0] = c; msg.data[0] = 0; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.cap[0]; } static Capability call_c01 (Capability c, unsigned d) { Message msg; msg.cap[0] = c; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.cap[0]; } static unsigned long long call_l01 (Capability c, unsigned d) { Message msg; msg.cap[0] = c; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32); } static Capability call_c02 (Capability c, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.cap[0]; } static unsigned long long call_l02 (Capability c, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32); } static Capability call_c03 (Capability c, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.cap[0]; } static unsigned long long call_l04 (Capability c, unsigned d0, unsigned d1, unsigned d2, unsigned d3) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = d3; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32); } static Capability call_c12 (Capability c, Capability c1, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.cap[0]; } static unsigned call_n01 (Capability c, unsigned d) { Message msg; msg.cap[0] = c; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n11 (Capability c, Capability c1, unsigned d) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.data[0] = d; msg.data[1] = 0; msg.data[2] = 0; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n12 (Capability c, Capability c1, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n14 (Capability c, Capability c1, unsigned d0, unsigned d1, unsigned d2, unsigned d3) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = d3; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n02 (Capability c, unsigned d0, unsigned d1) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static Capability call_p02 (Capability c, unsigned d0, unsigned d1, unsigned *base_return) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = 0; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); *base_return = msg.data[0]; return msg.cap[0]; } static unsigned call_n03 (Capability c, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n04 (Capability c, unsigned d0, unsigned d1, unsigned d2, unsigned d3) { Message msg; msg.cap[0] = c; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = d3; msg.data[3] = 0; msg.cap[1] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n13 (Capability c, Capability c1, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; msg.cap[2] = 0; msg.cap[3] = 0; call (__my_call, &msg); return msg.data[0]; } static unsigned call_n33 (Capability c, Capability c1, Capability c2, Capability c3, unsigned d0, unsigned d1, unsigned d2) { Message msg; msg.cap[0] = c; msg.cap[1] = c1; msg.cap[2] = c2; msg.cap[3] = c3; msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = 0; call (__my_call, &msg); return msg.data[0]; } static Capability degrade (Capability src, unsigned mask) { return call_c02 (src, CAP_DEGRADE, mask); } static void schedule () { invoke_01 (__my_thread, CAP_THREAD_SCHEDULE); } static void register_interrupt (unsigned num) { invoke_12 (__my_thread, __my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num); } static void unregister_interrupt (unsigned num) { invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num); } static Capability get_top_memory () { return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY); } static void alloc_physical (Capability page, unsigned address, int cachable, int freeable) { invoke_13 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, address & PAGE_MASK, (cachable ? 1 : 0) | (freeable ? 2 : 0)); } static unsigned alloc_range (Capability memory, unsigned pages) { return call_n12 (__my_thread, memory, CAP_THREAD_ALLOC_RANGE, pages); } static void receiver_set_owner (Capability receiver, Capability owner) { invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER); } static Capability receiver_create_capability (Capability receiver, unsigned protected_data) { return call_c02 (receiver, CAP_RECEIVER_CREATE_CAPABILITY, protected_data); } static unsigned receiver_reply_protected_data (Capability receiver, int set, unsigned data) { return call_n03 (receiver, CAP_RECEIVER_REPLY_PROTECTED_DATA, (unsigned)set, data); } static unsigned receiver_get_reply_protected_data (Capability receiver) { return receiver_reply_protected_data (receiver, 0, 0); } static unsigned receiver_set_reply_protected_data (Capability receiver, unsigned data) { return receiver_reply_protected_data (receiver, 1, data); } static unsigned receiver_alarm (Capability receiver, int set, unsigned data) { return call_n03 (receiver, CAP_RECEIVER_ALARM, (unsigned)set, data); } static unsigned receiver_get_alarm (Capability receiver) { return receiver_alarm (receiver, 0, 0); } static unsigned receiver_add_alarm (Capability receiver, unsigned data) { return receiver_alarm (receiver, 0, data); } static unsigned receiver_set_alarm (Capability receiver, unsigned data) { return receiver_alarm (receiver, 1, data); } static void my_sleep (unsigned value, Message *ret) { receiver_set_alarm (__my_receiver, value); wait (ret); } static Capability receiver_create_call_capability (Capability receiver) { return call_c02 (receiver, CAP_RECEIVER_CREATE_CALL_CAPABILITY, 0); } static Capability receiver_create_async_call_capability (Capability receiver) { return call_c02 (receiver, CAP_RECEIVER_CREATE_CALL_CAPABILITY, 1); } static Capability memory_create (Capability memory, unsigned type) { return call_c02 (memory, CAP_MEMORY_CREATE, type); } static Capability memory_create_page (Capability memory) { return memory_create (memory, CAPTYPE_PAGE | REQUEST_MASK); } static Capability memory_create_thread (Capability memory) { return memory_create (memory, CAPTYPE_THREAD | REQUEST_MASK); } static Capability memory_create_receiver (Capability memory) { return memory_create (memory, CAPTYPE_RECEIVER | REQUEST_MASK); } static Capability memory_create_memory (Capability memory) { return memory_create (memory, CAPTYPE_MEMORY | REQUEST_MASK); } static Capability memory_create_cappage (Capability memory, unsigned *base_return) { return call_p02 (memory, CAP_MEMORY_CREATE, CAPTYPE_CAPPAGE | REQUEST_MASK, base_return); } static void memory_destroy (Capability memory, Capability target) { invoke_11 (memory, target, CAP_MEMORY_DESTROY); } /* TODO: #define CAP_MEMORY_LIST 3 */ static void memory_map (Capability memory, Capability page, unsigned address, int writable) { if (writable) address |= 1 << CAP_PAGE_WRITE; invoke_12 (memory, page, CAP_MEMORY_MAP, address); } static Capability memory_mapping (Capability memory, void *address) { return call_c02 (memory, CAP_MEMORY_MAPPING, (unsigned)address); } static unsigned memory_limit (Capability memory, unsigned limit) { return call_c02 (memory, CAP_MEMORY_LIMIT, limit); } static void drop (Capability cap) { invoke_11 (__my_memory, cap, CAP_MEMORY_DROP); } static Capability thread_make_priv (Capability thread) { return call_c12 (__my_thread, thread, CAP_THREAD_MAKE_PRIV, ~0); } static unsigned thread_info (Capability thread, unsigned info, unsigned value, unsigned mask) { return call_n04 (thread, CAP_THREAD_INFO, info, value, mask); } static unsigned thread_set_pc (Capability thread, unsigned pc) { return thread_info (thread, CAP_THREAD_INFO_PC, pc, ~0); } static unsigned thread_set_sp (Capability thread, unsigned sp) { return thread_info (thread, CAP_THREAD_INFO_SP, sp, ~0); } static unsigned thread_flags (Capability thread, unsigned value, unsigned mask) { return thread_info (thread, CAP_THREAD_INFO_FLAGS, value, mask); } static unsigned thread_run (Capability thread, int run) { return thread_flags (thread, run ? THREAD_FLAG_RUNNING : 0, THREAD_FLAG_RUNNING); } static unsigned thread_wait (Capability thread, int wait) { return thread_flags (thread, wait ? THREAD_FLAG_WAITING : 0, THREAD_FLAG_WAITING); } static unsigned thread_get_pc (Capability thread) { return thread_info (thread, CAP_THREAD_INFO_PC, 0, 0); } static unsigned thread_get_sp (Capability thread) { return thread_info (thread, CAP_THREAD_INFO_SP, 0, 0); } static void page_share (Capability page, Capability target, unsigned flags) { invoke_12 (page, target, CAP_PAGE_SHARE, flags); } static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask) { return call_n03 (page, CAP_PAGE_FLAGS, new_flags, mask); } static unsigned page_physical_address (Capability page) { return call_n11 (__my_thread, page, CAP_THREAD_PHYSICAL_ADDRESS); } static Capability capability_get (Capability cap) { return call_c01 (cap, CAP_CAPABILITY_GET); } static void cappage_set (Capability page, Capability cap, unsigned index) { invoke_12 (page, cap, CAP_CAPPAGE_SET, index); } /* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */ #define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0) #define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); } while (0) static void kdebug_num (unsigned n) { unsigned i; const char *encode = "0123456789abcdef"; for (i = 0; i < 8; ++i) kdebug_char (encode[(n >> (4 * (7 - i))) & 0xf]); } #endif #ifdef __cplusplus } #endif #endif