From 305bc037115d4d6d85ea49b8009b48aae07f5e18 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Wed, 27 May 2009 18:33:05 +0200 Subject: [PATCH] more --- alloc.ccp | 6 +- boot-helper.S | 7 +- boot-programs/sos.h | 136 +++++++++++++++++++++++++------ init.ccp | 17 ++-- interrupts.ccp | 18 +++-- invoke.ccp | 190 +++++++++++++++++++++++++++----------------- kernel.hhp | 5 +- mips.ccp | 78 +++++++++++++++++- mips.hhp | 1 + 9 files changed, 337 insertions(+), 121 deletions(-) diff --git a/alloc.ccp b/alloc.ccp index f1e6638..cd71669 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -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 (): diff --git a/boot-helper.S b/boot-helper.S index a9b29c0..7dae1e4 100644 --- a/boot-helper.S +++ b/boot-helper.S @@ -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 diff --git a/boot-programs/sos.h b/boot-programs/sos.h index 6b582e0..65da45b 100644 --- a/boot-programs/sos.h +++ b/boot-programs/sos.h @@ -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 diff --git a/init.ccp b/init.ccp index 3bfc500..c8b76ad 100644 --- a/init.ccp +++ b/init.ccp @@ -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: diff --git a/interrupts.ccp b/interrupts.ccp index e4aea00..08e0c0f 100644 --- a/interrupts.ccp +++ b/interrupts.ccp @@ -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. diff --git a/invoke.ccp b/invoke.ccp index dfd88a4..09a62b0 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -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) diff --git a/kernel.hhp b/kernel.hhp index 2092c66..78ac736 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -69,6 +69,7 @@ struct Receiver : public Object : 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 : Receiver *target @@ -109,7 +110,7 @@ struct Memory : public Object : 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) diff --git a/mips.ccp b/mips.ccp index e0ae5ec..f55390c 100644 --- a/mips.ccp +++ b/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): 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, ©[0]) c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1]) c[2] = caller->address_space->find_capability (caller->arch.a2, ©[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))) diff --git a/mips.hhp b/mips.hhp index e209d70..1e96f7e 100644 --- a/mips.hhp +++ b/mips.hhp @@ -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":