1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2025-01-30 19:01:05 +02:00

make things work with terminals

This commit is contained in:
Bas Wijnen 2010-01-24 21:34:24 +01:00
parent 5ef2934bf8
commit 06390fd2d1
23 changed files with 854 additions and 487 deletions

View File

@ -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)

163
alloc.ccp
View File

@ -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)

View File

@ -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:

View File

@ -20,9 +20,13 @@
#include "iris.hh"
#include <elf.h>
#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")

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ()

View File

@ -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)

View File

@ -22,7 +22,7 @@
#include "../kernel.hh"
#include <elf.h>
#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.

View File

@ -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 ()

View File

@ -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

View File

@ -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 ():

View File

@ -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"

122
panic.ccp
View File

@ -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):

View File

@ -60,9 +60,9 @@ Kernel::Num start ():
Device dev = Kernel::my_receiver.create_capability (BUZZER)
Kernel::my_parent.provide_device <Buzzer> (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:

View File

@ -270,6 +270,7 @@ Kernel::Num start ():
c = Kernel::my_receiver.create_capability (TOUCHPAD)
Kernel::my_parent.provide_device <Keyboard> (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 ()

View File

@ -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 <Setting> (backlight)
Kernel::my_parent.provide_device <Setting> (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> (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

View File

@ -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 <Keyboard> (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)

49
source/ball.ccp Normal file
View File

@ -0,0 +1,49 @@
#pypp 0
#include <iris.hh>
#include <devices.hh>
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 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)

View File

@ -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:

View File

@ -20,6 +20,7 @@
#include "keys.hh"
Kernel::Num start ():
Kernel::my_parent.init_done ()
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
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: