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

things are working

This commit is contained in:
Bas Wijnen 2009-07-25 00:54:12 +02:00
parent b7d9b1554c
commit df38266bb8
13 changed files with 393 additions and 220 deletions

135
alloc.ccp
View File

@ -18,6 +18,13 @@
#include "kernel.hh" #include "kernel.hh"
// Memory model used for kernel structure storage
// Each Memory object has several pointers, one for each type of objects it contains. These pointers are the start of double-linked lists.
// Each object also has a NEXT and PREV pointer, which point to the next and previous object in the same page. These pointers are 0 for the first (or last) object in a page. There is no pointer to the first object, it always starts at page_base + SIZE.
// The PREV/NEXT-list contains all objects in the page, including Free objects, in the order they appear in the page.
// The prev/next-lists contain only objects of one type, unsorted.
// All pointers are to the start of the object. There is a header of size SIZE before it, containing NEXT and PREV.
#define PREV(x) (((Object_base **)(x))[-2]) #define PREV(x) (((Object_base **)(x))[-2])
#define NEXT(x) (((Object_base **)(x))[-1]) #define NEXT(x) (((Object_base **)(x))[-1])
#define SIZE (2 * sizeof (Object_base *)) #define SIZE (2 * sizeof (Object_base *))
@ -37,75 +44,116 @@ void Memory::unuse (unsigned num):
for Memory *m = this; m; m = m->address_space: for Memory *m = this; m; m = m->address_space:
m->used -= 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)
// 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 *Memory::search_free (unsigned size, void **first): void *Memory::search_free (unsigned size, void **first):
Free *f Free *f
unsigned s = 0 unsigned s = 0
// Let's see if there already is a Free chunk which is large enough.
for f = frees; f; f = f->next: for f = frees; f; f = f->next:
if NEXT (f): if NEXT (f):
s = (unsigned)NEXT (f) - (unsigned)f s = (unsigned)NEXT (f) - (unsigned)f
else: else:
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK) + SIZE s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK) + SIZE
// s is now the size of the current free block, including SIZE.
// The requirement is to fit a block of size, plus its SIZE header.
if s >= size + SIZE: if s >= size + SIZE:
break break
if !f: if !f:
// No chunk was found; allocate a new page and add a chunk in it. It is always large enough.
unsigned p = palloc () unsigned p = palloc ()
if !p: if !p:
assert (false) dbg_log ("no free space: kernel allocation failed")
return NULL return NULL
f = (Free *)(p + SIZE) f = (Free *)(p + SIZE)
// Mark it as a Free object.
f->marker = ~0 f->marker = ~0
// Link it in the Free list.
f->next = frees f->next = frees
f->prev = NULL f->prev = NULL
frees = f frees = f
if f->next: if f->next:
f->next->prev = f f->next->prev = f
// There are no other objects in this page.
NEXT (f) = NULL NEXT (f) = NULL
PREV (f) = NULL PREV (f) = NULL
// The size of this block is the entire page.
s = PAGE_SIZE s = PAGE_SIZE
// We have a free block, possibly too large. // We have a free block, possibly too large. The block is linked in frees, and in the page.
if s >= size + sizeof (Free) + 2 * SIZE: if s >= size + sizeof (Free) + 2 * SIZE:
// Create the new object at the end and keep the Free. // Create the new object at the end and keep the Free.
Free *obj = (Free *)((unsigned)f + s - size - SIZE) // f is the start of the free block
// f + (s - SIZE) is the end of the free block, compensated for the header of the next block.
// f + (s - SIZE) - size is the address where the new block should start.
Free *obj = (Free *)((unsigned)f + (s - SIZE) - size)
// Link the new object in the page.
NEXT (obj) = NEXT (f) NEXT (obj) = NEXT (f)
if NEXT (obj): if NEXT (obj):
PREV (NEXT (obj)) = obj PREV (NEXT (obj)) = obj
PREV (obj) = f PREV (obj) = f
NEXT (f) = obj NEXT (f) = obj
// Set f to the new object, because it is used by that name later.
f = obj f = obj
else: else:
// The block was only just large enough: turn it into a new type. It is already linked into the page.
// Unlink it from the free list.
if f->prev: if f->prev:
f->prev->next = f->next f->prev->next = f->next
else: else:
frees = f->next frees = f->next
if f->next: if f->next:
f->next->prev = f->prev f->next->prev = f->prev
f->address_space = this // f is now a block which is linked in the page, but not in any list. Link it into first.
f->refs = NULL
f->next = (Free *)*first f->next = (Free *)*first
f->prev = NULL f->prev = NULL
if f->next: if f->next:
f->next->prev = f f->next->prev = f
*first = f *first = f
// Set common initial values.
f->address_space = this
f->refs = NULL
return f return f
void Memory::free_obj (Object_base *obj): // Free an object; it is still in its list, and it is still in the page list.
Free *self void Memory::free_obj (Object_base *obj, void **first):
// Merge with previous, if it exists and is a Free. Free *self = (Free *)obj
if PREV (obj) && PREV (obj)->is_free (): // Free it from its list.
self = (Free *)PREV (obj) if self->prev:
NEXT (self) = NEXT (obj) self->prev->next = self->next
if NEXT (obj):
PREV (NEXT (obj)) = self
else: else:
self = (Free *)obj *(Object_base **)first = self->next
if self->next:
self->next->prev = self->prev
// Merge with previous, if it exists and is a Free.
if PREV (self) && PREV (self)->is_free ():
self = (Free *)PREV (self)
// Remove the object from the page list.
NEXT (self) = NEXT (obj)
if NEXT (self):
PREV (NEXT (self)) = self
else:
// The previous object is not a Free, so create a new one.
// It is already linked in the page, but needs to be linked into the free list.
self->next = frees self->next = frees
self->prev = NULL self->prev = NULL
if self->next: if self->next:
self->next->prev = self self->next->prev = self
frees = self frees = self
// Mark it as a Free.
self->marker = ~0 self->marker = ~0
// Merge with next, if it exists and is a Free. // Merge with next, if it exists and is a Free.
if NEXT (self) && NEXT (self)->is_free (): if NEXT (self) && NEXT (self)->is_free ():
// Unlink the next from the frees list.
Free *n = (Free *)NEXT (self)
if n->prev:
n->prev->next = n->next
else:
frees = n->next
if n->next:
n->next->prev = n->prev
// Unlink the next from the page list.
NEXT (self) = NEXT (NEXT (self)) NEXT (self) = NEXT (NEXT (self))
if NEXT (self): if NEXT (self):
PREV (NEXT (self)) = self PREV (NEXT (self)) = self
@ -139,6 +187,7 @@ Thread *Memory::alloc_thread ():
ret->schedule_prev = NULL ret->schedule_prev = NULL
ret->schedule_next = NULL ret->schedule_next = NULL
ret->receivers = NULL ret->receivers = NULL
top_memory.alloc_capability (NULL, NULL, NULL, 0, &ret->exception)
return ret return ret
Message *Memory::alloc_message (Receiver *target): Message *Memory::alloc_message (Receiver *target):
@ -222,48 +271,26 @@ Memory *Memory::alloc_memory ():
return ret return ret
void Memory::free_page (Page *page): void Memory::free_page (Page *page):
if page->prev: if page->data.flags & PAGE_FLAG_PAYING:
page->prev->next = page->next
else:
pages = page->next
if page->next:
page->next->prev = page->prev
unuse () unuse ()
if page->data.frame: if page->data.frame:
pfree (page->data.frame) pfree (page->data.frame)
free_obj (page) free_obj (page, (void **)&pages)
void Memory::free_thread (Thread *thread): void Memory::free_thread (Thread *thread):
if thread->prev: thread->unrun ()
thread->prev->next = thread->next
else:
threads = thread->next
if thread->next:
thread->next->prev = thread->prev
// Unschedule.
if thread->schedule_prev:
thread->schedule_prev->schedule_next = thread->schedule_next
else if first_scheduled == thread:
first_scheduled = thread->schedule_next
if thread->schedule_next:
thread->schedule_next->schedule_prev = thread->schedule_prev
while thread->receivers: while thread->receivers:
thread->receivers->orphan () thread->receivers->orphan ()
free_obj (thread) thread->exception.invalidate ()
free_obj (thread, (void **)&threads)
void Memory::free_message (Receiver *owner, Message *message): void Memory::free_message (Receiver *owner, Message *message):
if message->prev: if !message->next:
message->prev->next = message->next
else:
owner->messages = message->next
if message->next:
message->next->prev = message->prev
else:
owner->last_message = message->prev owner->last_message = message->prev
for unsigned i = 0; i < 4; ++i: for unsigned i = 0; i < 4; ++i:
if message->capabilities[i]: if message->capabilities[i]:
free_capability (message->capabilities[i]) free_capability (message->capabilities[i])
free_obj (message) free_obj (message, (void **)&owner->messages)
void Memory::free_receiver (Receiver *receiver): void Memory::free_receiver (Receiver *receiver):
receiver->orphan () receiver->orphan ()
@ -271,7 +298,7 @@ void Memory::free_receiver (Receiver *receiver):
receiver->capabilities->invalidate () receiver->capabilities->invalidate ()
while receiver->messages: while receiver->messages:
free_message (receiver, receiver->messages) free_message (receiver, receiver->messages)
free_obj (receiver) free_obj (receiver, (void **)&receivers)
void Receiver::orphan (): void Receiver::orphan ():
if prev_owned: if prev_owned:
@ -293,7 +320,7 @@ void Receiver::own (Thread *o):
void Memory::free_capability (Capability *capability): void Memory::free_capability (Capability *capability):
capability->invalidate () capability->invalidate ()
free_obj (capability) free_obj (capability, (void **)&capabilities)
void Capability::invalidate (): void Capability::invalidate ():
if !target: if !target:
@ -328,23 +355,25 @@ void Memory::free_cappage (Cappage *p):
for unsigned i = 0; i < CAPPAGE_SIZE; ++i: for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
((Capability *)p->data.frame)[i].invalidate () ((Capability *)p->data.frame)[i].invalidate ()
zfree (p->data.frame) zfree (p->data.frame)
free_obj (p) free_obj (p, (void **)&cappages)
void Memory::free_memory (Memory *mem): void Memory::free_memory (Memory *mem):
if mem->prev:
mem->prev->next = mem->next
else:
memories = mem->next
if mem->next:
mem->next->prev = mem->prev
while mem->pages: while mem->pages:
free_page (mem->pages) free_page (mem->pages)
while mem->cappages:
free_cappage (mem->cappages)
while mem->threads: while mem->threads:
free_thread (mem->threads) free_thread (mem->threads)
while mem->memories: while mem->memories:
free_memory (mem->memories) free_memory (mem->memories)
while mem->receivers:
free_receiver (mem->receivers)
while mem->capabilities:
free_capability (mem->capabilities)
Memory_arch_free (mem) Memory_arch_free (mem)
free_obj (mem) if mem->frees:
panic (0, "kernel memory leak: memory still in use")
free_obj (mem, (void **)&memories)
void Page::forget (): void Page::forget ():
if data.share_prev || data.share_next: if data.share_prev || data.share_next:

View File

@ -20,6 +20,9 @@
#define ARCH #define ARCH
#include "arch.hh" #include "arch.hh"
// Interval between polls for keyboard (when keys are pressed) and battery/power (always) events
#define ALARM_INTERVAL (HZ / 10)
// GPIO pins for the devices (port.pin) // GPIO pins for the devices (port.pin)
// keyboard // keyboard
@ -111,14 +114,15 @@ class Keyboard:
for unsigned i = 0; i < NUM_COLS; ++i: for unsigned i = 0; i < NUM_COLS; ++i:
keys[i] = 0xff keys[i] = 0xff
scan ()
void scan (): void scan ():
// Set all columns to 0 when the become output. // Set all columns to 0 when they become output.
GPIO_GPDR (3) &= ~COL_MASK GPIO_GPDR (3) &= ~COL_MASK
bool key_pressed = false scanning = false
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 } int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
for unsigned col = 0; col < NUM_COLS; ++col: for unsigned col = 0; col < NUM_COLS; ++col:
GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col]) GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col])
udelay (100) //udelay (100)
unsigned data = GPIO_GPDR (0) & ROW_MASK unsigned data = GPIO_GPDR (0) & ROW_MASK
// Generate events. // Generate events.
for unsigned row = 0; row < 8; ++row: for unsigned row = 0; row < 8; ++row:
@ -129,45 +133,46 @@ class Keyboard:
event (KEYBOARD_EVENT, code) event (KEYBOARD_EVENT, code)
keys[col] = data keys[col] = data
if data != ROW_MASK: if data != ROW_MASK:
key_pressed = true
if key_pressed:
scanning = true scanning = true
scanning = true
if scanning:
GPIO_GPDIR (3) &= ~COL_MASK
else:
GPIO_GPDIR (3) |= COL_MASK
class Touchpad: class Touchpad:
unsigned old_state unsigned old_state
public: public:
enum buttons:
LEFT = 1 << 16
RIGHT = 1 << 13
void check_events (): void check_events ():
unsigned state = GPIO_GPDR (0) unsigned state = GPIO_GPDR (0)
if (state ^ old_state) & LEFT: if (state ^ old_state) & (1 << GPIO_TP_LEFT):
if state & LEFT: if state & (1 << GPIO_TP_LEFT):
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0)) gpio_irq_fall (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
event (TOUCHPAD_EVENT, 0) event (TOUCHPAD_EVENT, 0)
else: else:
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_RAISEDG << (2 * 0)) gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
event (TOUCHPAD_EVENT, 0x10000) event (TOUCHPAD_EVENT, 0x10000)
if (state ^ old_state) & RIGHT: if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
if state & RIGHT: if state & (1 << GPIO_TP_RIGHT):
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13)) gpio_irq_fall (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
event (TOUCHPAD_EVENT, 1) event (TOUCHPAD_EVENT, 1)
else: else:
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_RAISEDG << (2 * 13)) gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
event (TOUCHPAD_EVENT, 0x10001) event (TOUCHPAD_EVENT, 0x10001)
old_state = state old_state = state
Touchpad (): Touchpad ():
// Set pins to input with pull-ups. // Set pins to input with pull-ups.
GPIO_GPDIR (0) &= ~(LEFT | RIGHT) gpio_as_input (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
GPIO_GPPUR (0) |= LEFT | RIGHT gpio_as_input (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
// Enable interrupts. GPIO_GPPUR (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0)) // Set up interrupts.
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13)) gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
old_state = 0 old_state = 0
// See if they are already pressed. If so, the interrupt detection is changed. // See if they are already pressed. If so, the interrupt detection is changed.
check_events () check_events ()
// Now enable the interrupts. // Now enable the interrupts.
GPIO_GPIER (0) |= LEFT | RIGHT GPIO_GPIER (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
class Lockleds: class Lockleds:
// Note that num lock is in port 2. The others are in port 0. // Note that num lock is in port 2. The others are in port 0.
@ -176,23 +181,25 @@ class Lockleds:
enum { SCROLL = 1 << 9 } enum { SCROLL = 1 << 9 }
public: public:
Lockleds (): Lockleds ():
GPIO_GPDR (2) &= ~NUM gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
GPIO_GPDR (0) &= ~(SCROLL | CAPS) gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS)
GPIO_GPDIR (2) |= NUM gpio_as_output (GPIO_SCROLL_PORT, GPIO_SCROLL)
GPIO_GPDIR (0) |= CAPS | SCROLL GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
void set (unsigned state): void set (unsigned state):
if state & 4: if state & 4:
GPIO_GPDR (2) &= ~NUM GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
else: else:
GPIO_GPDR (2) |= NUM GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
if state & 2: if state & 2:
GPIO_GPDR (0) &= ~CAPS GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
else: else:
GPIO_GPDR (0) |= CAPS GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
if state & 1: if state & 1:
GPIO_GPDR (0) &= ~SCROLL GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
else: else:
GPIO_GPDR (0) |= SCROLL GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
class Power: class Power:
// Power out is in port 2, the rest in port 3. // Power out is in port 2, the rest in port 3.
@ -207,14 +214,14 @@ class Power:
GPIO_GPIER (0) &= ~0xff GPIO_GPIER (0) &= ~0xff
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY) GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
GPIO_GPPUR (3) &= ~(PWR_IN | BATTERY) GPIO_GPPUR (3) &= ~(PWR_IN | BATTERY)
udelay (100) //udelay (100)
unsigned state = GPIO_GPDR (3) unsigned state = GPIO_GPDR (3)
if (state ^ old_state) & PWR_IN: if (state ^ old_state) & PWR_IN:
event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000) event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000)
if (state ^ old_state) & BATTERY: if (state ^ old_state) & BATTERY:
if !(state & BATTERY): if !(state & BATTERY):
GPIO_GPPUR (3) |= BATTERY GPIO_GPPUR (3) |= BATTERY
udelay (100) //udelay (100)
if GPIO_GPDR (3) & BATTERY: if GPIO_GPDR (3) & BATTERY:
if !was_present: if !was_present:
event (BATTERY_EVENT, BATTERY_CHARGED) event (BATTERY_EVENT, BATTERY_CHARGED)
@ -228,7 +235,7 @@ class Power:
old_state = state old_state = state
GPIO_GPPUR (3) &= ~BATTERY GPIO_GPPUR (3) &= ~BATTERY
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY) GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
udelay (100) //udelay (100)
GPIO_GPIER (3) |= 0xff GPIO_GPIER (3) |= 0xff
Power (): Power ():
GPIO_GPDR (2) |= PWR_OUT GPIO_GPDR (2) |= PWR_OUT
@ -237,10 +244,16 @@ class Power:
old_state = BATTERY old_state = BATTERY
poll () poll ()
void poweroff (): void poweroff ():
GPIO_GPDR (2) &= ~PWR_OUT gpio_as_gpio (GPIO_PW_O_PORT, GPIO_PW_O)
GPIO_GPDIR (2) |= PWR_OUT gpio_as_output (GPIO_PW_O_PORT, GPIO_PW_O)
GPIO_GPDR (GPIO_PW_O) &= ~(1 << GPIO_PW_O)
while true: while true:
// Do nothing; wait until the device stops running. // Do nothing; wait until the device stops running.
void reboot ():
wdt_set_count (0xffffffff - 32)
wdt_start ()
while true:
// Do nothing; wait until the device reboots.
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc. // Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
class Pwm: class Pwm:
@ -263,14 +276,14 @@ class Pwm:
int main (): int main ():
schedule () schedule ()
*(unsigned *)~3 = 0
map_gpio () map_gpio ()
map_pwm0 () map_pwm0 ()
map_wdt ()
Keyboard kbd Keyboard kbd
Touchpad tp Touchpad tp
//Lockleds leds Lockleds leds
Power power Power power
Pwm pwm Pwm pwm
@ -287,7 +300,7 @@ int main ():
invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0) invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0)
invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1) invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1)
receiver_set_alarm (__my_receiver, HZ / 5) receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
while true: while true:
Message msg Message msg
wait (&msg) wait (&msg)
@ -296,17 +309,20 @@ int main ():
// Alarm. // Alarm.
if kbd.is_scanning (): if kbd.is_scanning ():
kbd.scan () kbd.scan ()
power.poll () //power.poll ()
receiver_set_alarm (__my_receiver, HZ / 5) receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
break break
case IRQ_GPIO0: case IRQ_GPIO0:
kdebug ("gpio interrupt")
unsigned irq = GPIO_GPFR (0) unsigned irq = GPIO_GPFR (0)
// Ack all. This works because they are all edge triggered. // Ack all. This works because they are all edge triggered.
GPIO_GPFR (0) = irq GPIO_GPFR (0) = irq
if irq & 0xff: if irq & 0xff:
kbd.scan () kbd.scan ()
if irq & (Touchpad::LEFT | Touchpad::RIGHT): if irq & ((1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)):
tp.check_events () tp.check_events ()
register_interrupt (IRQ_GPIO0)
break
case CAP_KEYBOARD: case CAP_KEYBOARD:
set_cb (KEYBOARD_EVENT, msg.cap[0]) set_cb (KEYBOARD_EVENT, msg.cap[0])
break break
@ -314,7 +330,10 @@ int main ():
set_cb (TOUCHPAD_EVENT, msg.cap[0]) set_cb (TOUCHPAD_EVENT, msg.cap[0])
break break
case CAP_POWEROFF: case CAP_POWEROFF:
if msg.data[0]:
power.poweroff () power.poweroff ()
else:
power.reboot ()
break break
case CAP_POWERBUTTON: case CAP_POWERBUTTON:
set_cb (POWERBUTTON_EVENT, msg.cap[0]) set_cb (POWERBUTTON_EVENT, msg.cap[0])
@ -323,7 +342,7 @@ int main ():
set_cb (BATTERY_EVENT, msg.cap[0]) set_cb (BATTERY_EVENT, msg.cap[0])
break break
case CAP_LOCKLEDS: case CAP_LOCKLEDS:
//leds.set (msg.data[0]) leds.set (msg.data[0])
break break
case CAP_PWM: case CAP_PWM:
pwm.set_backlight (msg.data[0]) pwm.set_backlight (msg.data[0])

