From 06390fd2d1c2527f7906ece45bc15046d2e96d94 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Sun, 24 Jan 2010 21:34:24 +0100 Subject: [PATCH] make things work with terminals --- Makefile | 4 +- alloc.ccp | 163 +++++++++++++-------- boot-programs/crt0.ccp | 2 +- boot-programs/init.ccp | 150 ++++++++++++++----- devices.hhp | 33 ++--- invoke.ccp | 218 +++++++++++++++++----------- iris.hhp | 21 ++- kernel.hhp | 50 ++++--- memory.ccp | 78 ++++++---- mips/arch.ccp | 70 ++++----- mips/init.ccp | 37 +++-- mips/interrupts.ccp | 58 ++++---- mips/nanonote/Makefile.arch | 2 +- mips/nanonote/board.ccp | 2 +- mips/nanonote/server/usb-server.ccp | 14 +- panic.ccp | 122 +++++++++------- source/#buzzer.ccp | 2 +- source/#gpio.ccp | 2 +- source/#lcd.ccp | 181 +++++++++++++++++------ source/#nanonote-gpio.ccp | 66 ++++----- source/ball.ccp | 49 +++++++ source/crt0.ccp | 15 +- source/metronome.ccp | 2 +- 23 files changed, 854 insertions(+), 487 deletions(-) create mode 100644 source/ball.ccp diff --git a/Makefile b/Makefile index a45cea3..e94ae01 100644 --- a/Makefile +++ b/Makefile @@ -44,11 +44,11 @@ PYPP = /usr/bin/pypp %.elf: boot-programs/crt0.o boot-programs/%.o $(LD) $(LDFLAGS) $(filter %.o,$^) -o $@ - #$(OBJCOPY) -S $(OBJCOPYFLAGS) $@ + $(OBJCOPY) -S $(OBJCOPYFLAGS) $@ fs/%.elf: source/crt0.o source/%.o $(LD) $(LDFLAGS) $(filter %.o,$^) -o $@ - #$(OBJCOPY) -S $(OBJCOPYFLAGS) $@ + $(OBJCOPY) -S $(OBJCOPYFLAGS) $@ clean: rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES) diff --git a/alloc.ccp b/alloc.ccp index 2935864..29b9047 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -27,6 +27,7 @@ #define PREV(x) (((kObject **)(x))[-2]) #define NEXT(x) (((kObject **)(x))[-1]) +// ATTENTION! When changing SIZE, be sure to also change the hard-coded 8 in kernel.hhp which defines MAX_NUM_CAPS. #define SIZE (2 * sizeof (kObject *)) bool kMemory::use (unsigned num): @@ -45,12 +46,14 @@ void kMemory::unuse (unsigned num): m->used -= num // This allocates a new block of memory for use by the kernel. -// size is the requires size of the block (excluding SIZE) +// size is the required size of the block (excluding SIZE) // first is a pointer to the first object pointer of this type. // The result is a block of size at least size, which is linked as an object in the list of first. void *kMemory::search_free (unsigned size, void **first): kFree *f - unsigned s = 0 + if size >= PAGE_SIZE - SIZE: + panic (size, "requested size is too large") + int s = 0 // Let's see if there already is a kFree chunk which is large enough. for f = frees; f; f = (kFree *)f->next: if NEXT (f): @@ -65,7 +68,7 @@ void *kMemory::search_free (unsigned size, void **first): // No chunk was found; allocate a new page and add a chunk in it. It is always large enough. unsigned p = palloc () if !p: - dbg_log ("no free space: kernel allocation failed") + kdebug ("no free space: kernel allocation failed") return NULL f = (kFree *)(p + SIZE) // Mark it as a kFree object. @@ -199,9 +202,9 @@ kThread *kMemory::alloc_thread (unsigned size): ret->slot[i].prev.thread = NULL ret->slot[i].next.thread = NULL ret->slot[i].caps = NULL - //dbg_log ("new thread: ") - //dbg_log_num ((unsigned)ret) - //dbg_log ("\n") + //kdebug ("new thread: ") + //kdebug_num ((unsigned)ret) + //kdebug ("\n") return ret void kCaps::init (unsigned s): @@ -211,10 +214,22 @@ void kCaps::init (unsigned s): set (i, NULL, 0, kCapRef (), NULL) kCaps *kMemory::alloc_caps (unsigned size): - kCaps *ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses) + if size == 0: + dpanic (0, "zero-size caps") + return NULL + kCaps *ret + if size > MAX_NUM_CAPS: + dpanic (size, "requested caps is too large") + return NULL + ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses) if !ret: return NULL ret->init (size) + //kdebug ("allocate caps ") + //kdebug_num ((unsigned)ret) + //kdebug ('+') + //kdebug_num (size) + //kdebug ('\n') return ret kMessage *kMemory::alloc_message (kReceiver *target): @@ -278,22 +293,36 @@ kMemory *kMemory::alloc_memory (): return ret void kCaps::set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr): - caps[index].target = target - caps[index].protected_data = pdata - caps[index].parent = parent - caps[index].children.reset () - caps[index].sibling_prev.reset () + if index >= size: + kdebug ("size: ") + kdebug_num (size) + kdebug ("\n") + dpanic (index, "index too large for kCaps") + return + kCapability *c = &caps[index] + if (unsigned)target == 0x81fdc350: + kdebug ("setting cap ") + kdebug_num (index) + kdebug (" old target: ") + kdebug_num ((unsigned)c->target) + c->target = target + c->protected_data = pdata + c->parent = parent + c->children.reset () + c->sibling_prev.reset () if parent.valid (): - caps[index].sibling_next = parent->children + c->sibling_next = parent->children parent->children = kCapRef (this, index) else: if parent_ptr: - caps[index].sibling_next = *parent_ptr + c->sibling_next = *parent_ptr *parent_ptr = kCapRef (this, index) else: - caps[index].sibling_next.reset () - if caps[index].sibling_next.valid (): - caps[index].sibling_next->sibling_prev = kCapRef (this, index) + c->sibling_next.reset () + if c->sibling_next.valid (): + c->sibling_next->sibling_prev = kCapRef (this, index) + if (unsigned)target == 0x81fdc350: + kdebug (" done\n") void kCaps::clone (unsigned index, kCapRef source, bool copy): cap (index)->invalidate () @@ -375,6 +404,10 @@ void kReceiver::own (kThread *o): void kCapability::invalidate (): if !target: return + //kdebug_num ((unsigned)target) + //kdebug (":") + //kdebug_num ((unsigned)protected_data.l) + //kdebug ("\n") if sibling_prev.valid (): sibling_prev->sibling_next = sibling_next else if parent.valid (): @@ -404,8 +437,11 @@ void kCapability::invalidate (): c = next void kMemory::free_caps (kCaps *c): + //kdebug ("free caps ") + //kdebug_num ((unsigned)c) + //kdebug ('\n') for unsigned i = 0; i < c->size; ++i: - c->caps[i].invalidate () + c->cap (i)->invalidate () while c->first_slot.thread: c->first_slot.thread->unset_slot (c->first_slot.index) free_obj (c, (void **)&capses) @@ -474,10 +510,6 @@ void kMemory::free_memory (kMemory *mem): free_obj (mem, (void **)&memories) void kPage::forget (): - //dbg_log ("forget ") - //dbg_log_num ((unsigned)this) - //dbg_log ("\n") - dbg_code.l = (unsigned)old_current if share_prev || share_next: if share_prev: share_prev->share_next = share_next @@ -499,19 +531,19 @@ static void check_receiver (kReceiver *r, kCapRef cap, unsigned line): dpanic (line, "consistency bug in capabilities") else: if cap->protected_data.l != (unsigned)r: - dbg_log ("Buggy: receiver=") - dbg_log_num ((unsigned)r) - dbg_log ("; caps=") - dbg_log_num ((unsigned)cap.caps) - dbg_log ("; caps mem=") - dbg_log_num ((unsigned)cap.caps->address_space) - dbg_log ("; cap=") - dbg_log_num ((unsigned)cap.deref ()) - dbg_log ("; cap target=") - dbg_log_num ((unsigned)cap->target) - dbg_log ("; protected=") - dbg_log_num (cap->protected_data.l) - dbg_log ("!= receiver\n") + kdebug ("Buggy: receiver=") + kdebug_num ((unsigned)r) + kdebug ("; caps=") + kdebug_num ((unsigned)cap.caps) + kdebug ("; caps mem=") + kdebug_num ((unsigned)cap.caps->address_space) + kdebug ("; cap=") + kdebug_num ((unsigned)cap.deref ()) + kdebug ("; cap target=") + kdebug_num ((unsigned)cap->target) + kdebug ("; protected=") + kdebug_num (cap->protected_data.l) + kdebug ("!= receiver\n") dpanic (line, "consistency bug in kernel capabilities") for kCapRef c = cap->children; c.valid (); c = c->sibling_next: check_receiver (r, c, line) @@ -523,60 +555,65 @@ void kReceiver::check (unsigned line): void kMemory::check (unsigned line): for kReceiver *r = receivers; r; r = (kReceiver *)r->next: r->check (line) + for kThread *t = threads; t; t = (kThread *)t->next: + if t->flags & Kernel::Thread::RUNNING && t->pc == 0: + kdebug_num ((unsigned)t) + kdebug ("\n") + panic (line, "pc is 0") for kMemory *m = memories; m; m = (kMemory *)m->next: m->check (line) static void print_obj (kObject *o): for kObject *obj = o; o; o = (kObject *)o->next: - dbg_log_num ((unsigned)o) - dbg_log ("->") - dbg_log ("NULL\n") + kdebug_num ((unsigned)o) + kdebug ("->") + kdebug ("NULL\n") void kMemory::print (unsigned line, unsigned indent): if indent == 0: print_free () for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') + kdebug ('\t') ++indent - dbg_log ("Memory ") - dbg_log_num ((unsigned)this) - dbg_log ("\n") + kdebug ("Memory ") + kdebug_num ((unsigned)this) + kdebug ("\n") for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') - dbg_log ("frees: ") + kdebug ('\t') + kdebug ("frees: ") for kFree *f = frees; f; f = (kFree *)f->next: - dbg_log_num ((unsigned)f) - dbg_log (":") + kdebug_num ((unsigned)f) + kdebug (":") unsigned n = (unsigned)NEXT (f) if n: n -= (unsigned)f if n >= PAGE_SIZE: dpanic (0, "invalid kFree") - dbg_log_num (n, 3) - dbg_log ("->") - dbg_log ("NULL\n") + kdebug_num (n, 3) + kdebug ("->") + kdebug ("NULL\n") for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') - dbg_log ("pages: ") + kdebug ('\t') + kdebug ("pages: ") print_obj (pages) for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') - dbg_log ("threads: ") + kdebug ('\t') + kdebug ("threads: ") print_obj (threads) for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') - dbg_log ("receivers: ") + kdebug ('\t') + kdebug ("receivers: ") for kReceiver *r = receivers; r; r = (kReceiver *)r->next: - dbg_log_num ((unsigned)r) - dbg_log ("(") + kdebug_num ((unsigned)r) + kdebug ("(") for kMessage *m = r->messages; m; m = (kMessage *)m->next: - dbg_log_num ((unsigned)m) - dbg_log ("->") - dbg_log ("NULL)->") - dbg_log ("NULL\n") + kdebug_num ((unsigned)m) + kdebug ("->") + kdebug ("NULL)->") + kdebug ("NULL\n") for unsigned i = 0; i < indent; ++i: - dbg_log_char ('\t') - dbg_log ("capses: ") + kdebug ('\t') + kdebug ("capses: ") print_obj (capses) for kMemory *m = memories; m; m = (kMemory *)m->next: m->print (line, indent) diff --git a/boot-programs/crt0.ccp b/boot-programs/crt0.ccp index 355fabb..c0d91bc 100644 --- a/boot-programs/crt0.ccp +++ b/boot-programs/crt0.ccp @@ -105,7 +105,7 @@ extern "C": __slot_admin = slot_admin __cap_admin = cap_admin __first_free_slot = NULL - for unsigned i = 2; i < __slots; ++i: + for unsigned i = 1; i < __slots; ++i: Kernel::free_slot (i) __first_free_cap = NULL for unsigned i = 7; i < __caps; ++i: diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index 7f77952..dff8a17 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -20,9 +20,13 @@ #include "iris.hh" #include -#define NUM_SLOTS 4 +#define NUM_SLOTS 8 #define NUM_CAPS 32 +enum Cap_codes: + SYSREQ = 1 << 16 + THREAD + static unsigned _free extern unsigned _end @@ -71,6 +75,10 @@ static unsigned slot static unsigned max_pages static char *mapping static unsigned current_thread +static Kernel::Caps terminals +static unsigned terminal_slot +static Kernel::Caps memories +static unsigned memory_slot // Get the initial block device and filesystem. static Directory receive_devices (): @@ -175,8 +183,10 @@ static void sort (): index[i + 1] = index[i] index[i + 1] = f -static void run (file *f, bool priv): - Kernel::Memory mem = top_memory.create_memory () +static void run (file *f, bool priv, int id): + Kernel::Memory mem = Kernel::Cap (memory_slot, id) + Kernel::set_recv_arg (mem) + top_memory.create_memory () unsigned num_pages = (f->size + PAGE_SIZE - 1) >> PAGE_BITS for unsigned p = 0; p < num_pages; ++p: //kdebug_num (p) @@ -310,7 +320,7 @@ static void run (file *f, bool priv): Kernel::Receiver receiver = mem.create_receiver () receiver.set_owner (thread.copy ()) Kernel::Cap call = receiver.create_call_capability () - Kernel::Cap parent = Kernel::my_receiver.create_capability (++current_thread) + Kernel::Cap parent = Kernel::my_receiver.create_capability (Kernel::Num (current_thread++, THREAD)) caps.set (__receiver_num, receiver.copy ()) caps.set (__thread_num, thread.copy ()) caps.set (__memory_num, mem.copy ()) @@ -319,7 +329,6 @@ static void run (file *f, bool priv): thread.run () Kernel::free_cap (receiver) Kernel::free_cap (thread) - Kernel::free_cap (mem) Kernel::free_cap (call) Kernel::free_cap (parent) Kernel::free_cap (caps) @@ -331,10 +340,13 @@ static void kdebug_name (char const *t, file *f): kdebug_char (f->name[j]) kdebug ("...") +static Device sysreq_dev + struct Dev: static Dev *devs + static unsigned num_devs Dev *next - unsigned code, idx + unsigned code, idx, id Device dev static Dev *find (unsigned c, unsigned i): for Dev *d = devs; d; d = d->next: @@ -342,6 +354,9 @@ struct Dev: return d return NULL static void add (unsigned c, unsigned i, Kernel::Cap cap): + if c == Keyboard::ID && i == 1: + sysreq_dev = cap + return while find (c, i): ++i Dev *d = new Dev () @@ -350,6 +365,7 @@ struct Dev: d->idx = i d->dev = cap devs = d + d->id = num_devs++ static void kdebug_list (): for Dev *d = devs; d; d = d->next: kdebug (">") @@ -358,8 +374,9 @@ struct Dev: kdebug_num (d->idx) Dev *Dev::devs +unsigned Dev::num_devs -void handle_init (): +static void handle_init (unsigned id): while true: Kernel::wait () switch Kernel::recv.data[0].l: @@ -368,46 +385,55 @@ void handle_init (): kdebug_num (Kernel::recv.data[1].l) kdebug (":") kdebug_num (Kernel::recv.data[0].h) + kdebug (" as ") + kdebug_num (Dev::num_devs) kdebug ("\n") Kernel::Cap reply = Kernel::get_reply () Dev::add (Kernel::recv.data[1].l, Kernel::recv.data[0].h, Kernel::get_arg ()) reply.invoke () Kernel::free_cap (reply) break - case Parent::GET_DEVICE: - Kernel::Cap reply = Kernel::get_reply () - Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h) - if d: - kdebug ("giving dev ") - kdebug_num (Kernel::recv.data[1].l) - kdebug (":") - kdebug_num (Kernel::recv.data[0].h) - kdebug ("\n") - Kernel::Cap cap = d->dev.create_user (Kernel::my_memory) - d->dev.use (cap) - reply.invoke (0, 0, cap.copy ()) - Kernel::free_cap (cap) - else: - kdebug ("device not found: ") - kdebug_num (Kernel::recv.data[1].l) - kdebug (":") - kdebug_num (Kernel::recv.data[0].h) - Dev::kdebug_list () - kdebug ("\n") - reply.invoke (~0, ~0) - Kernel::panic (0) - Kernel::free_cap (reply) - break case Parent::INIT_DONE: + memories.set (id + num_files, Kernel::get_reply ()) return default: kdebug ("unknown init request\n") - Kernel::panic (0) + Kernel::panic (Kernel::recv.data[0].l) + +static void get_device (): + Kernel::Cap reply = Kernel::get_reply () + unsigned id = Kernel::recv.protected_data.l + Dev *d = Dev::find (Kernel::recv.data[1].l, Kernel::recv.data[0].h) + if d: + kdebug ("giving dev ") + kdebug_num (Kernel::recv.data[1].l) + kdebug (":") + kdebug_num (Kernel::recv.data[0].h) + kdebug (" = ") + kdebug_num (d->id) + kdebug (" to ") + kdebug_num (id) + kdebug ("\n") + Kernel::Cap cap = Kernel::Caps (terminal_slot, id).get (d->id) + d->dev.use (cap) + reply.invoke (0, 0, cap.copy ()) + Kernel::free_cap (cap) + else: + kdebug ("device not found: ") + kdebug_num (Kernel::recv.data[1].l) + kdebug (":") + kdebug_num (Kernel::recv.data[0].h) + Dev::kdebug_list () + kdebug ("\n") + reply.invoke (~0, ~0) + Kernel::panic (0) + Kernel::free_cap (reply) Kernel::Num start (): // Wait for the debugging device to be active, in case there is one. Kernel::schedule () Dev::devs = NULL + Dev::num_devs = 0 init_alloc () top_memory = Kernel::get_top_memory () Directory root = receive_devices () @@ -417,16 +443,66 @@ Kernel::Num start (): Kernel::Caps caps = Kernel::my_memory.create_caps (max_pages) slot = caps.use () mapping = alloc_space (max_pages) + terminals = Kernel::my_memory.create_caps (num_files) + terminal_slot = terminals.use () + // Two times, because it holds the memory and the init_done reply for each task. + memories = Kernel::my_memory.create_caps (num_files * 2) + memory_slot = memories.use () for unsigned i = 0; i < num_files; ++i: kdebug_name ("loading ", &files[index[i]]) - run (&files[index[i]], files[index[i]].name[0] == '#') + run (&files[index[i]], files[index[i]].name[0] == '#', i) kdebug ("running\n") - handle_init () + handle_init (i) + // Notify all programs that they may start. + for unsigned i = 0; i < num_files; ++i: + Kernel::Cap (memory_slot, i + num_files).invoke () + // create terminals. + for unsigned i = 0; i < num_files; ++i: + Kernel::Caps term (terminal_slot, i) + Kernel::Memory mem (memory_slot, i) + Kernel::set_recv_arg (term) + mem.create_caps (Dev::num_devs) + unsigned termslot = term.use () + for Dev *d = Dev::devs; d; d = d->next: + Kernel::set_recv_arg (Kernel::Cap (termslot, d->id)) + // The 0x15000 is for the Display; the others don't care about it. + d->dev.create_user (mem, 0, 0x15000) + Kernel::free_slot (termslot) + // set up system request. + Keyboard sysreq = sysreq_dev.create_user (Kernel::my_memory) + sysreq_dev.use (sysreq) + Kernel::free_cap (sysreq_dev) + Kernel::Cap cap = Kernel::my_receiver.create_capability (Kernel::Num (0, SYSREQ)) + sysreq.set_cb (cap.copy ()) + Kernel::free_cap (sysreq) + Kernel::free_cap (cap) kdebug ("init done\n") root.unlock_ro () Kernel::free_slot (slot) Kernel::my_memory.destroy (caps) while true: - handle_init () - //Kernel::wait () - //kdebug ("request!\n") + Kernel::wait () + switch Kernel::recv.protected_data.h: + case SYSREQ: + // System request. + if Kernel::recv.data[0].l & Keyboard::RELEASE: + continue + kdebug ("system request...\n") + continue + case THREAD: + // Request for something from a child thread. + switch Kernel::recv.data[0].l: + case Parent::INIT_DONE: + Kernel::panic (Kernel::recv.protected_data.l, "double init_done") + case Parent::PROVIDE_DEVICE: + Kernel::panic (Kernel::recv.protected_data.l, "too late now for provide") + case Parent::GET_DEVICE: + get_device () + break + case Parent::EXIT: + Kernel::panic (Kernel::recv.protected_data.l, "exit is not supported") + default: + Kernel::panic (Kernel::recv.data[0].l, "invalid operation from child") + break + default: + Kernel::panic (Kernel::recv.protected_data.h, "unknown source of request") diff --git a/devices.hhp b/devices.hhp index fceefba..cdb7539 100644 --- a/devices.hhp +++ b/devices.hhp @@ -86,8 +86,8 @@ struct Device : public Kernel::Cap: ID // Create a new user for this device. It will not be the active user. // The provided storage must allow object creation; no other actions may be used by the terminal. - Kernel::Cap create_user (Kernel::Memory storage): - iocall (storage, CAP_MASTER_DIRECT | CREATE_USER) + Kernel::Cap create_user (Kernel::Memory storage, unsigned arg1 = 0, Kernel::Num arg2 = 0): + iocall (storage, Kernel::Num (CAP_MASTER_DIRECT | CREATE_USER, arg1), arg2) return Kernel::get_arg () // Destroy a user. It is made inactive if it was active. void destroy_user (Kernel::Cap user): @@ -161,7 +161,7 @@ struct Parent : public Kernel::Cap: return Kernel::get_arg () // Signal the parent that the initialisation phase is over. void init_done (): - invoke (CAP_MASTER_DIRECT | INIT_DONE) + call (CAP_MASTER_DIRECT | INIT_DONE) // Exit the program. The parent does not reply, but kills the process. void exit (Kernel::Num code): call (CAP_MASTER_DIRECT | EXIT, code) @@ -205,33 +205,24 @@ struct Buzzer : public Kernel::Cap: struct Display : public Kernel::Cap: Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: - EOF_CB = Buzzer::ID - CREATE_FB - USE_FB + SET_EOF_CB = Buzzer::ID + MAP_FB GET_INFO - SET_STATE ID // Register an end-of-frame callback. // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events. void set_eof_cb (Kernel::Cap cb): - ocall (cb, CAP_MASTER_DIRECT | EOF_CB) - // Create a framebuffer for the display. When not in use, it can be freed by the user. - // The pages must be cappages holding Page capabilities. They are filled by the display. - // The passed numbers must be 0 or match a mode that the device can use. - // The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer. - unsigned create_framebuffer (unsigned w = 0, unsigned h = 0, unsigned mode = 0): - return icall (Kernel::Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Kernel::Num ((w << 16) | h, mode)).l - // Use a framebuffer. The address must have been returned from display_create_framebuffer. - // w, h and mode must match the values given at creation time. - // unuse_cb is called the next time this operation is requested for this display. - void use_framebuffer (unsigned addr, Kernel::Cap unuse_cb = Kernel::Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0): - ocall (unuse_cb, Kernel::Num (CAP_MASTER_DIRECT | USE_FB, addr), Kernel::Num ((w << 16) | h, mode)) + ocall (cb, CAP_MASTER_DIRECT | SET_EOF_CB) + // Map the framebuffer into memory. + void map_fb (unsigned address): + call (CAP_MASTER_DIRECT | MAP_FB, address) // Get information about the display. void get_info (): // TODO: Interface is to be designed. + kdebug ("using undefined interface Display::get_info ()\n") + Kernel::panic (0) - -// Numeric setting, such as a display backlight. +// Numerical setting, such as a display backlight. struct Setting : public Kernel::Cap: Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): enum request: diff --git a/invoke.ccp b/invoke.ccp index 254eff2..32602ea 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -19,50 +19,55 @@ #include "kernel.hh" static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c): - dbg_log (prefix) - dbg_log (": caller=") - dbg_log_num ((unsigned)old_current) - dbg_log ("; target=") - dbg_log_num (target) - dbg_log ("; pdata=") - dbg_log_num (pdata) - dbg_log ("; data=") - dbg_log_num (c->data[0].h) - dbg_log (":") - dbg_log_num (c->data[0].l) - dbg_log (",") - dbg_log_num (c->data[1].h) - dbg_log (":") - dbg_log_num (c->data[1].l) + kdebug (prefix) + kdebug (": caller=") + if old_current: + kdebug_num (old_current->id, 2) + else + kdebug ("xx") + kdebug (":") + kdebug_num ((unsigned)old_current) + kdebug ("; target=") + kdebug_num (target) + kdebug ("; pdata=") + kdebug_num (pdata) + kdebug ("; data=") + kdebug_num (c->data[0].h) + kdebug (":") + kdebug_num (c->data[0].l) + kdebug (",") + kdebug_num (c->data[1].h) + kdebug (":") + kdebug_num (c->data[1].l) if c->reply.valid (): - dbg_log ("; reply target=") - dbg_log_num ((unsigned)c->reply->target) - dbg_log ("; pdata=") - dbg_log_num (c->reply->protected_data.l) + kdebug ("; reply target=") + kdebug_num ((unsigned)c->reply->target) + kdebug ("; pdata=") + kdebug_num (c->reply->protected_data.l) if c->arg.valid (): - dbg_log ("; arg target=") - dbg_log_num ((unsigned)c->arg->target) - dbg_log ("; pdata=") - dbg_log_num (c->arg->protected_data.l) - dbg_log ("\n") + kdebug ("; arg target=") + kdebug_num ((unsigned)c->arg->target) + kdebug ("; pdata=") + kdebug_num (c->arg->protected_data.l) + kdebug ("\n") void kThread::raise (unsigned code, unsigned data): - dbg_log ("raise ") + kdebug ("raise ") if old_current: - dbg_log_num (old_current->id, 2) + kdebug_num (old_current->id, 2) else: - dbg_log ("xx") - dbg_log_char (':') - dbg_log_num ((unsigned)old_current) - dbg_log_char ('/') + kdebug ("xx") + kdebug (':') + kdebug_num ((unsigned)old_current) + kdebug ('/') if code < Kernel::NUM_EXCEPTION_CODES: - dbg_log (Kernel::exception_name[code]) + kdebug (Kernel::exception_name[code]) else: - dbg_log ("invalid code:") - dbg_log_num (code) - dbg_log_char ('/') - dbg_log_num (data) - dbg_log_char ('\n') + kdebug ("invalid code:") + kdebug_num (code) + kdebug ('/') + kdebug_num (data) + kdebug ('\n') dpanic (code, "raise") unrun () if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target: @@ -79,20 +84,20 @@ kCapRef kThread::find_capability (unsigned code, bool *copy): unsigned num = c & 0xffff if s >= slots || !slot[s].caps || num >= slot[s].caps->size: if c != CAP_NONE: - dbg_log_num ((unsigned)old_current) - dbg_log (": invalid capability ") - dbg_log_num (code) - dbg_log_char ('\n') - dbg_log_num (num) - dbg_log_char (':') - dbg_log_num (s) - dbg_log (" > ") + kdebug_num ((unsigned)old_current) + kdebug (": invalid capability ") + kdebug_num (code) + kdebug ('\n') + kdebug_num (num) + kdebug (':') + kdebug_num (s) + kdebug (" > ") if slot[s].caps: - dbg_log_num (slot[s].caps->size) + kdebug_num (slot[s].caps->size) else: - dbg_log ("no caps") - dbg_log_char ('\n') - dpanic (code, "debug") + kdebug ("no caps") + kdebug ('\n') + dpanic (code, "invalid capability") return kCapRef () return kCapRef (slot[s].caps, num) @@ -156,9 +161,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context * return true static kCapability::Context *context -// reply_caps is the source of a receiver-generated reply capability. -// replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply. -static kCaps reply_caps, replied_caps static kReceiver *reply_target static Kernel::Num reply_protected @@ -181,16 +183,16 @@ static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0): dpanic (0, "nothing to reply to") static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref, unsigned num = 0): + if !reply_target: + dpanic (0, "nothing to reply to") + return replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref) kCapability::Context c c.arg = kCapRef (&replied_caps, 0) c.copy[1] = true c.data[0] = Kernel::Num (num, 0) - if reply_target: - reply_target->send_message (reply_protected, &c) - c.arg->invalidate () - else: - dpanic (0, "nothing to reply to") + reply_target->send_message (reply_protected, &c) + c.arg->invalidate () static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): kReceiver *receiver = (kReceiver *)protected_data.l @@ -214,15 +216,15 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK: if !c->arg.valid () || c->arg->target != receiver: if !c->arg.valid (): - dbg_log ("invalid arg\n") + kdebug ("invalid arg\n") else: - dbg_log ("target: ") - dbg_log_num ((unsigned)c->arg->target) - dbg_log ("/") - dbg_log_num ((unsigned)c->arg->protected_data.h) - dbg_log (":") - dbg_log_num ((unsigned)c->arg->protected_data.l) - dbg_log ("\n") + kdebug ("target: ") + kdebug_num ((unsigned)c->arg->target) + kdebug ("/") + kdebug_num ((unsigned)c->arg->protected_data.h) + kdebug (":") + kdebug_num ((unsigned)c->arg->protected_data.l) + kdebug ("\n") dpanic (0, "wrong argument for get_protected") reply_num (Kernel::ERR_INVALID_ARGUMENT) return @@ -264,7 +266,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte reply_num (receiver->alarm_count) return default: - dpanic (0, "invalid receiver operation") + dpanic (cmd, "invalid receiver operation") reply_num (Kernel::ERR_INVALID_OPERATION) return reply_num (0) @@ -294,6 +296,9 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ kThread *ret = mem->alloc_thread (c->data[1].l) if ret: reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs) + //kdebug ("created thread: ") + //kdebug_num ((unsigned)ret) + //kdebug ("\n") else: dpanic (0x23311992, "out of memory creating thread") reply_num (Kernel::ERR_OUT_OF_MEMORY) @@ -358,7 +363,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ reply_num (Kernel::ERR_INVALID_ARGUMENT) return if c->data[1].l & (unsigned)c->arg->target & Kernel::Page::READONLY: - dbg_log ("Mapping readonly because capability is readonly\n") + kdebug ("Mapping readonly because capability is readonly\n") page->flags |= Kernel::Page::MAPPED_READONLY mem->map (page, c->data[1].l & PAGE_MASK) break @@ -526,7 +531,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ page->address_space->unuse () else: page->flags |= Kernel::Page::PAYING - page->frame = c->data[1].l & PAGE_MASK + page->frame = (c->data[1].l & PAGE_MASK) | 0x80000000 page->flags |= Kernel::Page::FRAME if !(c->data[1].l & 1): page->flags |= Kernel::Page::UNCACHED @@ -545,6 +550,9 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_ case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK: arch_reboot () case Kernel::Thread::PRIV_PANIC & REQUEST_MASK: + if c->data[1].l == 0xdeaddead: + dbg_code.l = 1 + break panic (c->data[1].l, "panic requested by thread") reply_num (~0) return @@ -602,9 +610,9 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da if c->data[0].h & Kernel::Page::READONLY || cmd & Kernel::Page::READONLY: t->flags |= Kernel::Page::READONLY if !(page->flags & Kernel::Page::FRAME): - dbg_log ("share problem: ") - dbg_log_num (page->flags) - dbg_log ("\n") + kdebug ("share problem: ") + kdebug_num (page->flags) + kdebug ("\n") dpanic (0, "sharing nothing results in lost page") kPage_arch_update_mapping (t) break @@ -727,35 +735,52 @@ static void page_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da static void print_cap (kCapRef cap, kCapRef self): if cap.deref () == self.deref (): - dbg_log_char ('{') + kdebug ('{') else: - dbg_log_char ('[') - dbg_log_num ((unsigned)cap.caps) - dbg_log_char (':') - dbg_log_num (cap.index, 1) + kdebug ('[') + kdebug_num ((unsigned)cap.caps) + kdebug (':') + kdebug_num (cap.index, 1) if !cap.valid (): - dbg_log_char ('!') + kdebug ('!') else: - dbg_log_char ('=') - dbg_log_num ((unsigned)cap->target) - dbg_log_char (':') - dbg_log_num (cap->protected_data.l) + kdebug ('=') + kdebug_num ((unsigned)cap->target) + kdebug (':') + kdebug_num (cap->protected_data.l) for kCapRef c = cap->children; c.valid (); c = c->sibling_next: print_cap (c, self) if cap.deref () == self.deref (): - dbg_log_char ('}') + kdebug ('}') else: - dbg_log_char (']') + kdebug (']') static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): kCaps *caps = (kCapsP)protected_data.l switch cmd: case Kernel::Caps::GET & REQUEST_MASK: if c->data[1].l >= caps->size: - dpanic (0, "invalid index for get caps") + reply_num (Kernel::ERR_INVALID_ARGUMENT) + kdebug_num ((unsigned)caps) + kdebug (" size: ") + kdebug_num (caps->size) + kdebug ('\n') + dpanic (c->data[1].l, "invalid index for get caps") return kCapability *ret = caps->cap (c->data[1].l) - reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->target)->refs : &ret->target->capabilities) + #if 0 + kdebug_num ((unsigned)caps) + kdebug (" get cap ") + kdebug_num (c->data[1].l) + kdebug (" = ") + kdebug_num ((unsigned)ret->target) + kdebug ("/") + kdebug_num (ret->protected_data.h) + kdebug (":") + kdebug_num (ret->protected_data.l) + kdebug ("\n") + #endif + reply_cap ((unsigned)ret->target, ret->protected_data, ((unsigned)ret->target & ~KERNEL_MASK) == 0 ? &((kObject *)ret->protected_data.l)->refs : &ret->target->capabilities) return case Kernel::Caps::GET_SIZE & REQUEST_MASK: reply_num (caps->size) @@ -766,6 +791,16 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da return caps->clone (c->data[1].l, c->arg, c->copy[1]) reply_num (0) + //kdebug_num ((unsigned)caps) + //kdebug (" set cap ") + //kdebug_num (c->data[1].l) + //kdebug (" to ") + //kdebug_num ((unsigned)caps->caps[c->data[1].l].target) + //kdebug ("/") + //kdebug_num (caps->caps[c->data[1].l].protected_data.h) + //kdebug (":") + //kdebug_num (caps->caps[c->data[1].l].protected_data.l) + //kdebug ("\n") return case Kernel::Caps::TRUNCATE & REQUEST_MASK: dpanic (0, "truncate caps is not implemented yet.") @@ -800,7 +835,7 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da while cap.valid (): print_cap (cap, orig) cap = cap->sibling_next - dbg_log_char ('\n') + kdebug ('\n') return default: dpanic (0, "invalid caps operation") @@ -916,7 +951,11 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil if must_wait: old_current->wait () if !reply_target: - dpanic (0x54635675, "no target to call") + if (c->reply.index & ~CAP_COPY) != CAP_NONE: + kdebug ("target index: ") + kdebug_num (c->reply.index) + kdebug ("\n") + dpanic (0x54635675, "no target to call") return if ((unsigned)reply_target & ~KERNEL_MASK) != 0: // This is a user-implemented object. Create a real reply capability. @@ -988,14 +1027,19 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil return void invoke (kReceiverP target, Kernel::Num protected_data, kCapability::Context *c): - //log_message ("invoke", (unsigned)target, protected_data.l, c) + if dbg_code.l && old_current->id != 1: + log_message ("invoke", (unsigned)target, protected_data.l, c) if (unsigned)target & ~KERNEL_MASK: // This is not a kernel capability: send a message to the receiver. if must_wait: old_current->wait () + //else + // log_message ("user invoke", (unsigned)target, protected_data.l, c) target->send_message (protected_data, c) return // This is a kernel capability. Use a function to allow optimized call capabilities. + //if !must_wait && old_current->id == ~0 + // log_message ("kernel invoke", (unsigned)target, protected_data.l, c) context = c if c->reply.valid (): reply_target = c->reply->target diff --git a/iris.hhp b/iris.hhp index af6836a..49dc340 100644 --- a/iris.hhp +++ b/iris.hhp @@ -229,12 +229,14 @@ namespace Kernel: IMessage i i.data[0] = d0 i.data[1] = d1 + i.arg = Cap (CAP_NONE) _call (&i) return recv.data[0] Num Cap::icall (Num d0, Num d1): IMessage i i.data[0] = d0 i.data[1] = d1 + i.arg = Cap (CAP_NONE) _call (&i) return recv.data[0] Num Cap::ocall (Cap c, Num d0, Num d1): @@ -541,7 +543,7 @@ namespace Kernel: ocall (target, CAP_MASTER_DIRECT | DESTROY) // TODO: LIST bool map (Cap page, unsigned address): - return ocall (page, CAP_MASTER_DIRECT | MAP, address).l != ~0 + return ocall (page, CAP_MASTER_DIRECT | MAP, address).l == NO_ERROR Page mapping (void *address): icall (CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address)) return get_arg () @@ -568,8 +570,6 @@ namespace Kernel: my_thread.call (CAP_MASTER_DIRECT | Thread::DBG_SEND, Num (code, bits)) inline void reboot (): my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REBOOT) - inline void panic (unsigned code): - my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code) void Receiver::sleep (unsigned value): my_receiver.set_alarm (value) @@ -578,7 +578,8 @@ namespace Kernel: // The start function has this prototype (there is no main function). Kernel::Num start () -#if 1 && !defined (__KERNEL__) +#ifndef __KERNEL__ +#if 1 // 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 @@ -595,4 +596,16 @@ static void kdebug_num (unsigned n, unsigned digits = 8): for i = 0; i < digits; ++i: kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf]) +namespace Kernel: + inline void panic (unsigned code, char const *message = NULL): + if message: + kdebug (message) + kdebug_char ('\n') + my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code) + if code == 0xdeaddead: + return + while true: + wait () + +#endif #endif diff --git a/kernel.hhp b/kernel.hhp index f449d4f..b2d8c67 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -40,16 +40,14 @@ struct kList struct kListitem // Some functions which must be defined early. -extern "C": - #ifndef NDEBUG - void dbg_log_char (unsigned ch) - void dbg_log (char const *str) - void dbg_log_num (unsigned num, unsigned digits = 8) - #else - #define dbg_log_char(x) do {} while (0) - #define dbg_log(x) do {} while (0) - #define dbg_log_num(n) do {} while (0) - #endif +#ifndef NDEBUG +void kdebug (unsigned ch) +void kdebug (char const *str) +void kdebug_num (unsigned num, unsigned digits = 8) +#else +#define kdebug(x) do {} while (0) +#define kdebug_num(n) do {} while (0) +#endif #include "iris.hh" @@ -178,12 +176,14 @@ struct kCaps : public kObject: _slot_data first_slot unsigned size kCapability caps[1] - kCapability *cap (unsigned idx): - return &caps[idx] + inline kCapability *cap (unsigned idx) void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) void clone (unsigned index, kCapRef source, bool copy) void init (unsigned size) +// The 8 comes from the size of the admin data in a free page. When changing that, this must be changed as well. +#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1) + struct kMessage : public kObject: Kernel::Num protected_data Kernel::Num data[2] @@ -258,6 +258,12 @@ extern "C": void panic_impl (unsigned n, char const *line, char const *name, char const *message = "") #ifndef NDEBUG EXTERN Kernel::Num dbg_code + EXTERN unsigned dbg_buffer[32] + EXTERN unsigned dbg_buffer_head + static void dbg_push (unsigned n): + dbg_buffer[dbg_buffer_head++] = n + if dbg_buffer_head == 32: + dbg_buffer_head = 0 EXTERN kCapRef dbg_cap void dbg_send (unsigned num, unsigned bits) void check (unsigned num, char const *msg) @@ -285,6 +291,9 @@ EXTERN kPage idle_page EXTERN kThreadP first_scheduled EXTERN kThreadP current, old_current EXTERN bool do_schedule, must_wait +// reply_caps is the source of a receiver-generated reply capability. +// replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply. +EXTERN kCaps reply_caps, replied_caps // Defined in memory.ccp unsigned init_memory (unsigned mem) @@ -311,6 +320,11 @@ void arch_register_interrupt (unsigned num, kReceiverP r) void arch_reboot () void arch_uncache_page (unsigned page) +#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0) +#define __stringify2(x) #x +#define __stringify(x) __stringify2 (x) +#define kdebug_line() do { kdebug (__FILE__ ":"); kdebug (__PRETTY_FUNCTION__); kdebug (":"); kdebug (__stringify (__LINE__)); kdebug ('\n'); } while (0) + bool kMemory::map (kPage *page, unsigned address): return kMemory_arch_map (this, page, address) void kMemory::unmap (kPage *page): @@ -323,13 +337,15 @@ kCapability *kCapRef::deref (): void kCapRef::clone (kCapRef source, bool copy): caps->clone (index, source, copy) void kCapRef::set (kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr): + if valid (): + deref ()->invalidate () caps->set (index, target, pdata, parent, parent_ptr) void kCapability::invoke (kCapability::Context *c): ::invoke (target, protected_data, c) - -#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0) -#define __stringify2(x) #x -#define __stringify(x) __stringify2 (x) -#define dbg_log_line() do { dbg_log (__FILE__ ":"); dbg_log (__PRETTY_FUNCTION__); dbg_log (":"); dbg_log (__stringify (__LINE__)); dbg_log_char ('\n'); } while (0) +kCapability *kCaps::cap (unsigned idx): + if idx >= size: + dpanic (idx, "invalid capability requested\n") + return NULL + return &caps[idx] #endif diff --git a/memory.ccp b/memory.ccp index 8d6bea4..f16462a 100644 --- a/memory.ccp +++ b/memory.ccp @@ -1,9 +1,17 @@ #pypp 0 #include "kernel.hh" +//#define DEBUG_ALLOC extern unsigned _end static void clear_page (unsigned page, unsigned num = 1): + #ifdef DEBUG_ALLOC + kdebug ("clearing page ") + kdebug_num (page) + kdebug ("+") + kdebug_num (num) + kdebug ('\n') + #endif page = (page & ~0xc0000000) | 0xa0000000 for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i: arch_uncache_page (page - 0x20000000) @@ -24,7 +32,7 @@ unsigned init_memory (unsigned mem): unsigned phys_alloc (unsigned num): if free_begin + num * PAGE_SIZE > free_end: - dbg_log ("memory allocation failed\n") + kdebug ("memory allocation failed\n") return 0 unsigned ret = free_begin free_begin += num * PAGE_SIZE @@ -57,14 +65,22 @@ unsigned init_memory (unsigned mem): first_free->next = NULL first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free & ~0xc0000000)) >> PAGE_BITS #ifdef DEBUG_ALLOC - dbg_log ("initial memory: ") - dbg_log_num ((unsigned)first_free & ~0xc0000000) - dbg_log ("+") - dbg_log_num (first_free->num) - dbg_log ("\n") + kdebug ("initial memory: ") + kdebug_num ((unsigned)first_free & ~0xc0000000) + kdebug ("+") + kdebug_num (first_free->num) + kdebug ("\n") #endif return first_free->num +#ifdef DEBUG_ALLOC +static bool is_free (unsigned page): + for kFreePages *p = first_free; p; p = p->next: + if page >= (unsigned)p && page < (unsigned)p + (p->num << PAGE_BITS): + return true + return false +#endif + unsigned phys_alloc (unsigned num): kFreePages *choice = NULL for kFreePages *p = first_free; p; p = p->next: @@ -81,11 +97,13 @@ unsigned phys_alloc (unsigned num): p->next->prev = p->prev clear_page ((unsigned)p, num) #ifdef DEBUG_ALLOC - dbg_log ("allocating ") - dbg_log_num ((unsigned)p & ~0xc0000000) - dbg_log ("+") - dbg_log_num (num << PAGE_BITS) - dbg_log ("\n") + kdebug ("allocating ") + kdebug_num ((unsigned)p & ~0xc0000000) + kdebug ("+") + kdebug_num (num << PAGE_BITS) + kdebug ("\n") + if is_free ((unsigned)p): + panic ((unsigned)p, "page still free after allocation") #endif return (unsigned)p choice = p @@ -97,21 +115,25 @@ unsigned phys_alloc (unsigned num): unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS) clear_page (ret, num) #ifdef DEBUG_ALLOC - dbg_log ("allocating ") - dbg_log_num (ret & ~0xc0000000) - dbg_log ("+") - dbg_log_num (num << PAGE_BITS) - dbg_log ("\n") + kdebug ("allocating ") + kdebug_num (ret & ~0xc0000000) + kdebug ("+") + kdebug_num (num << PAGE_BITS) + kdebug ("\n") + if is_free (ret): + panic (ret, "page still free after allocation") #endif return ret void phys_free (unsigned page, unsigned num): #ifdef DEBUG_ALLOC - dbg_log ("free ") - dbg_log_num (page & ~0xc0000000) - dbg_log ("+") - dbg_log_num (num) - dbg_log ("\n") + kdebug ("free ") + kdebug_num (page & ~0xc0000000) + kdebug ("+") + kdebug_num (num << PAGE_BITS) + kdebug ("\n") + if is_free (page): + panic (page, "page already free") #endif unsigned size = num << PAGE_BITS if !first_free || (unsigned)first_free > page: @@ -172,13 +194,13 @@ bool check_free (kObject *o, unsigned size): return true void print_free (): - dbg_log ("Free pages: ") + kdebug ("Free pages: ") for kFreePages *p = first_free; p; p = p->next: - dbg_log_num ((unsigned)p) - dbg_log (":") - dbg_log_num (p->num, 4) - dbg_log ("->") - dbg_log ("NULL\n") + kdebug_num ((unsigned)p) + kdebug (":") + kdebug_num (p->num, 4) + kdebug ("->") + kdebug ("NULL\n") #endif #endif @@ -208,7 +230,7 @@ void raw_pfree (unsigned page): unsigned kMemory::zalloc (): if !use (): dpanic (0x34638920, "limit reached: allocation not allowed") - dbg_log ("limit reached: allocation not allowed\n") + kdebug ("limit reached: allocation not allowed\n") return NULL return raw_zalloc () diff --git a/mips/arch.ccp b/mips/arch.ccp index 80cb3c3..e9a36de 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -119,19 +119,19 @@ void kMemory_arch_init (kMemory *mem): mem->arch.shadow = NULL static void tlb_reset (kMemory *mem, unsigned address, unsigned value): - //dbg_log_line () + //kdebug_line () unsigned asid = mem->arch.asid if asids[asid] != (unsigned)mem: - //dbg_log ("not resetting tlb, because the asid is not in use.\n") + //kdebug ("not resetting tlb, because the asid is not in use.\n") return - //dbg_log ("resetting tlb for ") - //dbg_log_num (address) - //dbg_log ("\n") + //kdebug ("resetting tlb for ") + //kdebug_num (address) + //kdebug ("\n") cp0_set (CP0_ENTRY_HI, address | asid) __asm__ volatile ("tlbp") unsigned idx cp0_get (CP0_INDEX, idx) - if ~idx & 0x80000000: + if !(idx & (1 << 31)): __asm__ volatile ("tlbr") if address & (1 << PAGE_BITS): cp0_set (CP0_ENTRY_LO1, value) @@ -139,23 +139,26 @@ static void tlb_reset (kMemory *mem, unsigned address, unsigned value): cp0_set (CP0_ENTRY_LO0, value) __asm__ volatile ("tlbwi") #if 0 - dbg_log ("tlb reset ") + kdebug ("tlb reset ") unsigned hi, lo0, lo1 cp0_get (CP0_ENTRY_LO0, lo0) cp0_get (CP0_ENTRY_LO1, lo1) cp0_get (CP0_ENTRY_HI, hi) - dbg_log_num (lo0) - dbg_log (":") - dbg_log_num (lo1) - dbg_log (" for ") - dbg_log_num (hi) - dbg_log ("\n") + kdebug_num (idx, 2) + kdebug ('|') + kdebug_num (lo0) + kdebug (":") + kdebug_num (lo1) + kdebug (" for ") + kdebug_num (hi) + kdebug ("\n") #endif + cp0_set (CP0_ENTRY_HI, old_current->address_space->arch.asid) static unsigned make_entry_lo (kPage *page): - //dbg_log_line () + //kdebug_line () if !page->frame: - //dbg_log ("not mapping because there is no frame\n") + //kdebug ("not mapping because there is no frame\n") return 0 unsigned flags if page->flags & Kernel::Page::UNCACHED: @@ -168,7 +171,6 @@ static unsigned make_entry_lo (kPage *page): return ((page->frame & ~0x80000000) >> 6) | flags bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address): - //dbg_log_line () if address >= 0x80000000: dpanic (address, "trying to map to kernel address") return false @@ -180,7 +182,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address): dpanic (address, "mapping not page-aligned") address &= PAGE_MASK if !mem->arch.directory: - //dbg_log ("creating directory\n") + //kdebug ("creating directory\n") mem->arch.directory = (Table **)mem->zalloc () if !mem->arch.directory: dpanic (0, "unable to allocate directory") @@ -193,7 +195,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address): return false Table *table = mem->arch.directory[address >> 21] if !table: - //dbg_log ("creating table\n") + //kdebug ("creating table\n") table = (Table *)mem->zalloc () if !table: dpanic (0, "unable to allocate table") @@ -206,21 +208,23 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address): mem->arch.directory[address >> 21] = table unsigned idx = (address >> 12) & ((1 << 9) - 1) if table->entrylo[idx]: - dbg_log ("page already mapped: ") - dbg_log_num (idx, 3) - dbg_log (";") - dbg_log_num (table->entrylo[idx]) - dbg_log ("/") - dbg_log_num ((unsigned)table->page[idx]) - dbg_log (" table: ") - dbg_log_num ((unsigned)table) - dbg_log ("\n") + kdebug ("page already mapped: ") + kdebug_num (idx, 3) + kdebug (";") + kdebug_num (table->entrylo[idx]) + kdebug ("/") + kdebug_num ((unsigned)table->page[idx]) + kdebug (" table: ") + kdebug_num ((unsigned)table) + kdebug ("\n") mem->unmap (table->page[idx]) table->entrylo[idx] = make_entry_lo (page) table->page[idx] = page - //dbg_log ("mapped at address ") - //dbg_log_num (address) - //dbg_log_char ('\n') + //kdebug ("mapped ") + //kdebug_num (page->frame) + //kdebug (" at address ") + //kdebug_num (address) + //kdebug ('\n') page->mapping = address page->arch.next_mapped = mem->arch.shadow[address >> 21] if page->arch.next_mapped: @@ -230,7 +234,7 @@ bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address): return true void kMemory_arch_unmap (kMemory *mem, kPage *page): - //dbg_log_line () + //kdebug_line () unsigned didx = page->mapping >> 21 unsigned tidx = (page->mapping >> 12) & ((1 << 9) - 1) Table *table = mem->arch.directory[didx] @@ -248,7 +252,7 @@ void kMemory_arch_unmap (kMemory *mem, kPage *page): page->mapping = ~0 kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address): - //dbg_log_line () + //kdebug_line () if address >= 0x80000000 || !mem->arch.directory: return NULL Table *table = mem->arch.directory[address >> 21] @@ -257,7 +261,7 @@ kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address): return table->page[(address >> 12) & ((1 << 9) - 1)] void kPage_arch_update_mapping (kPage *page): - //dbg_log_line () + //kdebug_line () if page->mapping == ~0: return unsigned target = make_entry_lo (page) diff --git a/mips/init.ccp b/mips/init.ccp index 17f32eb..3461ce2 100644 --- a/mips/init.ccp +++ b/mips/init.ccp @@ -22,7 +22,7 @@ #include "../kernel.hh" #include -#define NUM_SLOTS 4 +#define NUM_SLOTS 8 #define NUM_CAPS 32 static void init_idle (): @@ -116,9 +116,9 @@ static void init_threads (): first_alarm = NULL kReceiver *init_receiver = NULL for unsigned i = 0; i < NUM_THREADS; ++i: - dbg_log ("Starting thread ") - dbg_log_num (i, 2) - dbg_log ("\n") + kdebug ("Starting thread ") + kdebug_num (i, 2) + kdebug ("\n") kMemory *mem = top_memory.alloc_memory () assert (mem) kThread *thread = mem->alloc_thread (NUM_SLOTS) @@ -177,14 +177,14 @@ static void init_threads (): if !mem->map (page, p): panic (0x22446688, "unable to map initial page") return - //dbg_log ("mapped page ") + //kdebug ("mapped page ") //if readonly: - // dbg_log ("as readonly ") - //dbg_log ("at address ") - //dbg_log_num (p) - //dbg_log (" for ") - //dbg_log_num (i, 1) - //dbg_log_char ('\n') + // kdebug ("as readonly ") + //kdebug ("at address ") + //kdebug_num (p) + //kdebug (" for ") + //kdebug_num (i, 1) + //kdebug ('\n') else: if readonly: panic (0x33399993, "unwritable bss section") @@ -204,11 +204,11 @@ static void init_threads (): if !mem->map (page, p): panic (0x33557799, "unable to map initial bss page") return - dbg_log ("mapped bss page at address ") - dbg_log_num (p) - dbg_log (" for ") - dbg_log_num (i, 1) - dbg_log_char ('\n') + kdebug ("mapped bss page at address ") + kdebug_num (p) + kdebug (" for ") + kdebug_num (i, 1) + kdebug ('\n') else: if page->flags & Kernel::Page::MAPPED_READONLY: panic (0x20203030, "bss section starts on read-only page") @@ -224,7 +224,9 @@ static void init_threads (): if used[p]: mem->use () continue + //kdebug ("freeing unused page from initial file\n") top_memory.pfree (thread_start[i] + (p << PAGE_BITS)) + //kdebug ("freeing unused page list\n") mem->pfree ((unsigned)used) kPage *stackpage = mem->alloc_page () stackpage->frame = mem->zalloc () @@ -262,6 +264,9 @@ void init (unsigned mem): must_wait = false // Initialize kernel variables to empty. unsigned count = init_memory (mem) + // Set up invoke system. + reply_caps.init (1) + replied_caps.init (1) // initialize system control coprocessor. init_cp0 () // initialize everything about the idle task. diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index 87919df..f0ce225 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -24,7 +24,8 @@ void arch_flush_cache (): for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line: __asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line)) -static void handle_exit (): +static kThread *handle_exit (): + dbg_check () --dbg_code.h // Set must_wait to false, so random threads are not set to waiting when the kernel invokes something (such as a dbg_cap). must_wait = false @@ -32,11 +33,10 @@ static void handle_exit (): schedule () if !current: current = &idle - //if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING: - //panic (current->flags, "non-scheduled thread running") + if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING: + panic (current->flags, "non-scheduled thread running") if old_current == current: - return - //dbg_send ((unsigned)current >> 12, 3) + return current arch_flush_cache () if current != &idle: if (kMemory *)asids[current->address_space->arch.asid] != current->address_space: @@ -58,6 +58,7 @@ static void handle_exit (): cp0_set (CP0_STATUS, 0x1000ff13) else: cp0_set (CP0_STATUS, 0x0000ff13) + return current /// A TLB miss has occurred. This is the slow version. It is only used /// when k0 or k1 is not 0, or when an error occurs. @@ -69,8 +70,7 @@ kThread *tlb_refill (): unsigned addr cp0_get (CP0_BAD_V_ADDR, addr) current->raise (Kernel::ERR_NO_PAGE_DIRECTORY, addr) - handle_exit () - return current + return handle_exit () unsigned EntryHi cp0_get (CP0_ENTRY_HI, EntryHi) Table *t = directory[EntryHi >> 21] @@ -84,17 +84,20 @@ kThread *tlb_refill (): cp0_set (CP0_ENTRY_LO0, t->entrylo[idx]) cp0_set (CP0_ENTRY_LO1, t->entrylo[idx + 1]) __asm__ volatile ("tlbwr") - #if 0 - dbg_log ("tlb refill ") - dbg_log_num (t->entrylo[idx]) - dbg_log (":") - dbg_log_num (t->entrylo[idx + 1]) - dbg_log (" for ") - dbg_log_num (EntryHi) - dbg_log ("\n") - #endif - handle_exit () - return current + if dbg_code.l: + kdebug ("tlb refill ") + __asm__ volatile ("tlbp") + unsigned index + cp0_get (CP0_INDEX, index) + kdebug_num (index, 2) + kdebug ("|") + kdebug_num (t->entrylo[idx]) + kdebug (":") + kdebug_num (t->entrylo[idx + 1]) + kdebug (" for ") + kdebug_num (EntryHi) + kdebug ("\n") + return handle_exit () /// An interrupt which is not an exception has occurred. kThread *interrupt (): @@ -126,8 +129,7 @@ kThread *interrupt (): #endif intc_ack_irq (TIMER_INTERRUPT) timer_interrupt () - handle_exit () - return current + return handle_exit () void flush_tlb (unsigned asid): for unsigned tlb = 1; tlb < 32; ++tlb: @@ -147,9 +149,15 @@ static void arch_invoke (): if must_wait: old_current->recv_reply = old_current->arch.t[2] old_current->recv_arg = old_current->arch.t[3] + //kdebug_num (old_current->recv_reply) + //kdebug ("/") + //kdebug_num (old_current->recv_arg) + //kdebug ("\n") if !target.valid (): if must_wait: old_current->wait () + else: + dpanic (target.index, "invalid target called") return msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0]) msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1]) @@ -236,9 +244,9 @@ kThread *exception (): if !dbg_cap.valid (): dpanic (0, "no log capability provided") break - dbg_log ("log capability registered.\n") + kdebug ("log capability registered.\n") break - dbg_log_char (current->arch.a[1]) + kdebug (current->arch.a[1]) #endif break case 10: @@ -294,13 +302,11 @@ kThread *exception (): default: panic (0xf6223344, "Impossible exception code") break - handle_exit () - return current + return handle_exit () /// There's a cache error. Big trouble. Probably not worth trying to recover. kThread *cache_error (): ++dbg_code.h panic (0x33333333, "cache error") old_current = current - handle_exit () - return current + return handle_exit () diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index 9324f01..ece3a08 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -29,7 +29,7 @@ arch_iris_sources = mips/interrupts.cc mips/arch.cc boot_sources = mips/init.cc mips/nanonote/board.cc arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh boot_threads = init udc -programs = \#nanonote-gpio \#buzzer \#lcd metronome +programs = \#nanonote-gpio \#buzzer \#lcd metronome ball all: test diff --git a/mips/nanonote/board.ccp b/mips/nanonote/board.ccp index 5c76a82..8fd1732 100644 --- a/mips/nanonote/board.ccp +++ b/mips/nanonote/board.ccp @@ -72,7 +72,7 @@ void board_init (): UART0_DLLR = uart_div UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS - dbg_log ("\n\nSerial port initialized\n") + kdebug ("\n\nSerial port initialized\n") #endif void arch_reboot (): diff --git a/mips/nanonote/server/usb-server.ccp b/mips/nanonote/server/usb-server.ccp index a124a01..0988a66 100644 --- a/mips/nanonote/server/usb-server.ccp +++ b/mips/nanonote/server/usb-server.ccp @@ -137,13 +137,13 @@ void data::poll (): continue case Directory::LOCK_RO: std::cerr << "lock\n" - if !lock++: - std::cerr << "freezing file list\n" - shevek::dir d (files) - dir.clear () - for shevek::dir::const_iterator i = d.begin (); i != d.end (); ++i: - if !i->name.empty () && i->name[0] != '.': - dir.push_back (Name (i->name)) + lock++ + std::cerr << "freezing file list\n" + shevek::dir d (files) + dir.clear () + for shevek::dir::const_iterator i = d.begin (); i != d.end (); ++i: + if !i->name.empty () && i->name[0] != '.': + dir.push_back (Name (i->name)) continue case Directory::UNLOCK_RO: std::cerr << "unlock\n" diff --git a/panic.ccp b/panic.ccp index 6c640c0..210dbf2 100644 --- a/panic.ccp +++ b/panic.ccp @@ -20,11 +20,11 @@ #include "kernel.hh" #ifdef USE_SERIAL -void dbg_log_char (unsigned ch): +void kdebug (unsigned ch): while !(UART0_LSR & UARTLSR_TDRQ): UART0_TDR = ch #else -void dbg_log_char (unsigned ch): +void kdebug (unsigned ch): if !dbg_cap.valid () || dbg_code.l: return kCapability::Context c @@ -34,51 +34,57 @@ void dbg_log_char (unsigned ch): --dbg_code.l #endif -void dbg_log (char const *str): +void kdebug (char const *str): while *str: - dbg_log_char (*str++) + kdebug (*str++) -void dbg_log_num (unsigned num, unsigned digits): +void kdebug_num (unsigned num, unsigned digits): char const *encode = "0123456789abcdef" for unsigned i = 0; i < digits; ++i: - dbg_log_char (encode[(num >> (4 * ((digits - 1) - i))) & 0xf]) + kdebug (encode[(num >> (4 * ((digits - 1) - i))) & 0xf]) return #if 1 || defined (NDEBUG) -static void print_addr (char const *t, unsigned addr): - dbg_log (t) - dbg_log_num (addr) +static void print_addr (char const *t, unsigned addr, bool last = false): + kdebug (t) + kdebug_num (addr) + #if 1 unsigned de = addr >> 21 unsigned te = (addr >> 12) & ((1 << 9) - 1) if de < 0x400 && old_current && old_current->address_space->arch.directory && old_current->address_space->arch.directory[de]: - dbg_log ("; EntryLo = ") - dbg_log_num (old_current->address_space->arch.directory[de]->entrylo[te]) + kdebug ("; EntryLo = ") + kdebug_num (old_current->address_space->arch.directory[de]->entrylo[te]) else: - dbg_log ("; no directory or page table") - if old_current: + kdebug ("; no directory or page table") + if old_current && de < 0x400: cp0_set (CP0_ENTRY_HI, (addr & (PAGE_MASK << 1)) | old_current->address_space->arch.asid) __asm__ volatile ("tlbp") unsigned idx, hi cp0_get (CP0_INDEX, idx) - dbg_log ("; tlb index: ") + kdebug ("; tlb index: ") if idx & (1 << 31): - dbg_log ("none\n") + kdebug ("none\n") else: __asm__ volatile ("tlbr") - dbg_log_num (idx, 2) - dbg_log ("; EntryLo = ") + kdebug_num (idx, 2) + kdebug ("; EntryLo = ") unsigned lo cp0_get (CP0_ENTRY_LO0, lo) - dbg_log_num (lo) - dbg_log (":") + kdebug_num (lo) + kdebug (":") cp0_get (CP0_ENTRY_LO1, lo) - dbg_log_num (lo) - dbg_log ("\n") - if addr >= 0x80000000: + kdebug_num (lo) + kdebug ("\n") + else: + kdebug ('\n') + if addr >= 0x80000000 && addr < 0xc0000000: for int i = -4; i < 4; ++i: - dbg_log (" ") - dbg_log_num (((unsigned *)addr)[i]) - dbg_log ("\n") + kdebug (" ") + kdebug_num (((unsigned *)addr)[i]) + kdebug ("\n") + #else + kdebug (last ? '\n' : ';') + #endif static void panic_message (unsigned n, const char *line, char const *name, char const *message): unsigned vaddr, epc @@ -89,29 +95,40 @@ static void panic_message (unsigned n, const char *line, char const *name, char print_addr ("BadVAddr: ", vaddr) if old_current: print_addr ("PC: ", old_current->pc) - print_addr ("epc: ", epc) + print_addr ("epc: ", epc, true) #endif - dbg_log ("Panic: caller = ") + kdebug ("Panic: caller = ") if old_current: - dbg_log_num (old_current->id, 2) - dbg_log (":") - dbg_log_num ((unsigned)old_current) + kdebug_num (old_current->id, 2) + kdebug (":") + kdebug_num ((unsigned)old_current) if old_current: - dbg_log_char ('@') - dbg_log_num (old_current->pc) - dbg_log ("; ") - dbg_log (name) - dbg_log_char (':') - dbg_log (line) - dbg_log (": ") - dbg_log (message) - dbg_log_char ('/') - dbg_log_num (n) - dbg_log ("; debug: ") - dbg_log_num (dbg_code.h) - dbg_log_char (':') - dbg_log_num (dbg_code.l) - dbg_log_char ('\n') + kdebug ('@') + kdebug_num (old_current->pc) + kdebug ("; ") + kdebug (name) + kdebug (':') + kdebug (line) + kdebug (": ") + kdebug (message) + kdebug ('/') + kdebug_num (n) + kdebug ("; debug: ") + kdebug_num (dbg_code.h) + kdebug (':') + kdebug_num (dbg_code.l) + kdebug ('\n') + kdebug ("debug buffer:") + unsigned b = dbg_buffer_head + for unsigned i = 0; i < 16; ++i: + kdebug ('\n') + for unsigned j = 0; j < 2; ++j: + kdebug (' ') + kdebug_num (dbg_buffer[b]) + ++b + if b == 32: + b = 0 + kdebug ('\n') void panic_impl (unsigned n, const char *line, char const *name, char const *message): // Stop all threads. @@ -126,23 +143,22 @@ void panic_impl (unsigned n, const char *line, char const *name, char const *mes #ifndef NDEBUG // If a log capability is registered, run its owner. panic_message (n, line, name, message) + #ifndef USE_SERIAL if dbg_cap.valid () && dbg_cap->target->owner: - #ifndef USE_SERIAL dbg_cap->target->owner->run () - #endif // Use the (now running) log thread to display the message. // If no log capability is registered, the machine just hangs. - #ifdef USE_SERIAL + #else arch_reboot () #endif #endif #ifndef NDEBUG void dbg_send (unsigned num, unsigned bits): - dbg_log ("Warning: ") - dbg_log_num (num) - dbg_log_char ('/') - dbg_log_num (bits) - dbg_log_char ('\n') + kdebug ("Warning: ") + kdebug_num (num) + kdebug ('/') + kdebug_num (bits) + kdebug ('\n') #endif #else void delay (unsigned ms): diff --git a/source/#buzzer.ccp b/source/#buzzer.ccp index fa29cf2..3826be4 100644 --- a/source/#buzzer.ccp +++ b/source/#buzzer.ccp @@ -60,9 +60,9 @@ Kernel::Num start (): Device dev = Kernel::my_receiver.create_capability (BUZZER) Kernel::my_parent.provide_device (dev.copy ()) Kernel::free_cap (dev) + Kernel::my_parent.init_done () unsigned user (~0) unsigned next_user (0) - Kernel::my_parent.init_done () while true: Kernel::wait () switch Kernel::recv.protected_data.h: diff --git a/source/#gpio.ccp b/source/#gpio.ccp index e316d6f..66f6da4 100644 --- a/source/#gpio.ccp +++ b/source/#gpio.ccp @@ -270,6 +270,7 @@ Kernel::Num start (): c = Kernel::my_receiver.create_capability (TOUCHPAD) Kernel::my_parent.provide_device (c.copy (), 1) Kernel::free_cap (c) + Kernel::my_parent.init_done () if kbd.is_scanning (): Kernel::my_receiver.set_alarm (ALARM_INTERVAL) @@ -278,7 +279,6 @@ Kernel::Num start (): GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK Kernel::register_interrupt (IRQ_GPIO0) - Kernel::my_parent.init_done () while true: Kernel::schedule () Kernel::wait () diff --git a/source/#lcd.ccp b/source/#lcd.ccp index f5314af..9ed44e1 100644 --- a/source/#lcd.ccp +++ b/source/#lcd.ccp @@ -183,7 +183,7 @@ static void reset (): write_reg (COLOR, 0x01) #endif - LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 + LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM LCD_CFG = cfg LCD_HSYNC = hpe LCD_VSYNC = vpe @@ -191,8 +191,8 @@ static void reset (): LCD_DAH = (hds << 16) | hde LCD_DAV = (vds << 16) | vde LCD_DA0 = physical_descriptor - LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_ENA - //lcd_enable_eof_intr () + LCD_STATE = 0 + LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_EOFM | LCD_CTRL_ENA static void putchar (unsigned x, unsigned y, unsigned ch): if ch < 32 || ch > 126: @@ -245,8 +245,8 @@ static void log_msg (): enum captype: LOG = 32 - SET_EOF_CB BACKLIGHT + LCD static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy): unsigned dx2 = (x - cx) * (x - cx) @@ -267,6 +267,7 @@ Kernel::Num start (): Descriptor descriptor __attribute__ ((aligned (16))) unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS + #if 0 unsigned physical = Kernel::my_memory.alloc_range (pages) assert (physical & PAGE_MASK && ~physical) for unsigned i = 0; i < pages; ++i: @@ -286,6 +287,9 @@ Kernel::Num start (): #else #error "Define your framebuffer format." #endif + #else + unsigned physical = 0 + #endif Kernel::Page p = Kernel::my_memory.mapping (&descriptor) unsigned paddr = p.physical_address () physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK) @@ -305,14 +309,20 @@ Kernel::Num start (): // Register the backlight device. Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT) - Kernel::my_parent.provide_device (backlight) + Kernel::my_parent.provide_device (backlight.copy ()) + Kernel::free_cap (backlight) + + // Register the display device. + Kernel::Cap display = Kernel::my_receiver.create_capability (LCD) + Kernel::my_parent.provide_device (display.copy ()) + Kernel::free_cap (display) + Kernel::my_parent.init_done () Kernel::Cap eof_cb bool have_eof = false bool is_on = true unsigned backlight_user = 0 - Kernel::Num current_backlight = 0 - Kernel::my_parent.init_done () + unsigned current_backlight = 0 while true: Kernel::wait () //log_msg () @@ -320,9 +330,8 @@ Kernel::Num start (): case 0: switch Kernel::recv.protected_data.l: case IRQ_LCD: - lcd_clr_eof () - eof_cb.invoke () have_eof = false + eof_cb.invoke () Kernel::free_cap (eof_cb) break #if defined (TRENDTAC) @@ -331,46 +340,112 @@ Kernel::Num start (): break #endif case BACKLIGHT: + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () + Device::host (BACKLIGHT, current_backlight, reply, arg) + break + case LCD: + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () switch Kernel::recv.data[0].l: case Device::CREATE_USER: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (backlight_user++, BACKLIGHT)) - reply.invoke (0, 0, c.copy ()) - Kernel::free_cap (c) - Kernel::free_cap (reply) + Kernel::Memory mem (arg) + unsigned width = Kernel::recv.data[0].h >> 16 + unsigned height = Kernel::recv.data[0].h & 0xffff + unsigned mode = Kernel::recv.data[1].l & ~PAGE_MASK + unsigned address = Kernel::recv.data[1].l & PAGE_MASK + if (width != 0 && width != h) || (height != 0 && height != v) || mode != 0: + reply.invoke (Kernel::ERR_INVALID_ARGUMENT) + kdebug ("invalid framebuffer requested\n") + Kernel::panic (0) + Kernel::free_cap (reply) + Kernel::free_cap (arg) + break + Kernel::Caps caps = mem.create_caps (4) + caps.set (1, mem.copy ()) + unsigned slot = caps.use () + unsigned physical = mem.alloc_range (pages) + if physical & ~PAGE_MASK: + kdebug ("can't allocate framebuffer\n") + Kernel::panic (0) + assert (physical & PAGE_MASK && ~physical) + Kernel::set_recv_arg (Kernel::Cap (slot, 0)) + Kernel::my_receiver.create_capability (Kernel::Num (physical, LCD)) + for unsigned i = 0; i < pages; ++i: + Kernel::Page p = mem.create_page () + p.alloc_physical (physical + (i << PAGE_BITS), false, true) + if address != ~0: + //Kernel::panic (0xdeaddead) + mem.map (p, address + (i << PAGE_BITS)) + Kernel::free_cap (p) + Kernel::free_slot (slot) + reply.invoke (0, 0, caps.copy ()) + Kernel::free_cap (caps) break case Device::DESTROY_USER: - Kernel::recv.reply.invoke () + unsigned slot = Kernel::Caps (arg).use () + unsigned physical = Kernel::my_receiver.get_protected (Kernel::Cap (slot, 0)).l + if physical == ~0: + kdebug ("unable to destroy framebuffer with wrong cap0\n") + Kernel::panic (0) + break + if descriptor.frame == physical && is_on: + lcd_clr_ena () + #ifdef NANONOTE + write_reg (BACKLIGHT1, 0x5e) + #endif + Kernel::Memory mem = Kernel::Cap (slot, 1) + for unsigned i = 0; i < pages; ++i: + mem.destroy (Kernel::Cap (slot, 2 + i)) + mem.destroy (arg) + Kernel::free_slot (slot) + reply.invoke () break case Device::USE: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - current_backlight = Kernel::my_receiver.get_protected (arg) + Kernel::Cap first = Kernel::Caps (arg).get (0) + unsigned physical = Kernel::my_receiver.get_protected (first).l + if physical == ~0: + kdebug ("unable to use framebuffer with wrong cap0\n") + Kernel::panic (0) + break + Kernel::free_cap (first) + bool was_unused = descriptor.frame == ~0 + descriptor.frame = physical + unsigned dptr = (unsigned)&descriptor + __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0") + if was_unused && is_on: + lcd_set_ena () + #ifdef NANONOTE: + write_reg (BACKLIGHT1, 0x5f) + #endif reply.invoke () - Kernel::free_cap (arg) - Kernel::free_cap (reply) break case Device::UNUSE: - Kernel::Cap reply = Kernel::get_reply () - Kernel::Cap arg = Kernel::get_arg () - if current_backlight.value () == Kernel::my_receiver.get_protected (arg).value (): - current_backlight = 0 + Kernel::Cap first = Kernel::Caps (arg).get (0) + unsigned physical = Kernel::my_receiver.get_protected (first).l + if physical == ~0: + kdebug ("unable to unuse framebuffer with wrong cap0\n") + Kernel::panic (0) + break + Kernel::free_cap (first) + if descriptor.frame == physical: + lcd_clr_ena () + #ifdef NANONOTE + write_reg (BACKLIGHT1, 0x5e) + #endif reply.invoke () - Kernel::free_cap (arg) - Kernel::free_cap (reply) break default: - log_char ('@') - break + Kernel::panic (0, "invalid operation for lcd device") + Kernel::free_cap (arg) + Kernel::free_cap (reply) break default: - log_char ('#') - log_num (Kernel::recv.protected_data) - log_char ('\n') + Kernel::panic (Kernel::recv.protected_data.l, "invalid operation for master lcd") break break case BACKLIGHT: - if current_backlight.value () != Kernel::recv.protected_data.value (): + if current_backlight != Kernel::recv.protected_data.l: log_char ('&') log_num (current_backlight) log_num (Kernel::recv.protected_data) @@ -400,22 +475,36 @@ Kernel::Num start (): Kernel::recv.reply.invoke (~0) break default: - log_char ('$') + Kernel::panic (0, "invalid operation for backlight") break break - case SET_EOF_CB: - Kernel::Cap reply = Kernel::get_reply () - if have_eof: - Kernel::free_cap (eof_cb) - else: - Kernel::register_interrupt (IRQ_LCD) - have_eof = true - eof_cb = Kernel::get_arg () - reply.invoke () - Kernel::free_cap (reply) + case LCD: + if descriptor.frame != Kernel::recv.protected_data.l: + kdebug ("invalid user requesting lcd\n") + Kernel::panic (0) + break + switch Kernel::recv.data[0].l: + case Display::SET_EOF_CB: + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () + if have_eof: + Kernel::free_cap (eof_cb) + kdebug ("replacing eof_cb\n") + Kernel::panic (0) + else: + lcd_clr_eof () + Kernel::register_interrupt (IRQ_LCD) + have_eof = true + eof_cb = arg + reply.invoke () + Kernel::free_cap (reply) + break + case Display::GET_INFO: + kdebug ("get_info isn't defined yet.\n") + Kernel::panic (0) + default: + Kernel::panic (0, "invalid operation for lcd") break default: - log_char ('~') - log_num (Kernel::recv.protected_data) - log_char ('\n') + Kernel::panic (0, "invalid master operation type for lcd") break diff --git a/source/#nanonote-gpio.ccp b/source/#nanonote-gpio.ccp index fc8dd8a..1d4de5f 100644 --- a/source/#nanonote-gpio.ccp +++ b/source/#nanonote-gpio.ccp @@ -170,6 +170,8 @@ class PowerButton: Kernel::Cap cb public: void scan (): + if !started: + return gpio_mask_irq (3, 1 << 29) bool s = gpio_get_port (3) & (1 << 29) if s != state: @@ -206,12 +208,12 @@ Kernel::Num start (): Kernel::my_parent.provide_device (pw.copy (), 1) Kernel::free_cap (dev) Kernel::free_cap (pw) + Kernel::my_parent.init_done () if kbd.scanning (): Kernel::my_receiver.set_alarm (SCAN_INTERVAL) - unsigned user (~0) + unsigned user (0), power_user (0) unsigned next_user (0) Kernel::register_interrupt (IRQ_GPIO3) - Kernel::my_parent.init_done () while true: Kernel::wait () switch Kernel::recv.protected_data.h: @@ -233,43 +235,15 @@ Kernel::Num start (): break case PWR: // Power button request. - switch Kernel::recv.data[0].l: - case Keyboard::SET_CB: - pwr.set_cb (Kernel::get_arg ()) - Kernel::recv.reply.invoke () - break - default: - kdebug ("power button invalid request\n") - break + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () + Device::host (PWR, power_user, reply, arg) break case KBD_DEV: // Keyboard device control request. - switch Kernel::recv.data[0].l: - case Device::CREATE_USER: - Kernel::Cap reply = Kernel::get_reply () - Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, KBD_DEV)) - reply.invoke (0, 0, cap.copy ()) - Kernel::free_cap (cap) - Kernel::free_cap (reply) - break - case Device::DESTROY_USER: - Kernel::recv.reply.invoke () - break - case Device::UNUSE: - kbd.inactive () - Kernel::recv.reply.invoke () - break - case Device::USE: - Kernel::Cap reply = Kernel::get_reply () - user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l - reply.invoke () - Kernel::free_cap (reply) - break - default: - kdebug ("gpio other dev:") - kdebug_num (Kernel::recv.data[0].l) - kdebug ("\n") - break + Kernel::Cap reply = Kernel::get_reply () + Kernel::Cap arg = Kernel::get_arg () + Device::host (KBD_DEV, user, reply, arg) break default: break @@ -277,7 +251,7 @@ Kernel::Num start (): case KBD_DEV: // Keyboard device user request. if Kernel::recv.protected_data.l != user: - kdebug ("invalid user requesting\n") + kdebug ("invalid user requesting keyboard\n") Kernel::recv.reply.invoke () break switch Kernel::recv.data[0].l: @@ -297,6 +271,24 @@ Kernel::Num start (): kdebug ("keyboard other\n") break break + case PWR: + if Kernel::recv.protected_data.l != power_user: + kdebug ("invalid user requesting power\n") + Kernel::recv.reply.invoke () + break + switch Kernel::recv.data[0].l: + case Keyboard::SET_CB: + Kernel::Cap reply = Kernel::get_reply () + pwr.set_cb (Kernel::get_arg ()) + reply.invoke () + Kernel::free_cap (reply) + break + default: + kdebug ("Power button invalid request\n") + kdebug_num (Kernel::recv.data[0].l) + kdebug ("\n") + break + break default: kdebug ("keyboard unknown num: ") kdebug_num (Kernel::recv.protected_data.h) diff --git a/source/ball.ccp b/source/ball.ccp new file mode 100644 index 0000000..af64c41 --- /dev/null +++ b/source/ball.ccp @@ -0,0 +1,49 @@ +#pypp 0 +#include +#include + +static unsigned *framebuffer +static int const r = 10 + +void ball (int x, int y, bool print): + static unsigned bg + static unsigned count + for int ty = y - r; ty < y + r; ++ty: + if ty < 0 || ty >= 240: + continue + for int tx = x - r; tx < x + r; ++tx: + if tx < 0 || tx >= 320: + continue + if (x - tx) * (x - tx) + (y - ty) * (y - ty) > r * r: + continue + framebuffer[ty * 320 + tx] = (print ? 0xffffff : bg) + if ++count >= 30: + bg += 0x010307 + count = 0 + +Kernel::Num start (): + Kernel::my_parent.init_done () + framebuffer = (unsigned *)0x15000 + Kernel::Caps caps = Kernel::my_parent.get_device () + Display display = caps.get (0) + int x = r, y = r, dx = 3, dy = 0 + Kernel::Cap eof = Kernel::my_receiver.create_capability (0) + while true: + display.set_eof_cb (eof) + Kernel::wait () + ball (x, y, false) + x += dx + y += dy + if y + r >= 240: + dy = -dy + y = 240 - r + if x - r < 0: + x = r + dx = -dx + if x + r >= 320: + x = 320 - r + dx = -dx + if y == 240 - r && dy == 0: + dy = -21 + ++dy + ball (x, y, true) diff --git a/source/crt0.ccp b/source/crt0.ccp index 3ae67fb..92f3868 100644 --- a/source/crt0.ccp +++ b/source/crt0.ccp @@ -46,7 +46,7 @@ namespace Kernel: for list *i = __first_free_cap; i; i = i->next: used[i - __cap_admin] = false ++num - kdebug_num (num, 1) + kdebug_num (num, 2) kdebug (":") for unsigned i = 0; i < 32; ++i: kdebug_char (used[i] ? '#' : '.') @@ -61,9 +61,12 @@ namespace Kernel: __first_free_slot = &__slot_admin[slot] void free_cap (Cap cap): - //kdebug ("free cap\n") + //kdebug ("free cap ") + //kdebug_num (cap.idx (), 2) + //kdebug ("\n") if cap.slot () != 0: kdebug ("trying to free capability from non-0 slot\n") + Kernel::panic (0) return list *l = &__cap_admin[cap.idx ()] l->prev = NULL @@ -77,6 +80,7 @@ namespace Kernel: if !__first_free_slot: // Out of slots... Probably best to raise an exception. For now, just return NO_SLOT. kdebug ("out of slots!\n") + Kernel::panic (0) return ~0 list *ret = __first_free_slot __first_free_slot = ret->next @@ -85,15 +89,18 @@ namespace Kernel: return ret - __slot_admin Cap alloc_cap (): - //kdebug ("alloc cap\n") + //kdebug ("alloc cap ") if !__first_free_cap: // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE kdebug ("out of capabilities!\n") + Kernel::panic (0) return Cap (0, CAP_NONE) list *ret = __first_free_cap __first_free_cap = ret->next if ret->next: ret->next->prev = NULL + //kdebug_num (ret - __cap_admin, 2) + //kdebug ("\n") return Cap (0, ret - __cap_admin) extern "C": @@ -103,7 +110,7 @@ extern "C": __slot_admin = slot_admin __cap_admin = cap_admin __first_free_slot = NULL - for unsigned i = 2; i < __slots; ++i: + for unsigned i = 1; i < __slots; ++i: Kernel::free_slot (i) __first_free_cap = NULL for unsigned i = 7; i < __caps; ++i: diff --git a/source/metronome.ccp b/source/metronome.ccp index c9fa6b2..f09cb87 100644 --- a/source/metronome.ccp +++ b/source/metronome.ccp @@ -20,6 +20,7 @@ #include "keys.hh" Kernel::Num start (): + Kernel::my_parent.init_done () Buzzer buzzer = Kernel::my_parent.get_device () Keyboard kbd = Kernel::my_parent.get_device () Kernel::Cap key = Kernel::my_receiver.create_capability (0) @@ -29,7 +30,6 @@ Kernel::Num start (): // Frequency of single pulses in hertz. unsigned freq = 1000 bool running (false) - Kernel::my_parent.init_done () while true: Kernel::wait () switch Kernel::recv.protected_data.l: