mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-02-06 12:11:06 +02:00
more
This commit is contained in:
parent
35fb72c239
commit
305bc03711
@ -157,14 +157,14 @@ Thread *Memory::alloc_thread ():
|
|||||||
ret->receivers = NULL
|
ret->receivers = NULL
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Message *Memory::alloc_message (Capability *source):
|
Message *Memory::alloc_message (Receiver *target, unsigned protected_data):
|
||||||
Message *ret = (Message *)search_free (sizeof (Message), (void **)&source->target->messages)
|
Message *ret = (Message *)search_free (sizeof (Message), (void **)&target->messages)
|
||||||
if !ret:
|
if !ret:
|
||||||
return NULL
|
return NULL
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
ret->capabilities[i] = NULL
|
ret->capabilities[i] = NULL
|
||||||
ret->data[i] = 0
|
ret->data[i] = 0
|
||||||
ret->protected_data = source->protected_data
|
ret->protected_data = protected_data
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Receiver *Memory::alloc_receiver ():
|
Receiver *Memory::alloc_receiver ():
|
||||||
|
@ -7,11 +7,11 @@ __start:
|
|||||||
lw $gp, 0($ra)
|
lw $gp, 0($ra)
|
||||||
la $v0, __my_receiver
|
la $v0, __my_receiver
|
||||||
sw $a0, ($v0)
|
sw $a0, ($v0)
|
||||||
la $v0, __top_memory
|
la $v0, __my_thread
|
||||||
sw $a1, ($v0)
|
sw $a1, ($v0)
|
||||||
la $v0, __my_memory
|
la $v0, __my_memory
|
||||||
sw $a2, ($v0)
|
sw $a2, ($v0)
|
||||||
la $v0, __my_admin
|
la $v0, __my_call
|
||||||
sw $a3, ($v0)
|
sw $a3, ($v0)
|
||||||
la $t9, main
|
la $t9, main
|
||||||
la $ra, 1f
|
la $ra, 1f
|
||||||
@ -23,7 +23,6 @@ __start:
|
|||||||
lw $a0, -4($zero)
|
lw $a0, -4($zero)
|
||||||
|
|
||||||
.comm __my_receiver, 4
|
.comm __my_receiver, 4
|
||||||
.comm __top_memory, 4
|
.comm __my_thread, 4
|
||||||
.comm __my_memory, 4
|
.comm __my_memory, 4
|
||||||
.comm __my_admin, 4
|
|
||||||
.comm __my_call, 4
|
.comm __my_call, 4
|
||||||
|
@ -8,29 +8,27 @@ extern "C" {
|
|||||||
#define KERNEL_MASK 0xfff
|
#define KERNEL_MASK 0xfff
|
||||||
#define CAPTYPE_MASK 0xe00
|
#define CAPTYPE_MASK 0xe00
|
||||||
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
||||||
#define CAPTYPE_ADMIN 0x000
|
#define CAPTYPE_RECEIVER 0x000
|
||||||
#define CAPTYPE_RECEIVER 0x200
|
#define CAPTYPE_MEMORY 0x200
|
||||||
#define CAPTYPE_MEMORY 0x400
|
#define CAPTYPE_THREAD 0x400
|
||||||
#define CAPTYPE_THREAD 0x600
|
#define CAPTYPE_PAGE 0x600
|
||||||
#define CAPTYPE_PAGE 0x800
|
#define CAPTYPE_CAPABILITY 0x800
|
||||||
#define CAPTYPE_CAPABILITY 0xa00
|
#define CAPTYPE_CAPPAGE 0xa00
|
||||||
#define CAPTYPE_CAPPAGE 0xc00
|
/*#define CAPTYPE_??? 0xc00*/
|
||||||
/*#define CAPTYPE_??? 0xe00*/
|
/*#define CAPTYPE_??? 0xe00*/
|
||||||
|
|
||||||
/* This works on all kernel capabilities. */
|
/* This works on all kernel capabilities. */
|
||||||
#define CAP_DEGRADE 0
|
#define CAP_DEGRADE 0
|
||||||
|
|
||||||
/* Operations */
|
/* Operations */
|
||||||
#define CAP_ADMIN_SCHEDULE 1
|
|
||||||
/* TODO: add priviledged operations. */
|
|
||||||
|
|
||||||
#define CAP_RECEIVER_SET_OWNER 1
|
#define CAP_RECEIVER_SET_OWNER 1
|
||||||
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
||||||
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
||||||
|
#define CAP_RECEIVER_ALL_RIGHTS 0x7f
|
||||||
/* Not an operation; a capability with this bit set is a call capability. */
|
/* Not an operation; a capability with this bit set is a call capability. */
|
||||||
#define CAP_RECEIVER_CALL 8
|
#define CAP_RECEIVER_CALL 7
|
||||||
/* Same thing for reply capability. */
|
/* Same thing for reply capability. */
|
||||||
#define CAP_RECEIVER_REPLY 9
|
#define CAP_RECEIVER_REPLY 8
|
||||||
|
|
||||||
#define CAP_MEMORY_CREATE 1
|
#define CAP_MEMORY_CREATE 1
|
||||||
#define CAP_MEMORY_DESTROY 2
|
#define CAP_MEMORY_DESTROY 2
|
||||||
@ -39,10 +37,20 @@ extern "C" {
|
|||||||
#define CAP_MEMORY_SET_LIMIT 5
|
#define CAP_MEMORY_SET_LIMIT 5
|
||||||
#define CAP_MEMORY_GET_LIMIT 6
|
#define CAP_MEMORY_GET_LIMIT 6
|
||||||
#define CAP_MEMORY_DROP 7
|
#define CAP_MEMORY_DROP 7
|
||||||
|
#define CAP_MEMORY_ALL_RIGHTS 0x1ff
|
||||||
|
|
||||||
#define CAP_THREAD_RUN 1
|
#define CAP_THREAD_GET_INFO 1 /* Details of this are arch-specific. */
|
||||||
#define CAP_THREAD_GET_INFO 2 /* Details of this are arch-specific. */
|
#define CAP_THREAD_SET_INFO 2 /* Details of this are arch-specific. */
|
||||||
#define CAP_THREAD_SET_INFO 3 /* Details of this are arch-specific. */
|
#define CAP_THREAD_SCHEDULE 3
|
||||||
|
#define CAP_THREAD_GET_TOP_MEMORY 7
|
||||||
|
#define CAP_THREAD_REGISTER_INTERRUPT 8
|
||||||
|
#define CAP_THREAD_ALL_RIGHTS 0xff
|
||||||
|
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY))
|
||||||
|
|
||||||
|
/* 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 */
|
/* Flag values for processor state */
|
||||||
#define THREAD_FLAG_WAITING 0x80000000
|
#define THREAD_FLAG_WAITING 0x80000000
|
||||||
#define THREAD_FLAG_RUNNING 0x40000000
|
#define THREAD_FLAG_RUNNING 0x40000000
|
||||||
@ -55,19 +63,22 @@ extern "C" {
|
|||||||
#define CAP_PAGE_FORGET 4
|
#define CAP_PAGE_FORGET 4
|
||||||
// Not an operation; a capability without this bit cannot write to the page. */
|
// Not an operation; a capability without this bit cannot write to the page. */
|
||||||
#define CAP_PAGE_WRITE 5
|
#define CAP_PAGE_WRITE 5
|
||||||
|
#define CAP_PAGE_ALL_RIGHTS 0x1ff
|
||||||
|
|
||||||
#define CAP_CAPABILITY_GET 1
|
#define CAP_CAPABILITY_GET 1
|
||||||
#define CAP_CAPABILITY_SET_DEATH_NOTIFY 2
|
#define CAP_CAPABILITY_SET_DEATH_NOTIFY 2
|
||||||
|
#define CAP_CAPABILITY_ALL_RIGHTS 0x1ff
|
||||||
|
|
||||||
#define CAPPAGE_SIZE 102
|
#define CAPPAGE_SIZE 102
|
||||||
/* Cappage has page's operations as well. */
|
/* Cappage has page's operations as well. */
|
||||||
#define CAP_CAPPAGE_SET 6
|
#define CAP_CAPPAGE_SET 6
|
||||||
|
#define CAP_CAPPAGE_ALL_RIGHTS 0x1ff
|
||||||
|
|
||||||
#ifndef __KERNEL
|
#ifndef __KERNEL
|
||||||
typedef unsigned __Capability;
|
typedef unsigned __Capability;
|
||||||
|
|
||||||
extern __Capability __my_receiver;
|
extern __Capability __my_receiver;
|
||||||
extern __Capability __my_admin;
|
extern __Capability __my_thread;
|
||||||
extern __Capability __my_memory;
|
extern __Capability __my_memory;
|
||||||
extern __Capability __my_call;
|
extern __Capability __my_call;
|
||||||
|
|
||||||
@ -139,6 +150,17 @@ static int __invoke_02 (__Capability t, unsigned d0, unsigned d1)
|
|||||||
return __invoke (t, &msg);
|
return __invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __invoke_04 (__Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||||
|
{
|
||||||
|
__Message msg;
|
||||||
|
int ret;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = d2;
|
||||||
|
msg.data[3] = d3;
|
||||||
|
return __invoke (t, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
static int __invoke_11 (__Capability t, __Capability c, unsigned d)
|
static int __invoke_11 (__Capability t, __Capability c, unsigned d)
|
||||||
{
|
{
|
||||||
__Message msg;
|
__Message msg;
|
||||||
@ -179,6 +201,17 @@ static __Capability __call_c02 (__Capability c, unsigned d0, unsigned d1)
|
|||||||
return ret ? msg.cap[0] : 0;
|
return ret ? msg.cap[0] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned __call_n02 (__Capability c, unsigned d0, unsigned d1)
|
||||||
|
{
|
||||||
|
__Message msg;
|
||||||
|
int ret;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
ret = __call (__my_call, &msg);
|
||||||
|
return ret ? msg.data[0] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static __Capability __degrade (__Capability src, unsigned mask)
|
static __Capability __degrade (__Capability src, unsigned mask)
|
||||||
{
|
{
|
||||||
return __call_c02 (src, CAP_DEGRADE, mask);
|
return __call_c02 (src, CAP_DEGRADE, mask);
|
||||||
@ -186,7 +219,22 @@ static __Capability __degrade (__Capability src, unsigned mask)
|
|||||||
|
|
||||||
static void __schedule ()
|
static void __schedule ()
|
||||||
{
|
{
|
||||||
__invoke_01 (__my_admin, CAP_ADMIN_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 __Capability __get_top_memory ()
|
||||||
|
{
|
||||||
|
return __call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __unregister_interrupt (unsigned num)
|
||||||
|
{
|
||||||
|
__invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __receiver_set_owner (__Capability receiver, __Capability owner)
|
static int __receiver_set_owner (__Capability receiver, __Capability owner)
|
||||||
@ -251,17 +299,57 @@ static void __drop (__Capability cap)
|
|||||||
__invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
__invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __thread_run (__Capability thread, int run)
|
static int __thread_set_info (__Capability thread, unsigned info, unsigned value, unsigned mask)
|
||||||
{
|
{
|
||||||
return __invoke_02 (thread, CAP_THREAD_RUN, run);
|
return __invoke_04 (thread, CAP_THREAD_SET_INFO, info, value, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:
|
static int __thread_set_pc (__Capability thread, unsigned pc)
|
||||||
#define CAP_THREAD_GET_INFO 4
|
{
|
||||||
#define CAP_THREAD_SET_INFO 5
|
return __thread_set_info (thread, CAP_THREAD_INFO_PC, pc, ~0);
|
||||||
*/
|
}
|
||||||
|
|
||||||
/* TODO: all except map should also work for cappages.
|
static int __thread_set_sp (__Capability thread, unsigned sp)
|
||||||
|
{
|
||||||
|
return __thread_set_info (thread, CAP_THREAD_INFO_SP, sp, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __thread_set_flags (__Capability thread, unsigned value, unsigned mask)
|
||||||
|
{
|
||||||
|
return __thread_set_info (thread, CAP_THREAD_INFO_FLAGS, value, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __thread_run (__Capability thread, int run)
|
||||||
|
{
|
||||||
|
return __thread_set_flags (thread, run ? THREAD_FLAG_RUNNING : 0, THREAD_FLAG_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __thread_wait (__Capability thread, int wait)
|
||||||
|
{
|
||||||
|
return __thread_set_flags (thread, wait ? THREAD_FLAG_WAITING : 0, THREAD_FLAG_WAITING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __thread_get_info (__Capability thread, unsigned info)
|
||||||
|
{
|
||||||
|
return __call_n02 (thread, CAP_THREAD_GET_INFO, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __thread_get_pc (__Capability thread)
|
||||||
|
{
|
||||||
|
return __thread_get_info (thread, CAP_THREAD_INFO_PC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __thread_get_sp (__Capability thread)
|
||||||
|
{
|
||||||
|
return __thread_get_info (thread, CAP_THREAD_INFO_SP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __thread_get_flags (__Capability thread)
|
||||||
|
{
|
||||||
|
return __thread_get_info (thread, CAP_THREAD_INFO_FLAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO. All except map should also work for cappages.
|
||||||
#define CAP_PAGE_MAP 1
|
#define CAP_PAGE_MAP 1
|
||||||
#define CAP_PAGE_SHARE 2
|
#define CAP_PAGE_SHARE 2
|
||||||
#define CAP_PAGE_SHARE_COW 3
|
#define CAP_PAGE_SHARE_COW 3
|
||||||
|
17
init.ccp
17
init.ccp
@ -13,6 +13,7 @@ static void init_idle ():
|
|||||||
idle.schedule_next = NULL
|
idle.schedule_next = NULL
|
||||||
idle.address_space = &idle_memory
|
idle.address_space = &idle_memory
|
||||||
idle.refs = NULL
|
idle.refs = NULL
|
||||||
|
idle.flags = THREAD_FLAG_RUNNING | THREAD_FLAG_PRIV
|
||||||
// initialize idle_memory.
|
// initialize idle_memory.
|
||||||
idle_memory.prev = NULL
|
idle_memory.prev = NULL
|
||||||
idle_memory.next = NULL
|
idle_memory.next = NULL
|
||||||
@ -84,6 +85,10 @@ static void init_cp0 ():
|
|||||||
// Wait with initializing the status register until the last moment, so that
|
// Wait with initializing the status register until the last moment, so that
|
||||||
// exceptions in the bootup code will fill EPC and friends.
|
// exceptions in the bootup code will fill EPC and friends.
|
||||||
|
|
||||||
|
// This returns unsigned, because the value is used to fill thread->arch.a*.
|
||||||
|
static unsigned mkcap (Memory *mem, unsigned type, void *obj):
|
||||||
|
return (unsigned)mem->alloc_capability ((Receiver *)type, NULL, &mem->capabilities, (unsigned)obj)
|
||||||
|
|
||||||
static void init_threads ():
|
static void init_threads ():
|
||||||
Thread *previous = NULL
|
Thread *previous = NULL
|
||||||
first_scheduled = NULL
|
first_scheduled = NULL
|
||||||
@ -151,13 +156,13 @@ static void init_threads ():
|
|||||||
stackpage->physical = mem->zalloc ()
|
stackpage->physical = mem->zalloc ()
|
||||||
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
||||||
panic (0x13151719, "unable to map initial stack page")
|
panic (0x13151719, "unable to map initial stack page")
|
||||||
thread->arch.a0 = (unsigned)mem->alloc_receiver ()
|
Receiver *recv = mem->alloc_receiver ()
|
||||||
thread->arch.a1 = (unsigned)&top_memory
|
thread->arch.a0 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_ALL_RIGHTS, recv)
|
||||||
thread->arch.a2 = (unsigned)mem
|
thread->arch.a1 = mkcap (mem, CAPTYPE_THREAD | CAP_THREAD_ALL_PRIV_RIGHTS, thread)
|
||||||
Capability *admin = mem->alloc_capability ((Receiver *)(CAPTYPE_ADMIN | ~PAGE_MASK), NULL, &mem->capabilities, ~0)
|
thread->arch.a2 = mkcap (mem, CAPTYPE_MEMORY | CAP_MEMORY_ALL_RIGHTS, mem)
|
||||||
thread->arch.a3 = (unsigned)admin
|
thread->arch.a3 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_CALL, recv)
|
||||||
mem->pfree ((unsigned)pages)
|
mem->pfree ((unsigned)pages)
|
||||||
thread->flags = THREAD_FLAG_RUNNING
|
thread->flags = THREAD_FLAG_RUNNING | THREAD_FLAG_PRIV
|
||||||
thread->schedule_next = NULL
|
thread->schedule_next = NULL
|
||||||
thread->schedule_prev = previous
|
thread->schedule_prev = previous
|
||||||
if previous:
|
if previous:
|
||||||
|
@ -24,17 +24,19 @@ Thread *tlb_refill ():
|
|||||||
/// An interrupt which is not an exception has occurred.
|
/// An interrupt which is not an exception has occurred.
|
||||||
Thread *interrupt ():
|
Thread *interrupt ():
|
||||||
panic (0x88877722, "Interrupt")
|
panic (0x88877722, "Interrupt")
|
||||||
unsigned cause
|
unsigned cause, status
|
||||||
cp0_get (CP0_CAUSE, cause)
|
cp0_get (CP0_CAUSE, cause)
|
||||||
|
cp0_get (CP0_STATUS, status)
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
if cause & (1 << (i + 8)):
|
if cause & (1 << (i + 8)):
|
||||||
// TODO: Handle interrupt.
|
// Disable the interrupt while handling it.
|
||||||
// Disable all interrupts which are not handled.
|
status &= ~(1 << (i + 8))
|
||||||
unsigned status
|
// Send message to interrupt handler.
|
||||||
cp0_get (CP0_STATUS, status)
|
if arch_interrupt_receiver[i]:
|
||||||
cp0_get (CP0_CAUSE, cause)
|
unsigned data[4] = {0, 0, 0, 0}
|
||||||
status &= ~(cause & 0x0000ff00)
|
Capability *cap[4] = {NULL, NULL, NULL, NULL}
|
||||||
cp0_set (CP0_STATUS, status)
|
bool copy[4] = {false, false, false, false}
|
||||||
|
arch_interrupt_receiver[i]->send_message (i, data, cap, copy)
|
||||||
return current
|
return current
|
||||||
|
|
||||||
/// A general exception has occurred.
|
/// A general exception has occurred.
|
||||||
|
190
invoke.ccp
190
invoke.ccp
@ -22,22 +22,26 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
|||||||
static Capability *reply
|
static Capability *reply
|
||||||
static Receiver *reply_receiver
|
static Receiver *reply_receiver
|
||||||
|
|
||||||
static void reply_cap (unsigned target, unsigned protected_data):
|
static void fill_cap (Capability *r, unsigned target, unsigned protected_data):
|
||||||
Capability r
|
|
||||||
Capability **ref
|
Capability **ref
|
||||||
if target & ~KERNEL_MASK:
|
if target & ~KERNEL_MASK:
|
||||||
ref = &((Receiver *)target)->capabilities
|
ref = &((Receiver *)target)->capabilities
|
||||||
else:
|
else:
|
||||||
ref = &((Object_base *)protected_data)->refs
|
ref = &((Object_base *)protected_data)->refs
|
||||||
// alloc_capability needs a Memory, but it isn't used if return storage is given.
|
// alloc_capability needs a Memory, but it isn't used if return storage is given.
|
||||||
top_memory.alloc_capability ((Receiver *)target, NULL, ref, protected_data, &r)
|
top_memory.alloc_capability ((Receiver *)target, NULL, ref, protected_data, r)
|
||||||
|
|
||||||
|
static void reply_cap (unsigned target, unsigned protected_data):
|
||||||
|
Capability r
|
||||||
|
fill_cap (&r, target, protected_data)
|
||||||
unsigned d[4] = { 0, 0, 0, 0 }
|
unsigned d[4] = { 0, 0, 0, 0 }
|
||||||
Capability *caps[4] = { &r, NULL, NULL, NULL }
|
Capability *caps[4] = { &r, NULL, NULL, NULL }
|
||||||
bool cops[4] = { true, false, false, false }
|
bool cops[4] = { true, false, false, false }
|
||||||
if reply:
|
if reply:
|
||||||
reply->invoke (d, caps, cops)
|
reply->invoke (d, caps, cops)
|
||||||
else:
|
else:
|
||||||
// TODO: send message to reply_receiver
|
reply_receiver->send_message (~0, d, caps, cops)
|
||||||
|
r.invalidate ()
|
||||||
|
|
||||||
static void reply_cap (Capability *cap, bool copy):
|
static void reply_cap (Capability *cap, bool copy):
|
||||||
unsigned d[4] = { 0, 0, 0, 0 }
|
unsigned d[4] = { 0, 0, 0, 0 }
|
||||||
@ -46,7 +50,7 @@ static void reply_cap (Capability *cap, bool copy):
|
|||||||
if reply:
|
if reply:
|
||||||
reply->invoke (d, caps, cops)
|
reply->invoke (d, caps, cops)
|
||||||
else:
|
else:
|
||||||
// TODO: send message to reply_receiver
|
reply_receiver->send_message (~0, d, caps, cops)
|
||||||
|
|
||||||
static void reply_num (unsigned num):
|
static void reply_num (unsigned num):
|
||||||
unsigned d[4] = { num, 0, 0, 0 }
|
unsigned d[4] = { num, 0, 0, 0 }
|
||||||
@ -55,15 +59,7 @@ static void reply_num (unsigned num):
|
|||||||
if reply:
|
if reply:
|
||||||
reply->invoke (d, caps, cops)
|
reply->invoke (d, caps, cops)
|
||||||
else:
|
else:
|
||||||
// TODO: send message to reply_receiver
|
reply_receiver->send_message (~0, d, caps, cops)
|
||||||
|
|
||||||
static void admin_invoke (unsigned target, Capability *cap, unsigned request, unsigned data):
|
|
||||||
switch request:
|
|
||||||
case CAP_ADMIN_SCHEDULE:
|
|
||||||
schedule ()
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
|
|
||||||
static void receiver_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned data):
|
static void receiver_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned data):
|
||||||
Receiver *receiver = (Receiver *)protected_data
|
Receiver *receiver = (Receiver *)protected_data
|
||||||
@ -130,9 +126,6 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
|
|||||||
if !cap || cap->address_space != mem || (unsigned)cap->target & ~KERNEL_MASK:
|
if !cap || cap->address_space != mem || (unsigned)cap->target & ~KERNEL_MASK:
|
||||||
return
|
return
|
||||||
switch (unsigned)cap->target & CAPTYPE_MASK:
|
switch (unsigned)cap->target & CAPTYPE_MASK:
|
||||||
case CAPTYPE_ADMIN:
|
|
||||||
// Admin capabilities don't take space, so they cannot be destroyed.
|
|
||||||
return
|
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
mem->free_receiver ((Receiver *)cap->protected_data)
|
mem->free_receiver ((Receiver *)cap->protected_data)
|
||||||
return
|
return
|
||||||
@ -179,19 +172,64 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
||||||
static void thread_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned data):
|
static void thread_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned data[4]):
|
||||||
Thread *thread = (Thread *)protected_data
|
Thread *thread = (Thread *)protected_data
|
||||||
switch request:
|
switch data[0]:
|
||||||
case CAP_THREAD_RUN:
|
|
||||||
if data:
|
|
||||||
thread->run ()
|
|
||||||
else:
|
|
||||||
thread->unrun ()
|
|
||||||
break
|
|
||||||
case CAP_THREAD_GET_INFO:
|
case CAP_THREAD_GET_INFO:
|
||||||
// TODO
|
switch data[1]:
|
||||||
|
case CAP_THREAD_INFO_PC:
|
||||||
|
reply_num (thread->pc)
|
||||||
|
break
|
||||||
|
case CAP_THREAD_INFO_SP:
|
||||||
|
reply_num (thread->sp)
|
||||||
|
break
|
||||||
|
case CAP_THREAD_INFO_FLAGS:
|
||||||
|
reply_num (thread->flags)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
unsigned *n = Thread_arch_info (thread, data[1])
|
||||||
|
if n:
|
||||||
|
reply_num (*n)
|
||||||
|
break
|
||||||
|
break
|
||||||
case CAP_THREAD_SET_INFO:
|
case CAP_THREAD_SET_INFO:
|
||||||
// TODO
|
unsigned *value
|
||||||
|
switch data[1]:
|
||||||
|
case CAP_THREAD_INFO_PC:
|
||||||
|
value = &thread->pc
|
||||||
|
break
|
||||||
|
case CAP_THREAD_INFO_SP:
|
||||||
|
value = &thread->sp
|
||||||
|
break
|
||||||
|
case CAP_THREAD_INFO_FLAGS:
|
||||||
|
data[3] &= ~THREAD_FLAG_PRIV
|
||||||
|
value = &thread->flags
|
||||||
|
if data[3] & ~THREAD_FLAG_USER:
|
||||||
|
unsigned v = (*value & data[3]) | (data[2] & data[3])
|
||||||
|
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
|
||||||
|
if v & THREAD_FLAG_WAITING:
|
||||||
|
thread->wait ()
|
||||||
|
else
|
||||||
|
thread->unwait ()
|
||||||
|
if (v & THREAD_FLAG_RUNNING) != (*value & THREAD_FLAG_RUNNING):
|
||||||
|
if v & THREAD_FLAG_RUNNING:
|
||||||
|
thread->run ()
|
||||||
|
else
|
||||||
|
thread->unrun ()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
value = Thread_arch_info (thread, data[1])
|
||||||
|
break
|
||||||
|
if value:
|
||||||
|
*value &= ~data[3]
|
||||||
|
*value |= data[2] & data[3]
|
||||||
|
break
|
||||||
|
case CAP_THREAD_SCHEDULE:
|
||||||
|
schedule ()
|
||||||
|
break
|
||||||
|
case CAP_THREAD_REGISTER_INTERRUPT:
|
||||||
|
arch_register_interrupt (data[1], (Receiver *)cap->protected_data)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -246,24 +284,27 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
|||||||
reply_cap (target & d[1], protected_data)
|
reply_cap (target & d[1], protected_data)
|
||||||
return true
|
return true
|
||||||
switch target & CAPTYPE_MASK:
|
switch target & CAPTYPE_MASK:
|
||||||
case CAPTYPE_ADMIN:
|
|
||||||
admin_invoke (target, c[1], d[0], d[1])
|
|
||||||
break
|
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
if target & (1 << CAP_RECEIVER_CALL):
|
if target & (1 << CAP_RECEIVER_CALL):
|
||||||
// This is a call capability.
|
// This is a call capability.
|
||||||
protected_data = c[0]->protected_data
|
Capability r
|
||||||
target = (unsigned)c[0]->target
|
Receiver *t = c[0]->target
|
||||||
if ~(unsigned)c[0]->target & ~KERNEL_MASK:
|
unsigned p_d = c[0]->protected_data
|
||||||
// TODO: create reply capability.
|
if ~(unsigned)t & ~KERNEL_MASK:
|
||||||
|
fill_cap (&r, protected_data, ~0)
|
||||||
|
c[0] = &r
|
||||||
|
copy[0] = true
|
||||||
|
bool ret = kernel_invoke ((unsigned)t, p_d, d, c, copy)
|
||||||
|
r.invalidate ()
|
||||||
|
return ret
|
||||||
else:
|
else:
|
||||||
// Kernel call: don't create actual capablities.
|
// Kernel call: don't create actual capablities.
|
||||||
reply = NULL
|
reply = NULL
|
||||||
reply_receiver = (Receiver *)protected_data
|
reply_receiver = (Receiver *)protected_data
|
||||||
return kernel_invoke (target, protected_data, d, c, copy)
|
return kernel_invoke ((unsigned)t, p_d, d, c, copy)
|
||||||
if target & (1 << CAP_RECEIVER_REPLY):
|
if target & (1 << CAP_RECEIVER_REPLY):
|
||||||
// This is a reply capability.
|
// This is a reply capability.
|
||||||
// TODO
|
((Receiver *)protected_data)->send_message (~0, d, c, copy)
|
||||||
return true
|
return true
|
||||||
receiver_invoke (target, protected_data, c[1], d[0], d[1])
|
receiver_invoke (target, protected_data, c[1], d[0], d[1])
|
||||||
break
|
break
|
||||||
@ -271,7 +312,7 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
|||||||
memory_invoke (target, protected_data, c[1], d[0], d[1])
|
memory_invoke (target, protected_data, c[1], d[0], d[1])
|
||||||
break
|
break
|
||||||
case CAPTYPE_THREAD:
|
case CAPTYPE_THREAD:
|
||||||
thread_invoke (target, protected_data, c[1], d[0], d[1])
|
thread_invoke (target, protected_data, c[1], d)
|
||||||
break
|
break
|
||||||
case CAPTYPE_PAGE:
|
case CAPTYPE_PAGE:
|
||||||
page_invoke (target, protected_data, c[1], d[0], d[1])
|
page_invoke (target, protected_data, c[1], d[0], d[1])
|
||||||
@ -286,44 +327,47 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
|
|||||||
panic (0x99337744, "invalid capability type invoked")
|
panic (0x99337744, "invalid capability type invoked")
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
bool Receiver::send_message (unsigned protected_data, unsigned data[4], Capability *cap[4], bool copy[4]):
|
||||||
|
bool tried_direct = false
|
||||||
|
if owner && owner->is_waiting ():
|
||||||
|
Capability *c[4]
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
if !cap[i]:
|
||||||
|
c[i] = NULL
|
||||||
|
else:
|
||||||
|
c[i] = owner->address_space->clone_capability (cap[i], copy[i])
|
||||||
|
if !c[i]:
|
||||||
|
for unsigned j = 0; j < i; ++j:
|
||||||
|
owner->address_space->free_capability (c[i])
|
||||||
|
tried_direct = true
|
||||||
|
break
|
||||||
|
if !tried_direct:
|
||||||
|
Thread_arch_receive (owner, data, c)
|
||||||
|
owner->unwait ()
|
||||||
|
return true
|
||||||
|
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||||
|
Message *msg = address_space->alloc_message (this, protected_data)
|
||||||
|
if !msg:
|
||||||
|
return false
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
msg->data[i] = data[i]
|
||||||
|
if !cap[i]:
|
||||||
|
msg->capabilities[i] = NULL
|
||||||
|
else:
|
||||||
|
msg->capabilities[i] = address_space->clone_capability (cap[i], copy[i])
|
||||||
|
if !msg->capabilities[i]:
|
||||||
|
for unsigned j = 0; j < i; ++j:
|
||||||
|
address_space->free_capability (msg->capabilities[j])
|
||||||
|
address_space->free_message (msg)
|
||||||
|
return false
|
||||||
|
if tried_direct:
|
||||||
|
Thread_arch_receive_fail (owner)
|
||||||
|
owner->unwait ()
|
||||||
|
return true
|
||||||
|
|
||||||
bool Capability::invoke (unsigned data[4], Capability *cap[4], bool copy[4]):
|
bool Capability::invoke (unsigned data[4], Capability *cap[4], bool copy[4]):
|
||||||
if (unsigned)target & ~KERNEL_MASK:
|
if (unsigned)target & ~KERNEL_MASK:
|
||||||
// This is not a kernel capability: send a message to the receiver.
|
// This is not a kernel capability: send a message to the receiver.
|
||||||
bool tried_direct = false
|
return target->send_message (protected_data, data, cap, copy)
|
||||||
if target->owner && target->owner->is_waiting ():
|
|
||||||
Capability *c[4]
|
|
||||||
for unsigned i = 0; i < 4; ++i:
|
|
||||||
if !cap[i]:
|
|
||||||
c[i] = NULL
|
|
||||||
else:
|
|
||||||
c[i] = target->owner->address_space->clone_capability (cap[i], copy[i])
|
|
||||||
if !c[i]:
|
|
||||||
for unsigned j = 0; j < i; ++j:
|
|
||||||
target->owner->address_space->free_capability (c[i])
|
|
||||||
tried_direct = true
|
|
||||||
break
|
|
||||||
if !tried_direct:
|
|
||||||
Thread_arch_receive (target->owner, data, c)
|
|
||||||
target->owner->unwait ()
|
|
||||||
return true
|
|
||||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
|
||||||
Message *msg = target->address_space->alloc_message (this)
|
|
||||||
if !msg:
|
|
||||||
return false
|
|
||||||
for unsigned i = 0; i < 4; ++i:
|
|
||||||
msg->data[i] = data[i]
|
|
||||||
if !cap[i]:
|
|
||||||
msg->capabilities[i] = NULL
|
|
||||||
else:
|
|
||||||
msg->capabilities[i] = target->address_space->clone_capability (cap[i], copy[i])
|
|
||||||
if !msg->capabilities[i]:
|
|
||||||
for unsigned j = 0; j < i; ++j:
|
|
||||||
target->address_space->free_capability (msg->capabilities[j])
|
|
||||||
target->address_space->free_message (msg)
|
|
||||||
return false
|
|
||||||
if tried_direct:
|
|
||||||
Thread_arch_receive_fail (target->owner)
|
|
||||||
target->owner->unwait ()
|
|
||||||
return true
|
|
||||||
// This is a kernel capability. Use a function to allow optimized call capabilities.
|
// This is a kernel capability. Use a function to allow optimized call capabilities.
|
||||||
return kernel_invoke ((unsigned)target, protected_data, data, cap, copy)
|
return kernel_invoke ((unsigned)target, protected_data, data, cap, copy)
|
||||||
|
@ -69,6 +69,7 @@ struct Receiver : public Object <Receiver>:
|
|||||||
Message *messages
|
Message *messages
|
||||||
void own (Thread *o)
|
void own (Thread *o)
|
||||||
void orphan ()
|
void orphan ()
|
||||||
|
bool send_message (unsigned protected_data, unsigned data[4], Capability *cap[4], bool copy[4])
|
||||||
|
|
||||||
struct Capability : public Object <Capability>:
|
struct Capability : public Object <Capability>:
|
||||||
Receiver *target
|
Receiver *target
|
||||||
@ -109,7 +110,7 @@ struct Memory : public Object <Memory>:
|
|||||||
void *search_free (unsigned size, void **first)
|
void *search_free (unsigned size, void **first)
|
||||||
Page *alloc_page ()
|
Page *alloc_page ()
|
||||||
Thread *alloc_thread ()
|
Thread *alloc_thread ()
|
||||||
Message *alloc_message (Capability *source)
|
Message *alloc_message (Receiver *target, unsigned protected_data)
|
||||||
Receiver *alloc_receiver ()
|
Receiver *alloc_receiver ()
|
||||||
Capability *alloc_capability (Receiver *target, Capability *parent, Capability **parent_ptr, unsigned protected_data, Capability *ret = NULL)
|
Capability *alloc_capability (Receiver *target, Capability *parent, Capability **parent_ptr, unsigned protected_data, Capability *ret = NULL)
|
||||||
Capability *clone_capability (Capability *source, bool copy, Capability *ret = NULL)
|
Capability *clone_capability (Capability *source, bool copy, Capability *ret = NULL)
|
||||||
@ -155,12 +156,14 @@ EXTERN Thread *current
|
|||||||
void Thread_arch_init (Thread *thread)
|
void Thread_arch_init (Thread *thread)
|
||||||
void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4])
|
void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4])
|
||||||
void Thread_arch_receive_fail (Thread *thread)
|
void Thread_arch_receive_fail (Thread *thread)
|
||||||
|
unsigned *Thread_arch_info (Thread *thread, unsigned num)
|
||||||
void Memory_arch_init (Memory *mem)
|
void Memory_arch_init (Memory *mem)
|
||||||
void Memory_arch_free (Memory *mem)
|
void Memory_arch_free (Memory *mem)
|
||||||
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write)
|
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write)
|
||||||
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
|
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
|
||||||
Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable)
|
Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable)
|
||||||
void arch_invoke ()
|
void arch_invoke ()
|
||||||
|
void arch_register_interrupt (unsigned num, Receiver *r)
|
||||||
|
|
||||||
bool Memory::map (Page *page, unsigned address, bool write):
|
bool Memory::map (Page *page, unsigned address, bool write):
|
||||||
return Memory_arch_map (this, page, address, write)
|
return Memory_arch_map (this, page, address, write)
|
||||||
|
78
mips.ccp
78
mips.ccp
@ -42,6 +42,73 @@ void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4]):
|
|||||||
void Thread_arch_receive_fail (Thread *thread):
|
void Thread_arch_receive_fail (Thread *thread):
|
||||||
thread->arch.v0 = 0
|
thread->arch.v0 = 0
|
||||||
|
|
||||||
|
unsigned *Thread_arch_info (Thread *thread, unsigned num):
|
||||||
|
switch num:
|
||||||
|
case 1:
|
||||||
|
return &thread->arch.at
|
||||||
|
case 2:
|
||||||
|
return &thread->arch.v0
|
||||||
|
case 3:
|
||||||
|
return &thread->arch.v1
|
||||||
|
case 4:
|
||||||
|
return &thread->arch.a0
|
||||||
|
case 5:
|
||||||
|
return &thread->arch.a1
|
||||||
|
case 6:
|
||||||
|
return &thread->arch.a2
|
||||||
|
case 7:
|
||||||
|
return &thread->arch.a3
|
||||||
|
case 8:
|
||||||
|
return &thread->arch.t0
|
||||||
|
case 9:
|
||||||
|
return &thread->arch.t1
|
||||||
|
case 10:
|
||||||
|
return &thread->arch.t2
|
||||||
|
case 11:
|
||||||
|
return &thread->arch.t3
|
||||||
|
case 12:
|
||||||
|
return &thread->arch.t4
|
||||||
|
case 13:
|
||||||
|
return &thread->arch.t5
|
||||||
|
case 14:
|
||||||
|
return &thread->arch.t6
|
||||||
|
case 15:
|
||||||
|
return &thread->arch.t7
|
||||||
|
case 16:
|
||||||
|
return &thread->arch.s0
|
||||||
|
case 17:
|
||||||
|
return &thread->arch.s1
|
||||||
|
case 18:
|
||||||
|
return &thread->arch.s2
|
||||||
|
case 19:
|
||||||
|
return &thread->arch.s3
|
||||||
|
case 20:
|
||||||
|
return &thread->arch.s4
|
||||||
|
case 21:
|
||||||
|
return &thread->arch.s5
|
||||||
|
case 22:
|
||||||
|
return &thread->arch.s6
|
||||||
|
case 23:
|
||||||
|
return &thread->arch.s7
|
||||||
|
case 24:
|
||||||
|
return &thread->arch.t8
|
||||||
|
case 25:
|
||||||
|
return &thread->arch.t9
|
||||||
|
case 26:
|
||||||
|
return &thread->arch.k0
|
||||||
|
case 27:
|
||||||
|
return &thread->arch.k1
|
||||||
|
case 28:
|
||||||
|
return &thread->arch.gp
|
||||||
|
case 29:
|
||||||
|
return &thread->sp
|
||||||
|
case 30:
|
||||||
|
return &thread->arch.fp
|
||||||
|
case 31:
|
||||||
|
return &thread->arch.ra
|
||||||
|
default:
|
||||||
|
return NULL
|
||||||
|
|
||||||
void Memory_arch_init (Memory *mem):
|
void Memory_arch_init (Memory *mem):
|
||||||
mem->arch.asid = 1
|
mem->arch.asid = 1
|
||||||
mem->arch.directory = NULL
|
mem->arch.directory = NULL
|
||||||
@ -195,8 +262,6 @@ void arch_invoke ():
|
|||||||
bool wait, copy[4]
|
bool wait, copy[4]
|
||||||
Thread *caller = current
|
Thread *caller = current
|
||||||
target = caller->address_space->find_capability (current->arch.v0, &wait)
|
target = caller->address_space->find_capability (current->arch.v0, &wait)
|
||||||
if wait:
|
|
||||||
caller->wait ()
|
|
||||||
if !target:
|
if !target:
|
||||||
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
||||||
dbg_led (caller->arch.a0, caller->arch.a1, caller->arch.a2)
|
dbg_led (caller->arch.a0, caller->arch.a1, caller->arch.a2)
|
||||||
@ -205,6 +270,8 @@ void arch_invoke ():
|
|||||||
// Calling an invalid capability always fails.
|
// Calling an invalid capability always fails.
|
||||||
caller->arch.v0 = 0
|
caller->arch.v0 = 0
|
||||||
else:
|
else:
|
||||||
|
if wait:
|
||||||
|
caller->wait ()
|
||||||
c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0])
|
c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0])
|
||||||
c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1])
|
c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1])
|
||||||
c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2])
|
c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2])
|
||||||
@ -237,3 +304,10 @@ void arch_invoke ():
|
|||||||
if current->flags & THREAD_FLAG_PRIV:
|
if current->flags & THREAD_FLAG_PRIV:
|
||||||
status |= 0x10000000
|
status |= 0x10000000
|
||||||
cp0_set (CP0_STATUS, status | 0x13)
|
cp0_set (CP0_STATUS, status | 0x13)
|
||||||
|
|
||||||
|
void arch_register_interrupt (unsigned num, Receiver *r):
|
||||||
|
arch_interrupt_receiver[num] = r
|
||||||
|
// And enable the interrupt.
|
||||||
|
unsigned status
|
||||||
|
cp0_get (CP0_STATUS, status)
|
||||||
|
cp0_set (CP0_STATUS, status | (1 << (num + 8)))
|
||||||
|
1
mips.hhp
1
mips.hhp
@ -120,6 +120,7 @@ struct Memory_arch:
|
|||||||
// Pointers to Memory when asid is taken, index of next free, or 0, if free.
|
// Pointers to Memory when asid is taken, index of next free, or 0, if free.
|
||||||
// asid[0] is used as index to first free asid.
|
// asid[0] is used as index to first free asid.
|
||||||
EXTERN unsigned asids[64]
|
EXTERN unsigned asids[64]
|
||||||
|
EXTERN Receiver *arch_interrupt_receiver[8]
|
||||||
|
|
||||||
// Functions which can be called from assembly must not be mangled.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user