1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 01:29:31 +03:00
This commit is contained in:
Bas Wijnen 2009-05-27 18:33:05 +02:00
parent 35fb72c239
commit 305bc03711
9 changed files with 337 additions and 121 deletions

View File

@ -157,14 +157,14 @@ Thread *Memory::alloc_thread ():
ret->receivers = NULL
return ret
Message *Memory::alloc_message (Capability *source):
Message *ret = (Message *)search_free (sizeof (Message), (void **)&source->target->messages)
Message *Memory::alloc_message (Receiver *target, unsigned protected_data):
Message *ret = (Message *)search_free (sizeof (Message), (void **)&target->messages)
if !ret:
return NULL
for unsigned i = 0; i < 4; ++i:
ret->capabilities[i] = NULL
ret->data[i] = 0
ret->protected_data = source->protected_data
ret->protected_data = protected_data
return ret
Receiver *Memory::alloc_receiver ():

View File

@ -7,11 +7,11 @@ __start:
lw $gp, 0($ra)
la $v0, __my_receiver
sw $a0, ($v0)
la $v0, __top_memory
la $v0, __my_thread
sw $a1, ($v0)
la $v0, __my_memory
sw $a2, ($v0)
la $v0, __my_admin
la $v0, __my_call
sw $a3, ($v0)
la $t9, main
la $ra, 1f
@ -23,7 +23,6 @@ __start:
lw $a0, -4($zero)
.comm __my_receiver, 4
.comm __top_memory, 4
.comm __my_thread, 4
.comm __my_memory, 4
.comm __my_admin, 4
.comm __my_call, 4

View File

@ -8,29 +8,27 @@ extern "C" {
#define KERNEL_MASK 0xfff
#define CAPTYPE_MASK 0xe00
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
#define CAPTYPE_ADMIN 0x000
#define CAPTYPE_RECEIVER 0x200
#define CAPTYPE_MEMORY 0x400
#define CAPTYPE_THREAD 0x600
#define CAPTYPE_PAGE 0x800
#define CAPTYPE_CAPABILITY 0xa00
#define CAPTYPE_CAPPAGE 0xc00
#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_ADMIN_SCHEDULE 1
/* TODO: add priviledged operations. */
#define CAP_RECEIVER_SET_OWNER 1
#define CAP_RECEIVER_CREATE_CAPABILITY 2
#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. */
#define CAP_RECEIVER_CALL 8
#define CAP_RECEIVER_CALL 7
/* Same thing for reply capability. */
#define CAP_RECEIVER_REPLY 9
#define CAP_RECEIVER_REPLY 8
#define CAP_MEMORY_CREATE 1
#define CAP_MEMORY_DESTROY 2
@ -39,10 +37,20 @@ extern "C" {
#define CAP_MEMORY_SET_LIMIT 5
#define CAP_MEMORY_GET_LIMIT 6
#define CAP_MEMORY_DROP 7
#define CAP_MEMORY_ALL_RIGHTS 0x1ff
#define CAP_THREAD_RUN 1
#define CAP_THREAD_GET_INFO 2 /* Details of this are arch-specific. */
#define CAP_THREAD_SET_INFO 3 /* Details of this are arch-specific. */
#define CAP_THREAD_GET_INFO 1 /* Details of this are arch-specific. */
#define CAP_THREAD_SET_INFO 2 /* 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 */
#define THREAD_FLAG_WAITING 0x80000000
#define THREAD_FLAG_RUNNING 0x40000000
@ -55,19 +63,22 @@ extern "C" {
#define CAP_PAGE_FORGET 4
// Not an operation; a capability without this bit cannot write to the page. */
#define CAP_PAGE_WRITE 5
#define CAP_PAGE_ALL_RIGHTS 0x1ff
#define CAP_CAPABILITY_GET 1
#define CAP_CAPABILITY_SET_DEATH_NOTIFY 2
#define CAP_CAPABILITY_ALL_RIGHTS 0x1ff
#define CAPPAGE_SIZE 102
/* Cappage has page's operations as well. */
#define CAP_CAPPAGE_SET 6
#define CAP_CAPPAGE_ALL_RIGHTS 0x1ff
#ifndef __KERNEL
typedef unsigned __Capability;
extern __Capability __my_receiver;
extern __Capability __my_admin;
extern __Capability __my_thread;
extern __Capability __my_memory;
extern __Capability __my_call;
@ -139,6 +150,17 @@ static int __invoke_02 (__Capability t, unsigned d0, unsigned d1)
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)
{
__Message msg;
@ -179,6 +201,17 @@ static __Capability __call_c02 (__Capability c, unsigned d0, unsigned d1)
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)
{
return __call_c02 (src, CAP_DEGRADE, mask);
@ -186,7 +219,22 @@ static __Capability __degrade (__Capability src, unsigned mask)
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)
@ -251,17 +299,57 @@ static void __drop (__Capability cap)
__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:
#define CAP_THREAD_GET_INFO 4
#define CAP_THREAD_SET_INFO 5
*/
static int __thread_set_pc (__Capability thread, unsigned pc)
{
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_SHARE 2
#define CAP_PAGE_SHARE_COW 3

View File

@ -13,6 +13,7 @@ static void init_idle ():
idle.schedule_next = NULL
idle.address_space = &idle_memory
idle.refs = NULL
idle.flags = THREAD_FLAG_RUNNING | THREAD_FLAG_PRIV
// initialize idle_memory.
idle_memory.prev = 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
// 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 ():
Thread *previous = NULL
first_scheduled = NULL
@ -151,13 +156,13 @@ static void init_threads ():
stackpage->physical = mem->zalloc ()
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
panic (0x13151719, "unable to map initial stack page")
thread->arch.a0 = (unsigned)mem->alloc_receiver ()
thread->arch.a1 = (unsigned)&top_memory
thread->arch.a2 = (unsigned)mem
Capability *admin = mem->alloc_capability ((Receiver *)(CAPTYPE_ADMIN | ~PAGE_MASK), NULL, &mem->capabilities, ~0)
thread->arch.a3 = (unsigned)admin
Receiver *recv = mem->alloc_receiver ()
thread->arch.a0 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_ALL_RIGHTS, recv)
thread->arch.a1 = mkcap (mem, CAPTYPE_THREAD | CAP_THREAD_ALL_PRIV_RIGHTS, thread)
thread->arch.a2 = mkcap (mem, CAPTYPE_MEMORY | CAP_MEMORY_ALL_RIGHTS, mem)
thread->arch.a3 = mkcap (mem, CAPTYPE_RECEIVER | CAP_RECEIVER_CALL, recv)
mem->pfree ((unsigned)pages)
thread->flags = THREAD_FLAG_RUNNING
thread->flags = THREAD_FLAG_RUNNING | THREAD_FLAG_PRIV
thread->schedule_next = NULL
thread->schedule_prev = previous
if previous:

View File

@ -24,17 +24,19 @@ Thread *tlb_refill ():
/// An interrupt which is not an exception has occurred.
Thread *interrupt ():
panic (0x88877722, "Interrupt")
unsigned cause
unsigned cause, status
cp0_get (CP0_CAUSE, cause)
cp0_get (CP0_STATUS, status)
for unsigned i = 0; i < 8; ++i:
if cause & (1 << (i + 8)):
// TODO: Handle interrupt.
// Disable all interrupts which are not handled.
unsigned status
cp0_get (CP0_STATUS, status)
cp0_get (CP0_CAUSE, cause)
status &= ~(cause & 0x0000ff00)
cp0_set (CP0_STATUS, status)
// Disable the interrupt while handling it.
status &= ~(1 << (i + 8))
// Send message to interrupt handler.
if arch_interrupt_receiver[i]:
unsigned data[4] = {0, 0, 0, 0}
Capability *cap[4] = {NULL, NULL, NULL, NULL}
bool copy[4] = {false, false, false, false}
arch_interrupt_receiver[i]->send_message (i, data, cap, copy)
return current
/// A general exception has occurred.

View File

@ -22,22 +22,26 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
static Capability *reply
static Receiver *reply_receiver
static void reply_cap (unsigned target, unsigned protected_data):
Capability r
static void fill_cap (Capability *r, unsigned target, unsigned protected_data):
Capability **ref
if target & ~KERNEL_MASK:
ref = &((Receiver *)target)->capabilities
else:
ref = &((Object_base *)protected_data)->refs
// 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 }
Capability *caps[4] = { &r, NULL, NULL, NULL }
bool cops[4] = { true, false, false, false }
if reply:
reply->invoke (d, caps, cops)
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):
unsigned d[4] = { 0, 0, 0, 0 }
@ -46,7 +50,7 @@ static void reply_cap (Capability *cap, bool copy):
if reply:
reply->invoke (d, caps, cops)
else:
// TODO: send message to reply_receiver
reply_receiver->send_message (~0, d, caps, cops)
static void reply_num (unsigned num):
unsigned d[4] = { num, 0, 0, 0 }
@ -55,15 +59,7 @@ static void reply_num (unsigned num):
if reply:
reply->invoke (d, caps, cops)
else:
// TODO: send message to reply_receiver
static void admin_invoke (unsigned target, Capability *cap, unsigned request, unsigned data):
switch request:
case CAP_ADMIN_SCHEDULE:
schedule ()
break
default:
break
reply_receiver->send_message (~0, d, caps, cops)
static void receiver_invoke (unsigned target, unsigned protected_data, Capability *cap, unsigned request, unsigned 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:
return
switch (unsigned)cap->target & CAPTYPE_MASK:
case CAPTYPE_ADMIN:
// Admin capabilities don't take space, so they cannot be destroyed.
return
case CAPTYPE_RECEIVER:
mem->free_receiver ((Receiver *)cap->protected_data)
return
@ -179,19 +172,64 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability
default:
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
switch request:
case CAP_THREAD_RUN:
if data:
thread->run ()
else:
thread->unrun ()
break
switch data[0]:
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:
// 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:
break
@ -246,24 +284,27 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[
reply_cap (target & d[1], protected_data)
return true
switch target & CAPTYPE_MASK:
case CAPTYPE_ADMIN:
admin_invoke (target, c[1], d[0], d[1])
break
case CAPTYPE_RECEIVER:
if target & (1 << CAP_RECEIVER_CALL):
// This is a call capability.
protected_data = c[0]->protected_data
target = (unsigned)c[0]->target
if ~(unsigned)c[0]->target & ~KERNEL_MASK:
// TODO: create reply capability.
Capability r
Receiver *t = c[0]->target
unsigned p_d = c[0]->protected_data
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:
// Kernel call: don't create actual capablities.
reply = NULL
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):
// This is a reply capability.
// TODO
((Receiver *)protected_data)->send_message (~0, d, c, copy)
return true
receiver_invoke (target, protected_data, c[1], d[0], d[1])
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])
break
case CAPTYPE_THREAD:
thread_invoke (target, protected_data, c[1], d[0], d[1])
thread_invoke (target, protected_data, c[1], d)
break
case CAPTYPE_PAGE:
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")
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]):
if (unsigned)target & ~KERNEL_MASK:
// This is not a kernel capability: send a message to the receiver.
bool tried_direct = false
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
return target->send_message (protected_data, data, cap, copy)
// This is a kernel capability. Use a function to allow optimized call capabilities.
return kernel_invoke ((unsigned)target, protected_data, data, cap, copy)

View File

@ -69,6 +69,7 @@ struct Receiver : public Object <Receiver>:
Message *messages
void own (Thread *o)
void orphan ()
bool send_message (unsigned protected_data, unsigned data[4], Capability *cap[4], bool copy[4])
struct Capability : public Object <Capability>:
Receiver *target
@ -109,7 +110,7 @@ struct Memory : public Object <Memory>:
void *search_free (unsigned size, void **first)
Page *alloc_page ()
Thread *alloc_thread ()
Message *alloc_message (Capability *source)
Message *alloc_message (Receiver *target, unsigned protected_data)
Receiver *alloc_receiver ()
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)
@ -155,12 +156,14 @@ EXTERN Thread *current
void Thread_arch_init (Thread *thread)
void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4])
void Thread_arch_receive_fail (Thread *thread)
unsigned *Thread_arch_info (Thread *thread, unsigned num)
void Memory_arch_init (Memory *mem)
void Memory_arch_free (Memory *mem)
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write)
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address)
Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable)
void arch_invoke ()
void arch_register_interrupt (unsigned num, Receiver *r)
bool Memory::map (Page *page, unsigned address, bool write):
return Memory_arch_map (this, page, address, write)

View File

@ -42,6 +42,73 @@ void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4]):
void Thread_arch_receive_fail (Thread *thread):
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):
mem->arch.asid = 1
mem->arch.directory = NULL
@ -195,8 +262,6 @@ void arch_invoke ():
bool wait, copy[4]
Thread *caller = current
target = caller->address_space->find_capability (current->arch.v0, &wait)
if wait:
caller->wait ()
if !target:
// 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)
@ -205,6 +270,8 @@ void arch_invoke ():
// Calling an invalid capability always fails.
caller->arch.v0 = 0
else:
if wait:
caller->wait ()
c[0] = caller->address_space->find_capability (caller->arch.a0, &copy[0])
c[1] = caller->address_space->find_capability (caller->arch.a1, &copy[1])
c[2] = caller->address_space->find_capability (caller->arch.a2, &copy[2])
@ -237,3 +304,10 @@ void arch_invoke ():
if current->flags & THREAD_FLAG_PRIV:
status |= 0x10000000
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)))

View File

@ -120,6 +120,7 @@ struct Memory_arch:
// 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.
EXTERN unsigned asids[64]
EXTERN Receiver *arch_interrupt_receiver[8]
// Functions which can be called from assembly must not be mangled.
extern "C":