View File

@ -76,14 +76,18 @@ int main ():
wait (&msg) wait (&msg)
switch msg.protected_data: switch msg.protected_data:
case KBD: case KBD:
kdebug ("keyboard event") kdebug ("keyboard event: ")
kdebug_num (msg.data[0])
kdebug_char ('\n')
break break
case TP: case TP:
kdebug ("touchpad event") if msg.data[0] == 0:
// Press left button.
invoke_00 (poweroff)
break break
case POWERBUTTON: case POWERBUTTON:
kdebug ("powerbutton event") kdebug ("powerbutton event\n")
break break
case BATTERY: case BATTERY:
kdebug ("battery event") kdebug ("battery event\n")
break break

View File

@ -18,6 +18,31 @@
#include "kernel.hh" #include "kernel.hh"
void Thread::raise (unsigned code, unsigned data):
dbg_log ("raise ")
dbg_log_num ((unsigned)current)
dbg_log_char ('/')
if code < NUM_EXCEPTION_CODES:
dbg_log (exception_name[code])
else:
dbg_log ("invalid code:")
dbg_log_num (code)
dbg_log_char ('/')
dbg_log_num (data)
dbg_log_char ('\n')
unrun ()
if !exception.target:
return
Capability::Context c
for unsigned i = 0; i < 4; ++i:
c.cap[i] = NULL
c.copy[i] = false
c.data[0] = code
c.data[1] = data
c.data[2] = 0
c.data[3] = 0
exception.invoke (&c)
// From user-provided, thus untrusted, data, find a capability. // From user-provided, thus untrusted, data, find a capability.
Capability *Memory::find_capability (unsigned code, bool *copy): Capability *Memory::find_capability (unsigned code, bool *copy):
*copy = code & 2 ? true : false *copy = code & 2 ? true : false
@ -27,7 +52,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
// Cappage capability // Cappage capability
unsigned num = (code & ~PAGE_MASK) >> 2 unsigned num = (code & ~PAGE_MASK) >> 2
if num >= CAPPAGE_SIZE: if num >= CAPPAGE_SIZE:
panic (0x15544551, "invalid cappage index") dbg_log_num ((unsigned)old_current)
dbg_log (": invalid cappage index ")
dbg_log_num (num)
dbg_log_char ('\n')
return NULL return NULL
unsigned page = code & PAGE_MASK unsigned page = code & PAGE_MASK
for Cappage *p = cappages; p; p = p->next: for Cappage *p = cappages; p; p = p->next:
@ -39,8 +67,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
for Capability *c = capabilities; c; c = c->next: for Capability *c = capabilities; c; c = c->next:
if c == target: if c == target:
return c return c
dbg_send (code) dbg_log_num ((unsigned)old_current)
panic (0xfffeee00, "invalid capability") dbg_log (": invalid capability ")
dbg_log_num (code)
dbg_log_char ('\n')
return NULL return NULL
// Try to deliver a message. // Try to deliver a message.
@ -56,7 +86,6 @@ bool Receiver::try_deliver ():
protected_only = false protected_only = false
break break
if !m: if !m:
//panic (0x32547688, "protected only")
return false return false
Capability::Context c Capability::Context c
for unsigned i = 0; i < 4; ++i: for unsigned i = 0; i < 4; ++i:
@ -64,7 +93,7 @@ bool Receiver::try_deliver ():
if m->capabilities[i]: if m->capabilities[i]:
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true) c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
if !c.cap[i]: if !c.cap[i]:
panic (0xffaaaaaa, "out of memory") owner->raise (ERR_OUT_OF_MEMORY, 0)
for unsigned j = 0; j < i; ++j: for unsigned j = 0; j < i; ++j:
owner->address_space->free_capability (c.cap[i]) owner->address_space->free_capability (c.cap[i])
return false return false
@ -85,15 +114,12 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
orig[i] = c->cap[i] orig[i] = c->cap[i]
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i]) c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
if !c->cap[i]: if !c->cap[i]:
panic (0xdddddddd, "out of memory") owner->raise (ERR_OUT_OF_MEMORY, 0)
return false
for unsigned j = 0; j < i; ++j: for unsigned j = 0; j < i; ++j:
owner->address_space->free_capability (c->cap[j]) owner->address_space->free_capability (c->cap[j])
c->cap[j] = orig[j] c->cap[j] = orig[j]
c->cap[i] = orig[i] c->cap[i] = orig[i]
tried_direct = true return false
break
if !tried_direct:
if protected_data == reply_protected_data: if protected_data == reply_protected_data:
protected_only = false protected_only = false
Thread_arch_receive (owner, protected_data, c) Thread_arch_receive (owner, protected_data, c)
@ -102,7 +128,8 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue. // The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
Message *msg = address_space->alloc_message (this) Message *msg = address_space->alloc_message (this)
if !msg: if !msg:
panic (0xbbbbbbbb, "out of memory") if owner:
owner->raise (ERR_OUT_OF_MEMORY, 0)
return false return false
msg->protected_data = protected_data msg->protected_data = protected_data
if protected_data == reply_protected_data: if protected_data == reply_protected_data:
@ -122,7 +149,8 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
else: else:
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i]) msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
if !msg->capabilities[i]: if !msg->capabilities[i]:
panic (0xcccccccc, "out of memory") if owner:
owner->raise (ERR_OUT_OF_MEMORY, 0)
for unsigned j = 0; j < i; ++j: for unsigned j = 0; j < i; ++j:
address_space->free_capability (msg->capabilities[j]) address_space->free_capability (msg->capabilities[j])
address_space->free_message (this, msg) address_space->free_message (this, msg)
@ -768,8 +796,10 @@ static void kernel_invoke (unsigned target, unsigned protected_data, Capability:
return return
if !((1 << c->data[0]) & target & REQUEST_MASK): if !((1 << c->data[0]) & target & REQUEST_MASK):
// You are not allowed to perform this operation. // You are not allowed to perform this operation.
dbg_send (1, 2) dbg_log ("operation not allowed: ")
dbg_send (c->data[0]) dbg_log_num (c->data[0])
dbg_log ("; target = ")
dbg_log_num (target)
return return
reply = c->cap[0] reply = c->cap[0]
if c->data[0] == CAP_DEGRADE: if c->data[0] == CAP_DEGRADE:

45
iris.h
View File

@ -36,6 +36,41 @@ extern "C" {
#define PAGE_SIZE (1 << PAGE_BITS) #define PAGE_SIZE (1 << PAGE_BITS)
#define PAGE_MASK (~(PAGE_SIZE - 1)) #define PAGE_MASK (~(PAGE_SIZE - 1))
enum Exception_code {
ERR_WRITE_DENIED,
ERR_UNMAPPED_READ,
ERR_UNMAPPED_WRITE,
ERR_INVALID_ADDRESS_READ,
ERR_INVALID_ADDRESS_WRITE,
ERR_RESERVED_INSTRUCTION,
ERR_COPROCESSOR_UNUSABLE,
ERR_OVERFLOW,
ERR_TRAP,
ERR_WATCHPOINT,
ERR_NO_PAGE_DIRECTORY,
ERR_NO_PAGE_TABLE,
ERR_OUT_OF_MEMORY,
NUM_EXCEPTION_CODES
};
#ifndef NDEBUG
static const char *exception_name[NUM_EXCEPTION_CODES] = {
"write denied",
"unmapped read",
"unmapped write",
"invalid address read",
"invalid address write",
"reserved instruction",
"coprocessor unusable",
"overflow",
"trap",
"watchpoint",
"no page directory",
"no page table",
"out of memory"
};
#endif
#define KERNEL_MASK 0xfff #define KERNEL_MASK 0xfff
#define CAPTYPE_MASK 0xe00 #define CAPTYPE_MASK 0xe00
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK) #define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
@ -801,7 +836,15 @@ static void cappage_set (Capability page, Capability cap, unsigned index)
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */ /* 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) #define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); kdebug_char ('\n'); } while (0) #define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); } while (0)
static void kdebug_num (unsigned n)
{
unsigned i;
const char *encode = "0123456789abcdef";
for (i = 0; i < 8; ++i)
kdebug_char (encode[(n >> (4 * (7 - i))) & 0xf]);
}
#endif #endif

View File

@ -60,21 +60,6 @@ bool Object_base::is_free ():
// Include architecture-specific parts. // Include architecture-specific parts.
#include "arch.hh" #include "arch.hh"
struct Thread : public Object <Thread>:
Receiver *receivers
unsigned pc, sp
Thread_arch arch
unsigned flags
Thread *schedule_prev, *schedule_next
Thread *exception
void raise (unsigned code)
void run ()
void unrun ()
void wait ()
void unwait ()
bool is_waiting ():
return flags & THREAD_FLAG_WAITING
struct Message : public Object <Message>: struct Message : public Object <Message>:
Capability *capabilities[4] Capability *capabilities[4]
unsigned data[4] unsigned data[4]
@ -93,6 +78,22 @@ struct Capability : public Object <Capability>:
void invoke (Context *c) void invoke (Context *c)
void invalidate () void invalidate ()
struct Thread : public Object <Thread>:
Receiver *receivers
unsigned pc, sp
Thread_arch arch
unsigned flags
Thread *schedule_prev, *schedule_next
// This is not a pointer, but a real Capability. That means that at capability destroy, no check is needed if it is used for an exception handler.
Capability exception
void raise (unsigned code, unsigned data)
void run ()
void unrun ()
void wait ()
void unwait ()
bool is_waiting ():
return flags & THREAD_FLAG_WAITING
struct Receiver : public Object <Receiver>: struct Receiver : public Object <Receiver>:
Thread *owner Thread *owner
Receiver *prev_owned, *next_owned Receiver *prev_owned, *next_owned
@ -167,20 +168,21 @@ struct Memory : public Object <Memory>:
void free_cappage (Cappage *page) void free_cappage (Cappage *page)
void free_memory (Memory *mem) void free_memory (Memory *mem)
void free_obj (Object_base *obj) void free_obj (Object_base *obj, void **first)
Capability *find_capability (unsigned code, bool *copy) Capability *find_capability (unsigned code, bool *copy)
// Functions which can be called from assembly must not be mangled. // Functions which can be called from assembly must not be mangled.
extern "C": extern "C":
// Panic. n is sent over caps led. message is currently ignored. // Panic. n is sent over caps led. message is currently ignored.
void panic (unsigned n, char const *message = "") void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
// Debug: send a message to the user.
void dbg_send (unsigned code, unsigned bits = 32)
EXTERN unsigned dbg_code EXTERN unsigned dbg_code
EXTERN Capability *dbg_cap EXTERN Capability *dbg_cap
void dbg_log_char (unsigned ch) void dbg_log_char (unsigned ch)
void dbg_log (char const *str) void dbg_log (char const *str)
void dbg_log_num (unsigned num)
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m))
/// Defined in schedule.ccp /// Defined in schedule.ccp
void schedule () void schedule ()

View File

@ -19,7 +19,7 @@ unsigned init_memory (unsigned mem):
unsigned phys_alloc (unsigned num): unsigned phys_alloc (unsigned num):
if free_begin + num * PAGE_SIZE > free_end: if free_begin + num * PAGE_SIZE > free_end:
panic (0xaaaaaaaa, "out of memory") dbg_log ("memory allocation failed\n")
return 0 return 0
unsigned ret = free_begin unsigned ret = free_begin
free_begin += num * PAGE_SIZE free_begin += num * PAGE_SIZE
@ -54,7 +54,7 @@ unsigned phys_alloc (unsigned num):
choice = p choice = p
if !choice: if !choice:
// TODO: reorganizing may work to allow allocation. // TODO: reorganizing may work to allow allocation.
panic (0x01100223, "out of large enough memory") dbg_log ("range memory allocation failed")
return 0 return 0
if choice->num == num: if choice->num == num:
if choice->prev: if choice->prev:
@ -132,7 +132,7 @@ void raw_pfree (unsigned page):
unsigned Memory::zalloc (): unsigned Memory::zalloc ():
if !use (): if !use ():
panic (0x4536928, "no memory due to limit") dbg_log ("limit reached: allocation not allowed")
return NULL return NULL
return raw_zalloc () return raw_zalloc ()

View File

@ -157,16 +157,10 @@ static arch_page *alloc_page (Memory *mem, arch_page_table *t):
static void free_page_table (arch_page_table *t, unsigned idx): static void free_page_table (arch_page_table *t, unsigned idx):
Memory *mem = t->address_space Memory *mem = t->address_space
if t->next:
t->next->prev = t->prev
if t->prev:
t->prev->next = t->next
else:
mem->arch.first_page_table = t->next
mem->zfree ((unsigned)mem->arch.directory[idx]) mem->zfree ((unsigned)mem->arch.directory[idx])
mem->arch.directory[idx] = NULL mem->arch.directory[idx] = NULL
mem->arch.shadow[idx] = NULL mem->arch.shadow[idx] = NULL
mem->free_obj (t) mem->free_obj (t, (void **)&mem->arch.first_page_table)
if !mem->arch.first_page_table: if !mem->arch.first_page_table:
mem->zfree ((unsigned)mem->arch.directory) mem->zfree ((unsigned)mem->arch.directory)
mem->zfree ((unsigned)mem->arch.shadow) mem->zfree ((unsigned)mem->arch.shadow)
@ -186,12 +180,6 @@ static void tlb_reset (unsigned address, unsigned asid, unsigned value):
__asm__ volatile ("tlbwi") __asm__ volatile ("tlbwi")
static void free_page (arch_page_table *t, arch_page *p): static void free_page (arch_page_table *t, arch_page *p):
if p->next:
p->next->prev = p->prev
if p->prev:
p->prev->next = p->next
else:
t->first_page = p->next
if p->prev_mapped: if p->prev_mapped:
p->prev_mapped->next_mapped = p->next_mapped p->prev_mapped->next_mapped = p->next_mapped
else: else:
@ -200,7 +188,7 @@ static void free_page (arch_page_table *t, arch_page *p):
p->next_mapped->prev_mapped = p->prev_mapped p->next_mapped->prev_mapped = p->prev_mapped
tlb_reset (p->mapping, p->address_space->arch.asid, 0) tlb_reset (p->mapping, p->address_space->arch.asid, 0)
unsigned idx = p->mapping >> 21 unsigned idx = p->mapping >> 21
p->address_space->free_obj (p) p->address_space->free_obj (p, (void **)&t->first_page)
if !t->first_page: if !t->first_page:
free_page_table (t, idx) free_page_table (t, idx)

View File

@ -274,6 +274,12 @@ void init (unsigned mem):
gpio_as_ssi() gpio_as_ssi()
gpio_as_msc () gpio_as_msc ()
gpio_as_gpio (GPIO_CAPS_PORT, GPIO_CAPS)
gpio_as_gpio (GPIO_SCROLL_PORT, GPIO_SCROLL)
gpio_as_gpio (GPIO_NUM_PORT, GPIO_NUM)
gpio_as_gpio (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
gpio_as_gpio (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
// Start the operating system timer, and set it to give an interrupt immediately. // Start the operating system timer, and set it to give an interrupt immediately.
// This is better, because the kernel starts with jumping into the idle task and // This is better, because the kernel starts with jumping into the idle task and
// waiting for the first interrupt. // waiting for the first interrupt.

View File

@ -30,7 +30,7 @@ static void handle_exit ():
if !current: if !current:
current = &idle current = &idle
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING: if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
panic (0x99338844, "non-scheduled thread running") panic (current->flags, "non-scheduled thread running")
if !current: if !current:
current = &idle current = &idle
if old_current == current: if old_current == current:
@ -61,22 +61,20 @@ static void handle_exit ():
/// when k0 or k1 is not 0, or when an error occurs. /// when k0 or k1 is not 0, or when an error occurs.
/// Otherwise, the ultra-fast code in entry.S is used. /// Otherwise, the ultra-fast code in entry.S is used.
Thread *tlb_refill (): Thread *tlb_refill ():
//panic (0x88776655, "TLB refill")
old_current = current old_current = current
if !directory: if !directory:
panic (0x44449999, "No directory") unsigned addr
cp0_get (CP0_BAD_V_ADDR, addr)
current->raise (ERR_NO_PAGE_DIRECTORY, addr)
handle_exit () handle_exit ()
return current return current
unsigned EntryHi unsigned EntryHi
cp0_get (CP0_ENTRY_HI, EntryHi) cp0_get (CP0_ENTRY_HI, EntryHi)
unsigned *t = directory[EntryHi >> 21] unsigned *t = directory[EntryHi >> 21]
if !t: if !t:
unsigned a unsigned addr
cp0_get (CP0_EPC, a) cp0_get (CP0_BAD_V_ADDR, addr)
//dbg_send (a) current->raise (ERR_NO_PAGE_TABLE, addr)
cp0_get (CP0_BAD_V_ADDR, a)
//dbg_send (a)
panic (0x99992222, "No page table")
else: else:
// - 2 instead of - 1 means reset bit 0 // - 2 instead of - 1 means reset bit 0
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2) unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
@ -88,7 +86,6 @@ Thread *tlb_refill ():
/// An interrupt which is not an exception has occurred. /// An interrupt which is not an exception has occurred.
Thread *interrupt (): Thread *interrupt ():
//panic (0x88877722, "Interrupt")
old_current = current old_current = current
unsigned ipr = INTC_IPR unsigned ipr = INTC_IPR
for unsigned i = 0; i < 32; ++i: for unsigned i = 0; i < 32; ++i:
@ -134,7 +131,6 @@ static void arch_invoke ():
if wait: if wait:
old_current->wait () old_current->wait ()
if !target: if !target:
//dbg_send (0, 0)
// There must be no action here. // There must be no action here.
else: else:
Capability::Context c Capability::Context c
@ -164,55 +160,45 @@ Thread *exception ():
switch (cause >> 2) & 0x1f: switch (cause >> 2) & 0x1f:
case 0: case 0:
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1. // Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
panic (0x01223344, "Interrupt on exception vector.") panic (0, "Interrupt on exception vector.")
break break
case 1: case 1:
// TLB modification. // TLB modification.
panic (0x11223344, "TLB modification.") unsigned addr
cp0_get (CP0_BAD_V_ADDR, addr)
current->raise (ERR_WRITE_DENIED, addr)
break break
case 2: case 2:
// TLB load or instruction fetch. // TLB load or instruction fetch.
unsigned a unsigned addr
cp0_get (CP0_EPC, a) cp0_get (CP0_BAD_V_ADDR, addr)
//dbg_send (a) current->raise (ERR_UNMAPPED_READ, addr)
panic (0x21223344, "TLB load or instruction fetch.")
break break
case 3: case 3:
// TLB store. // TLB store.
unsigned a unsigned addr
cp0_get (CP0_EPC, a) cp0_get (CP0_BAD_V_ADDR, addr)
//dbg_send (a) current->raise (ERR_UNMAPPED_WRITE, addr)
cp0_get (CP0_BAD_V_ADDR, a)
//dbg_send (a)
panic (0x31223344, "TLB store.")
break break
case 4: case 4:
// Address error load or instruction fetch. // Address error load or instruction fetch.
unsigned a unsigned addr
cp0_get (CP0_EPC, a) cp0_get (CP0_BAD_V_ADDR, addr)
//dbg_send (a) current->raise (ERR_INVALID_ADDRESS_READ, addr)
cp0_get (CP0_BAD_V_ADDR, a)
//dbg_send (a)
panic (0x41223344, "Address error load or instruction fetch.")
break break
case 5: case 5:
// Address error store. // Address error store.
//dbg_send (current->arch.v1, 4) unsigned addr
//unsigned a cp0_get (CP0_BAD_V_ADDR, addr)
//cp0_get (CP0_EPC, a) current->raise (ERR_INVALID_ADDRESS_WRITE, addr)
//dbg_send (*(unsigned *)(a & ~3), 32)
//dbg_send (a, 32)
//cp0_get (CP0_BAD_V_ADDR, a)
//dbg_send (a, 32)
panic (0x51223344, "Address error store.")
break break
case 6: case 6:
// Bus error instruction fetch. // Bus error instruction fetch.
panic (0x61223344, "Bus error instruction fetch.") panic (0, "Bus error instruction fetch.")
break break
case 7: case 7:
// Bus error load or store. // Bus error load or store.
panic (0x71223344, "Bus error load or store.") panic (0, "Bus error load or store.")
break break
case 8: case 8:
// Syscall. // Syscall.
@ -221,37 +207,40 @@ Thread *exception ():
break break
case 9: case 9:
// Breakpoint. // Breakpoint.
//panic (0x91223344, "Breakpoint.") #if 0
current->raise (ERR_BREAKPOINT, 0)
#else
current->pc += 4 current->pc += 4
if current->arch.a0: if current->arch.a0:
if dbg_cap: if dbg_cap:
panic (0x34259380, "Break instruction while log capability was already set") panic (0, "Break instruction while log capability was already set")
break break
bool dummy bool dummy
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy) dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
if !dbg_cap: if !dbg_cap:
panic (0x06111129, "no log capability provided") panic (0, "no log capability provided")
break break
break break
if dbg_cap: if dbg_cap:
dbg_log_char (current->arch.a1) dbg_log_char (current->arch.a1)
break break
break break
#endif
case 10: case 10:
// Reserved instruction. // Reserved instruction.
panic (0xa1223344, "Reserved instruction.") current->raise (ERR_RESERVED_INSTRUCTION, 0)
break break
case 11: case 11:
// Coprocessor unusable. // Coprocessor unusable.
panic (0xb1223344, "Coprocessor unusable.") current->raise (ERR_COPROCESSOR_UNUSABLE, 0)
break break
case 12: case 12:
// Arithmetic overflow. // Arithmetic overflow.
panic (0xc1223344, "Arithmetic overflow.") current->raise (ERR_OVERFLOW, 0)
break break
case 13: case 13:
// Trap. // Trap.
panic (0xd1223344, "Trap.") current->raise (ERR_TRAP, 0)
break break
case 15: case 15:
// Floating point exception. // Floating point exception.
@ -259,7 +248,7 @@ Thread *exception ():
break break
case 23: case 23:
// Reference to WatchHi/WatchLo address. // Reference to WatchHi/WatchLo address.
panic (0xf1223344, "Reference to WatchHi/WatchLo address.") current->raise (ERR_WATCHPOINT, 0)
break break
case 24: case 24:
// Machine check. // Machine check.

View File

@ -2837,6 +2837,66 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
#define GPIO_CHARG_STAT 29 #define GPIO_CHARG_STAT 29
#define GPIO_TS_PENIRQ_PORT 2 #define GPIO_TS_PENIRQ_PORT 2
#define GPIO_TS_PENIRQ 4 #define GPIO_TS_PENIRQ 4
#define GPIO_CAPS_PORT 0
#define GPIO_CAPS 27
#define GPIO_SCROLL_PORT 0
#define GPIO_SCROLL 9
#define GPIO_NUM_PORT 2
#define GPIO_NUM 22
#define GPIO_TP_LEFT_PORT 0
#define GPIO_TP_LEFT 16
#define GPIO_TP_RIGHT_PORT 0
#define GPIO_TP_RIGHT 13
#define GPIO_HALF(x) (((x) & 0xf) << 1)
static __inline__ void gpio_as_gpio (unsigned port, unsigned pin):
unsigned mask = 3 << GPIO_HALF (pin)
if pin < 16:
GPIO_GPALR (port) &= ~mask
else:
GPIO_GPAUR (port) &= ~mask
static __inline__ void gpio_as_input (unsigned port, unsigned pin):
#if 0
unsigned mask = 3 << GPIO_HALF (pin)
if pin < 16:
GPIO_GPIDLR (port) &= ~mask
else:
GPIO_GPIDUR (port) &= ~mask
#else
GPIO_GPDIR (port) &= ~(1 << pin)
#endif
static __inline__ void gpio_as_output (unsigned port, unsigned pin):
#if 0
unsigned half = 1 << GPIO_HALF (pin)
if pin < 16:
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | half
else:
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | half
#else
GPIO_GPDIR (port) |= 1 << pin
#endif
static __inline__ void gpio_irq (unsigned port, unsigned pin, unsigned how):
unsigned half = 1 << GPIO_HALF (pin)
if pin < 16:
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | (how * half)
else:
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | (how * half)
static __inline__ void gpio_irq_low (unsigned port, unsigned pin):
gpio_irq (port, pin, GPIO_IRQ_LOLEVEL)
static __inline__ void gpio_irq_high (unsigned port, unsigned pin):
gpio_irq (port, pin, GPIO_IRQ_HILEVEL)
static __inline__ void gpio_irq_fall (unsigned port, unsigned pin):
gpio_irq (port, pin, GPIO_IRQ_FALLEDG)
static __inline__ void gpio_irq_rise (unsigned port, unsigned pin):
gpio_irq (port, pin, GPIO_IRQ_RAISEDG)
/* Init the alternate function pins */ /* Init the alternate function pins */

View File

@ -36,20 +36,13 @@ void dbg_log (char const *str):
while *str: while *str:
dbg_log_char (*str++) dbg_log_char (*str++)
void dbg_send (unsigned code, unsigned bits): void dbg_log_num (unsigned num):
if bits > 32:
bits = 32
char const *encode = "0123456789abcdef" char const *encode = "0123456789abcdef"
dbg_log_char ('[')
dbg_log_char (encode[(bits >> 4) & 0xf])
dbg_log_char (encode[bits & 0xf])
dbg_log_char (':')
for unsigned i = 0; i < 8; ++i: for unsigned i = 0; i < 8; ++i:
dbg_log_char (encode[(code >> (4 * (7 - i))) & 0xf]) dbg_log_char (encode[(num >> (4 * (7 - i))) & 0xf])
dbg_log_char (']')
return return
void panic (unsigned n, char const *message): void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
Thread *who = current Thread *who = current
// Stop all threads. // Stop all threads.
while first_scheduled: while first_scheduled:
@ -64,8 +57,18 @@ void panic (unsigned n, char const *message):
if dbg_cap && dbg_cap->target->owner: if dbg_cap && dbg_cap->target->owner:
dbg_cap->target->owner->run () dbg_cap->target->owner->run ()
// Use the (now running) log thread to display the message. // Use the (now running) log thread to display the message.
dbg_log ("Panic: ") dbg_log ("Panic: current = ")
dbg_send (n) dbg_log_num ((unsigned)who)
if who:
dbg_log_char ('@')
dbg_log_num ((unsigned)who->pc)
dbg_log ("; ")
dbg_log (name)
dbg_log_char (':')
dbg_log_num (line)
dbg_log (": ")
dbg_log (message) dbg_log (message)
dbg_log_char ('/')
dbg_log_num (n)
dbg_log_char ('\n') dbg_log_char ('\n')
// If no log capability is registered, the machine just hangs. // If no log capability is registered, the machine just hangs.

View File

@ -71,7 +71,7 @@ static void alarm_tick (Receiver *recv):
first_alarm = recv->next_alarm first_alarm = recv->next_alarm
if recv->next_alarm: if recv->next_alarm:
recv->next_alarm->prev_alarm = recv->prev_alarm recv->next_alarm->prev_alarm = recv->prev_alarm
return // Fall through to let alarm_count be ~0. This is required, because it is the indicator for no running alarm.
--recv->alarm_count --recv->alarm_count
void Thread::wait (): void Thread::wait ():