1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-30 22:36:23 +03:00
iris/iris.h
2009-08-05 10:16:24 +02:00

1024 lines
25 KiB
C

/* Iris: micro-kernel for a capability-based operating system.
* iris.h: C header file for userspace programs.
* Copyright 2009 Bas Wijnen <wijnen@debian.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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 100
#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_BREAKPOINT,
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",
"breakpoint",
"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_CAPS 0x800
/*#define CAPTYPE_??? 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_ALL_RIGHTS 0x1ff
#define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */
#define CAP_THREAD_SCHEDULE 2
#define CAP_THREAD_CAP_CLONE 3
#define CAP_THREAD_PRIV 8
#define CAP_THREAD_PRIV_ALLOC_RANGE 0
#define CAP_THREAD_PRIV_PHYSICAL_ADDRESS 1
#define CAP_THREAD_PRIV_ALLOC_PHYSICAL 2
#define CAP_THREAD_PRIV_MAKE_PRIV 3
#define CAP_THREAD_PRIV_GET_TOP_MEMORY 4
#define CAP_THREAD_PRIV_REGISTER_INTERRUPT 5
#define CAP_THREAD_ALL_RIGHTS 0x0ff
#define CAP_THREAD_ALL_PRIV_RIGHTS 0x1ff
/* 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_CAPS_SET 1
#define CAP_CAPS_ALL_RIGHTS 0x1ff
#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
/* If this flag is set in a capability, it is copied instead of mapped. */
/* If it is set in the target capability, the Thread waits after the request. */
#define CAPABILITY_COPY 0x80000000
/* This constant can be used to signify that no capability is passed or accepted. */
#define CAPABILITY_NONE (~CAPABILITY_COPY)
#define __my_receiver 1
#define __my_thread 2
#define __my_memory 3
#define __my_call 4
#define __my_parent 5
#ifndef __KERNEL
typedef unsigned Capability;
static Capability cap_copy (Capability src)
{
return src | CAPABILITY_COPY;
}
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, Capability r0, Capability r1, Capability r2, Capability r3)
{
__asm__ volatile ("li $v0, 0x80000000\n"
"\tlw $t4, %1\n"
"\tlw $t5, %2\n"
"\tlw $t6, %3\n"
"\tlw $t7, %4\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 $v0, 32($v1)"
:
: "m"(msg), "m"(r0), "m"(r1), "m"(r2), "m"(r3)
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "a0", "a1", "a2", "a3");
}
static void call (Capability target, Message *msg, Capability r0, Capability r1, Capability r2, Capability r3)
{
Capability t = cap_copy (target);
__asm__ volatile ("lw $v0, %0\n"
"\tlw $v1, %1\n"
"\tlw $t4, %1\n"
"\tlw $t5, %2\n"
"\tlw $t6, %3\n"
"\tlw $t7, %4\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 $v0, 32($v1)"
:
: "m" (t), "m" (msg), "m" (r0), "m" (r1), "m" (r2), "m" (r3)
: "memory", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7");
}
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_14 (Capability t, 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;
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return msg.data[0];
}
static void call_c00 (Capability c, Capability target)
{
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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
static void call_c01 (Capability c, Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32);
}
static void call_c02 (Capability c, Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32);
}
static void call_c03 (Capability c, Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return (unsigned long long)msg.data[0] | ((unsigned long long)msg.data[1] << 32);
}
static void call_c12 (Capability c, Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
static void call_c13 (Capability c, Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
*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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return msg.data[0];
}
static void call_c11 (Capability target, 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, target, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
return msg.data[0];
}
static void degrade (Capability target, Capability src, unsigned mask)
{
call_c02 (src, target, CAP_DEGRADE, mask);
}
static void schedule ()
{
invoke_01 (__my_thread, CAP_THREAD_SCHEDULE);
}
static void capability_clone (Capability target, Capability src)
{
call_c11 (__my_thread, target, src, CAP_THREAD_CAP_CLONE);
}
static void register_interrupt (unsigned num)
{
invoke_13 (__my_thread, __my_receiver, CAP_THREAD_PRIV, CAP_THREAD_PRIV_REGISTER_INTERRUPT, num);
}
static void unregister_interrupt (unsigned num)
{
invoke_03 (__my_thread, CAP_THREAD_PRIV, CAP_THREAD_PRIV_REGISTER_INTERRUPT, num);
}
static void get_top_memory (Capability target)
{
return call_c02 (__my_thread, target, CAP_THREAD_PRIV, CAP_THREAD_PRIV_GET_TOP_MEMORY);
}
static void alloc_physical (Capability page, unsigned address, int cachable, int freeable)
{
invoke_14 (__my_thread, page, CAP_THREAD_PRIV, CAP_THREAD_PRIV_ALLOC_PHYSICAL, address & PAGE_MASK, (cachable ? 1 : 0) | (freeable ? 2 : 0));
}
static unsigned alloc_range (Capability memory, unsigned pages)
{
return call_n13 (__my_thread, memory, CAP_THREAD_PRIV, CAP_THREAD_PRIV_ALLOC_RANGE, pages);
}
static void receiver_set_owner (Capability receiver, Capability owner)
{
invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER);
}
static void receiver_create_capability (Capability target, Capability receiver, unsigned protected_data)
{
return call_c02 (receiver, target, 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, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE, CAPABILITY_NONE);
}
static void receiver_create_call_capability (Capability target, Capability receiver)
{
return call_c02 (receiver, target, CAP_RECEIVER_CREATE_CALL_CAPABILITY, 0);
}
static void receiver_create_async_call_capability (Capability target, Capability receiver)
{
return call_c02 (receiver, target, CAP_RECEIVER_CREATE_CALL_CAPABILITY, 1);
}
static void memory_create (Capability target, Capability memory, unsigned type)
{
return call_c02 (memory, target, CAP_MEMORY_CREATE, type);
}
static void memory_create_page (Capability target, Capability memory)
{
return memory_create (memory, target, CAPTYPE_PAGE | REQUEST_MASK);
}
static void memory_create_thread (Capability target, Capability memory)
{
return memory_create (memory, target, CAPTYPE_THREAD | REQUEST_MASK);
}
static void memory_create_receiver (Capability target, Capability memory)
{
return memory_create (memory, target, CAPTYPE_RECEIVER | REQUEST_MASK);
}
static void memory_create_memory (Capability target, Capability memory)
{
return memory_create (memory, target, CAPTYPE_MEMORY | REQUEST_MASK);
}
static void memory_create_caps (Capability target, Capability memory)
{
return memory_create (memory, target, CAPTYPE_CAPS | REQUEST_MASK);
}
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 void memory_mapping (Capability target, Capability memory, void *address)
{
call_c02 (memory, target, CAP_MEMORY_MAPPING, (unsigned)address);
}
static unsigned memory_limit (Capability memory, unsigned limit)
{
return call_n02 (memory, CAP_MEMORY_LIMIT, limit);
}
static void thread_make_priv (Capability target, Capability thread)
{
call_c13 (__my_thread, target, thread, CAP_THREAD_PRIV, CAP_THREAD_PRIV_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_n12 (__my_thread, page, CAP_THREAD_PRIV, CAP_THREAD_PRIV_PHYSICAL_ADDRESS);
}
static void caps_set (Capability caps, Capability cap, unsigned index)
{
invoke_12 (caps, cap, CAP_CAPS_SET, index);
}
#if 0
/* 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)
#else
#define kdebug_char(c) do {} while (0)
#endif
#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