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

new stuff almost working

This commit is contained in:
Bas Wijnen 2009-08-24 21:02:35 +02:00
parent ebdc68a9d8
commit 418f6c6594
18 changed files with 651 additions and 495 deletions

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Define some variables. # Define some variables.
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS) CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc $(ARCH_CXXFLAGS) -ggdb3
CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS) CPPFLAGS = -O5 -fno-inline $(ARCH_CPPFLAGS)
CC = $(CROSS)gcc CC = $(CROSS)gcc
LD = $(CROSS)ld LD = $(CROSS)ld

View File

@ -120,7 +120,7 @@ void *kMemory::search_free (unsigned size, void **first):
void kMemory::free_obj (kObject *obj, kPointer *first): void kMemory::free_obj (kObject *obj, kPointer *first):
kFree *self = (kFree *)obj kFree *self = (kFree *)obj
// Invalidate references. // Invalidate references.
while self->refs: while self->refs.valid ():
self->refs->invalidate () self->refs->invalidate ()
// Free it from its list. // Free it from its list.
if self->prev: if self->prev:
@ -216,7 +216,7 @@ kReceiver *kMemory::alloc_receiver ():
ret->last_message = NULL ret->last_message = NULL
ret->reply_protected_data = ~0 ret->reply_protected_data = ~0
ret->protected_only = false ret->protected_only = false
ret->queue_limit = 0 ret->queue_limit = ~0
return ret return ret
kCaps *kMemory::alloc_caps (unsigned size): kCaps *kMemory::alloc_caps (unsigned size):
@ -249,7 +249,7 @@ void kCaps::set (unsigned index, kReceiver *target, Num pdata, kCapRef parent, k
caps[index].parent = parent caps[index].parent = parent
caps[index].children.reset () caps[index].children.reset ()
caps[index].sibling_prev.reset () caps[index].sibling_prev.reset ()
if parent: if parent.valid ():
caps[index].sibling_next = parent->children caps[index].sibling_next = parent->children
parent->children = kCapRef (this, index) parent->children = kCapRef (this, index)
else: else:
@ -258,12 +258,12 @@ void kCaps::set (unsigned index, kReceiver *target, Num pdata, kCapRef parent, k
*parent_ptr = kCapRef (this, index) *parent_ptr = kCapRef (this, index)
else: else:
caps[index].sibling_next.reset () caps[index].sibling_next.reset ()
if caps[index].sibling_next: if caps[index].sibling_next.valid ():
caps[index].sibling_next->sibling_prev = kCapRef (this, index) caps[index].sibling_next->sibling_prev = kCapRef (this, index)
void kCaps::clone (unsigned index, kCapRef source, bool copy): void kCaps::clone (unsigned index, kCapRef source, bool copy):
if copy: if copy:
if source->parent: if source->parent.valid ():
set (index, source->target, source->cap_protected, source->parent) set (index, source->target, source->cap_protected, source->parent)
else if (unsigned)source->target & ~KERNEL_MASK: else if (unsigned)source->target & ~KERNEL_MASK:
set (index, source->target, source->cap_protected, kCapRef (), &source->target->capabilities) set (index, source->target, source->cap_protected, kCapRef (), &source->target->capabilities)
@ -292,7 +292,7 @@ void kMemory::free_message (kReceiver *owner, kMessage *message):
void kMemory::free_receiver (kReceiver *receiver): void kMemory::free_receiver (kReceiver *receiver):
receiver->orphan () receiver->orphan ()
while receiver->capabilities: while receiver->capabilities.valid ():
receiver->capabilities->invalidate () receiver->capabilities->invalidate ()
while receiver->messages: while receiver->messages:
free_message (receiver, receiver->messages) free_message (receiver, receiver->messages)
@ -319,20 +319,20 @@ void kReceiver::own (kThread *o):
void kCapability::invalidate (): void kCapability::invalidate ():
if !target: if !target:
return return
if sibling_prev: if sibling_prev.valid ():
sibling_prev->sibling_next = sibling_next sibling_prev->sibling_next = sibling_next
else if (unsigned)target & ~KERNEL_MASK: else if (unsigned)target & ~KERNEL_MASK:
target->capabilities = sibling_next target->capabilities = sibling_next
else: else:
((kObject *)cap_protected.l)->refs = sibling_next ((kObject *)cap_protected.l)->refs = sibling_next
if sibling_next: if sibling_next.valid ():
sibling_next->sibling_prev = sibling_prev sibling_next->sibling_prev = sibling_prev
parent.reset () parent.reset ()
sibling_prev.reset () sibling_prev.reset ()
sibling_next.reset () sibling_next.reset ()
kCapability *c = this kCapability *c = this
while c: while c:
while c->children: while c->children.valid ():
c = c->children.deref () c = c->children.deref ()
kCapability *next = c->sibling_next.deref () kCapability *next = c->sibling_next.deref ()
if !next: if !next:

View File

@ -31,10 +31,8 @@ static list *__first_free_slot, *__first_free_cap
Receiver __my_receiver Receiver __my_receiver
Thread __my_thread Thread __my_thread
Memory __my_memory Memory __my_memory
Caps __my_caps
Cap __my_call Cap __my_call
Cap __my_parent Cap __my_parent
Caps __tmp_caps
void free_slot (unsigned slot): void free_slot (unsigned slot):
__slot_admin[slot].prev = NULL __slot_admin[slot].prev = NULL
@ -59,16 +57,17 @@ unsigned alloc_slot ():
__first_free_slot = ret->next __first_free_slot = ret->next
if ret->next: if ret->next:
ret->next->prev = NULL ret->next->prev = NULL
return ret - __slot_admin
unsigned alloc_cap (): unsigned alloc_cap ():
if !__first_free_cap: if !__first_free_cap:
// Out of caps... Probably best to raise an exception. For now, just return NO_SLOT. // Out of caps... Probably best to raise an exception. For now, just return NO_CAPABILITY.
return ~0 return ~0
list *ret = __first_free_cap list *ret = __first_free_cap
__first_free_cap = ret->next __first_free_cap = ret->next
if ret->next: if ret->next:
ret->next->prev = NULL ret->next->prev = NULL
return ret - __slot_admin return ret - __cap_admin
extern "C": extern "C":
void __main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin): void __main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
@ -77,7 +76,7 @@ extern "C":
__slot_admin = slot_admin __slot_admin = slot_admin
__cap_admin = cap_admin __cap_admin = cap_admin
__first_free_slot = NULL __first_free_slot = NULL
for unsigned i = 1; i < __slots; ++i: for unsigned i = 2; i < __slots; ++i:
free_slot (i) free_slot (i)
__first_free_cap = NULL __first_free_cap = NULL
for unsigned i = 7; i < __caps; ++i: for unsigned i = 7; i < __caps; ++i:
@ -85,10 +84,8 @@ extern "C":
__my_receiver = Cap (0, __receiver_num) __my_receiver = Cap (0, __receiver_num)
__my_thread = Cap (0, __thread_num) __my_thread = Cap (0, __thread_num)
__my_memory = Cap (0, __memory_num) __my_memory = Cap (0, __memory_num)
__my_caps = Cap (0, __caps_num)
__my_call = Cap (0, __call_num) __my_call = Cap (0, __call_num)
__my_parent = Cap (0, __parent_num) __my_parent = Cap (0, __parent_num)
__tmp_caps = Cap (0, __tmp_num)
Num ret = start () Num ret = start ()
__my_parent.invoke (~0, ret) __my_parent.invoke (~0, ret)
__my_memory.destroy (__my_thread) __my_memory.destroy (__my_thread)

View File

@ -48,10 +48,11 @@ struct Keyboard : public Cap:
RELEASE = 1 << 31 RELEASE = 1 << 31
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events. // Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events.
void set_cb (Cap cb): void set_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | SET_CB) ocall (cb, CAP_MASTER_DIRECT | SET_CB)
// Get a list of keys on this keyboard. The key codes start at zero with no gaps. // Get a list of keys on this keyboard. The key codes start at zero with no gaps.
void get_keys (List <String> ret): List <String> get_keys (List <String> ret = Cap (0, alloc_cap ())):
call (ret, CAP_MASTER_DIRECT | GET_KEYS) icall (ret, CAP_MASTER_DIRECT | GET_KEYS)
return ret
// Display interface. // Display interface.
struct Display : public Cap: struct Display : public Cap:
@ -64,18 +65,18 @@ struct Display : public Cap:
// Register an end-of-frame callback. // 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. // At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
void set_eof_cb (Cap cb): void set_eof_cb (Cap cb):
invoke (cb, CAP_MASTER_DIRECT | EOF_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. // 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 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 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. // The returned number is the physical address of the framebuffer. It can be used with display_use_framebuffer.
unsigned create_framebuffer (Caps pages, unsigned w = 0, unsigned h = 0, unsigned mode = 0): unsigned create_framebuffer (Caps pages, unsigned w = 0, unsigned h = 0, unsigned mode = 0):
return call (pages, Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Num ((w << 16) | h, mode)).l return icall (pages, Num (CAP_MASTER_DIRECT | CREATE_FB, 0), Num ((w << 16) | h, mode)).l
// Use a framebuffer. The address must have been returned from display_create_framebuffer. // 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. // 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. // unuse_cb is called the next time this operation is requested for this display.
void use_framebuffer (unsigned addr, Cap unuse_cb = Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0): void use_framebuffer (unsigned addr, Cap unuse_cb = Cap (), unsigned w = 0, unsigned h = 0, unsigned mode = 0):
invoke (unuse_cb, Num (CAP_MASTER_DIRECT | USE_FB, addr), Num ((w << 16) | h, mode)) ocall (unuse_cb, Num (CAP_MASTER_DIRECT | USE_FB, addr), Num ((w << 16) | h, mode))
// Get information about the display. // Get information about the display.
void get_info (): void get_info ():
// TODO: Interface is to be designed. // TODO: Interface is to be designed.
@ -93,13 +94,13 @@ struct File : public Cap:
MAP_HANDLE MAP_HANDLE
// Get information about the file. // Get information about the file.
Num get_info (unsigned type, Caps ret = Cap ()): Num get_info (unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | INFO, type)) return icall (ret, Num (CAP_MASTER_DIRECT | INFO, type))
// Close a file. If this is a directory, it implicitly closes all files opened from it. // Close a file. If this is a directory, it implicitly closes all files opened from it.
void close (): void close ():
invoke (CAP_MASTER_DIRECT | CLOSE) call (CAP_MASTER_DIRECT | CLOSE)
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle. // Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
File map_handle (File ret): File map_handle (File ret):
call (ret, CAP_MASTER_DIRECT | MAP_HANDLE) icall (ret, CAP_MASTER_DIRECT | MAP_HANDLE)
// Directory interface. // Directory interface.
struct Directory : public File: struct Directory : public File:
@ -116,19 +117,19 @@ struct Directory : public File:
return call (CAP_MASTER_DIRECT | GET_SIZE) return call (CAP_MASTER_DIRECT | GET_SIZE)
// Get the filename. The return value is the size of the string, the page is filled with the string itself. // Get the filename. The return value is the size of the string, the page is filled with the string itself.
void get_name (Num idx, String target): void get_name (Num idx, String target):
call (target, CAP_MASTER_DIRECT | GET_NAME, idx) icall (target, CAP_MASTER_DIRECT | GET_NAME, idx)
// Get the file. // Get the file.
void get_file (Num idx, File ret): void get_file (Num idx, File ret):
call (ret, CAP_MASTER_DIRECT | GET_FILE, idx) icall (ret, CAP_MASTER_DIRECT | GET_FILE, idx)
// Get file info. This returns the same information as file_get_info, without opening the file. // Get file info. This returns the same information as file_get_info, without opening the file.
Num get_file_info (Num idx, unsigned type, Caps ret = Cap ()): Num get_file_info (Num idx, unsigned type, Caps ret = Cap ()):
return call (ret, Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx) return icall (ret, Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
// Create a new file. After this, any index may map to a different file. // Create a new file. After this, any index may map to a different file.
void create_file (String name, File ret): void create_file (String name, File ret):
call (ret, CAP_MASTER_DIRECT | CREATE_FILE) icall (ret, CAP_MASTER_DIRECT | CREATE_FILE)
// Delete a file. After this, any index may map to a different file. // Delete a file. After this, any index may map to a different file.
void delete_file (Num idx): void delete_file (Num idx):
invoke (CAP_MASTER_DIRECT | DELETE_FILE, idx) call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
// Stream interface. // Stream interface.
struct Stream : public File: struct Stream : public File:
@ -138,10 +139,10 @@ struct Stream : public File:
WRITE WRITE
// Try to read size bytes. Returns the number of bytes successfully read. // Try to read size bytes. Returns the number of bytes successfully read.
Num read (Num size, String ret): Num read (Num size, String ret):
return call (ret, CAP_MASTER_DIRECT | READ, size) return icall (ret, CAP_MASTER_DIRECT | READ, size)
// Try to write size bytes. Returns the number of bytes successfully written. // Try to write size bytes. Returns the number of bytes successfully written.
Num write (String s, Num size): Num write (String s, Num size):
return call (s, CAP_MASTER_DIRECT | WRITE, size) return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
// Seekable file interface. // Seekable file interface.
struct Seekable : public File: struct Seekable : public File:
@ -152,13 +153,13 @@ struct Seekable : public File:
TRUNCATE TRUNCATE
// Try to read size bytes from position idx. Returns the number of bytes successfully read. // Try to read size bytes from position idx. Returns the number of bytes successfully read.
Num read (Num idx, unsigned size, String ret): Num read (Num idx, unsigned size, String ret):
return call (ret, Num (CAP_MASTER_DIRECT | READ, size), idx) return icall (ret, Num (CAP_MASTER_DIRECT | READ, size), idx)
// Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written. // Try to write size bytes at position idx; the file is extended with zeroes if the write is past the end. Returns the number of bytes successfully written.
Num write (Num idx, String s): Num write (Num idx, String s):
return call (s, CAP_MASTER_DIRECT | WRITE, idx) return ocall (s, CAP_MASTER_DIRECT | WRITE, idx)
// Truncate file to size idx. The file is extended with zeroes if it gets longer. // Truncate file to size idx. The file is extended with zeroes if it gets longer.
void truncate (Num idx): void truncate (Num idx):
invoke (CAP_MASTER_DIRECT | TRUNCATE, idx) call (CAP_MASTER_DIRECT | TRUNCATE, idx)
// Mappable file interface. // Mappable file interface.
struct Mappable : public Seekable: struct Mappable : public Seekable:

View File

@ -58,15 +58,30 @@ enum cap_type:
CAP_TOUCHPAD CAP_TOUCHPAD
CAP_LOCKLEDS CAP_LOCKLEDS
CAP_PWM CAP_PWM
NUM_EVENT_TYPES
static unsigned events static unsigned events
static Caps event_caps
static void event (event_type type, unsigned data): static void event (event_type type, unsigned data):
Cap (events, type - 32).invoke (data) kdebug ("event t/d/e=")
kdebug_num (type)
kdebug_char ('/')
kdebug_num (data)
kdebug_char ('/')
kdebug_num (events)
kdebug_char ('\n')
Cap (events, type).invoke (data)
static void set_cb (Cap cap, event_type type): static void set_cb (Cap cap, event_type type):
cap.clone (Cap (events, type - 32)) kdebug ("gpio set cb ")
kdebug_num (type)
kdebug_char ('\n')
for unsigned i = 0; i < NUM_EVENTS; ++i:
event_caps.print (i)
cap.clone (Cap (events, type))
kdebug ("after:\n")
for unsigned i = 0; i < NUM_EVENTS; ++i:
event_caps.print (i)
class DevKeyboard: class DevKeyboard:
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
@ -188,7 +203,7 @@ class Touchpad:
else: else:
gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT) gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT): if (state ^ old_state) & (1 << GPIO_TP_LEFT):
event (TOUCHPAD_EVENT, 0x10000) event (TOUCHPAD_EVENT, 0 | Keyboard::RELEASE)
if state & (1 << GPIO_TP_RIGHT): if state & (1 << GPIO_TP_RIGHT):
gpio_irq_low (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT) gpio_irq_low (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT): if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
@ -196,7 +211,7 @@ class Touchpad:
else: else:
gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT) gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT): if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
event (TOUCHPAD_EVENT, 0x10001) event (TOUCHPAD_EVENT, 1 | Keyboard::RELEASE)
old_state = state old_state = state
// Ack interrupts. // Ack interrupts.
//GPIO_GPFR (GPIO_TP_LEFT_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) //GPIO_GPFR (GPIO_TP_LEFT_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
@ -255,22 +270,18 @@ class Pwm:
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything. // TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
Num start (): Num start ():
Kernel::schedule ()
map_gpio () map_gpio ()
map_pwm0 () map_pwm0 ()
Caps e = __my_memory.create_caps (NUM_EVENT_TYPES - 32) event_caps = __my_memory.create_caps (NUM_EVENTS)
events = e.use () events = event_caps.use ()
free_cap (e)
DevKeyboard kbd DevKeyboard kbd
Touchpad tp Touchpad tp
Lockleds leds Lockleds leds
Pwm pwm Pwm pwm
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
Kernel::register_interrupt (IRQ_GPIO0)
Caps c = __my_memory.create_caps (4) Caps c = __my_memory.create_caps (4)
unsigned init_slot = c.use () unsigned init_slot = c.use ()
__my_receiver.create_capability (CAP_KEYBOARD, Cap (init_slot, 0)) __my_receiver.create_capability (CAP_KEYBOARD, Cap (init_slot, 0))
@ -278,15 +289,23 @@ Num start ():
__my_receiver.create_capability (CAP_LOCKLEDS, Cap (init_slot, 2)) __my_receiver.create_capability (CAP_LOCKLEDS, Cap (init_slot, 2))
__my_receiver.create_capability (CAP_PWM, Cap (init_slot, 3)) __my_receiver.create_capability (CAP_PWM, Cap (init_slot, 3))
__my_parent.invoke (c, INIT_SET_GPIO) __my_parent.ocall (c, INIT_SET_GPIO)
free_cap (c) free_cap (c)
free_slot (init_slot)
if kbd.is_scanning (): if kbd.is_scanning ():
__my_receiver.set_alarm (ALARM_INTERVAL) __my_receiver.set_alarm (ALARM_INTERVAL)
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
Kernel::register_interrupt (IRQ_GPIO0)
kdebug ("gpio ready\n")
unsigned slot = alloc_slot ()
while true: while true:
Kernel::schedule () Kernel::schedule ()
Cap::OMessage msg Cap::OMessage msg
Kernel::wait (&msg) Kernel::wait (&msg, slot)
switch (unsigned)msg.cap_protected.value (): switch (unsigned)msg.cap_protected.value ():
case ~0: case ~0:
// Alarm. // Alarm.
@ -302,16 +321,20 @@ Num start ():
Kernel::register_interrupt (IRQ_GPIO0) Kernel::register_interrupt (IRQ_GPIO0)
break break
case CAP_KEYBOARD: case CAP_KEYBOARD:
set_cb (Cap (__tmp_slot, 0), KEYBOARD_EVENT) set_cb (Cap (slot, 1), KEYBOARD_EVENT)
Cap (slot, 0).invoke ()
kbd.send_initial () kbd.send_initial ()
break break
case CAP_TOUCHPAD: case CAP_TOUCHPAD:
set_cb (Cap (__tmp_slot, 0), TOUCHPAD_EVENT) set_cb (Cap (slot, 1), TOUCHPAD_EVENT)
Cap (slot, 0).invoke ()
tp.send_initial () tp.send_initial ()
break break
case CAP_LOCKLEDS: case CAP_LOCKLEDS:
leds.set (msg.data[0].l) leds.set (msg.data[0].l)
Cap (slot, 0).invoke ()
break break
case CAP_PWM: case CAP_PWM:
pwm.set_backlight (msg.data[0].l) pwm.set_backlight (msg.data[0].l)
Cap (slot, 0).invoke ()
break break

View File

@ -30,31 +30,37 @@ enum type:
static void setup (): static void setup ():
unsigned state = 0 unsigned state = 0
unsigned slot = 2 unsigned slot = alloc_slot ()
while true: while true:
Cap::OMessage msg Cap::OMessage msg
Kernel::wait (&msg, slot) Kernel::wait (&msg, slot)
switch msg.data[0].value (): switch msg.data[0].value ():
case INIT_SET_GPIO: case INIT_SET_GPIO:
kdebug ("gpio\n") kdebug ("gpio\n")
kbd = Cap (slot, 0) Caps caps = Cap (slot, 1)
tp = Cap (slot, 1) unsigned gpio_slot = caps.use ()
lockleds = Cap (slot, 2) Cap (slot, 0).invoke ()
pwm = Cap (slot, 3) kbd = Cap (gpio_slot, 0)
++slot tp = Cap (gpio_slot, 1)
lockleds = Cap (gpio_slot, 2)
pwm = Cap (gpio_slot, 3)
++state ++state
break break
case INIT_SET_LCD: case INIT_SET_LCD:
kdebug ("lcd\n") kdebug ("lcd\n")
lcd = Cap (slot, 0) lcd = Cap (slot, 1).clone ()
++slot Cap (slot, 0).invoke ()
++state ++state
break break
if state == 2: if state == 2:
break break
kbd.set_cb (__my_receiver.create_capability (KBD).copy ()) Caps caps = __my_memory.create_caps (2)
tp.set_cb (__my_receiver.create_capability (TP).copy ()) caps.use (slot)
pwm.invoke (1) Cap kc = __my_receiver.create_capability (KBD, Cap (slot, 1))
kbd.set_cb (kc)
Cap tc = __my_receiver.create_capability (TP, Cap (slot, 0))
tp.set_cb (tc)
pwm.call (1)
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":" char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
@ -82,5 +88,5 @@ Num start ():
leds |= 0x4 leds |= 0x4
if !(msg.data[0].l & Keyboard::RELEASE): if !(msg.data[0].l & Keyboard::RELEASE):
leds |= 0x2 leds |= 0x2
lockleds.invoke (leds) lockleds.call (leds)
break break

View File

@ -20,9 +20,9 @@
#define ARCH #define ARCH
#include "arch.hh" #include "arch.hh"
__asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"") __asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"\n.section .text")
// I'm too lazy to do this right. The address of charset is really the address of the array. // charset is really the first character in the array. Its address is used as the start of the array.
extern unsigned charset extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0) #define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
@ -32,16 +32,18 @@ enum types:
// For now, support only 16 bpp. // For now, support only 16 bpp.
// Screen is 800x480 tft. // Screen is 800x480 tft.
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#define frame_size (v * h * Bpp) #define frame_size (v * h * Bpp)
static unsigned physical_descriptor
struct Descriptor: struct Descriptor:
unsigned next unsigned next
unsigned frame unsigned frame
unsigned id unsigned id
unsigned cmd unsigned cmd
static void reset (unsigned physical_descriptor): static void reset ():
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
LCD_VSYNC = vs LCD_VSYNC = vs
LCD_HSYNC = hs LCD_HSYNC = hs
@ -74,11 +76,10 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
if ch < 32 || ch > 126: if ch < 32 || ch > 126:
ch = 127 ch = 127
ch -= 32 ch -= 32
unsigned char *c = &((unsigned char *)&charset)[ch * 6]
unsigned lookup[2] = { bg, fg } unsigned lookup[2] = { bg, fg }
for unsigned k = 0; k < 6; ++k: for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r: for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0] LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
static unsigned log_x = 1, log_y = 1 static unsigned log_x = 1, log_y = 1
static void inc_logx (): static void inc_logx ():
@ -126,12 +127,12 @@ Num start ():
Descriptor descriptor __attribute__ ((aligned (16))) Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
unsigned physical = Kernel::alloc_range (__my_memory, pages) unsigned physical = __my_memory.alloc_range (pages)
assert (physical) assert (physical & PAGE_MASK && ~physical)
for unsigned i = 0; i < pages; ++i: for unsigned i = 0; i < pages; ++i:
Page p = __my_memory.create_page () Page p = __my_memory.create_page ()
p.alloc_physical (physical + i * PAGE_SIZE, false, true) p.alloc_physical (physical + i * PAGE_SIZE, false, true)
__my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, true) __my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
free_cap (p) free_cap (p)
for unsigned y = 0; y < 480; ++y: for unsigned y = 0; y < 480; ++y:
unsigned g = (y << 6) / 480 unsigned g = (y << 6) / 480
@ -150,7 +151,7 @@ Num start ():
b = 0x1f b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b) LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
Page p = __my_memory.mapping (&descriptor) Page p = __my_memory.mapping (&descriptor)
unsigned physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK) physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
free_cap (p) free_cap (p)
descriptor.next = physical_descriptor descriptor.next = physical_descriptor
descriptor.frame = physical descriptor.frame = physical
@ -158,15 +159,16 @@ Num start ():
descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT) descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
unsigned dptr = (unsigned)&descriptor unsigned dptr = (unsigned)&descriptor
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0") __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset (physical_descriptor) reset ()
Cap set_eof_cb = __my_receiver.create_capability (LCD_EOF_CB)
__my_parent.invoke (set_eof_cb.copy (), INIT_SET_LCD)
Cap logcap = __my_receiver.create_capability (LCD_LOG) Cap logcap = __my_receiver.create_capability (LCD_LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory") __asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
Cap set_eof_cb = __my_receiver.create_capability (LCD_EOF_CB)
__my_parent.ocall (set_eof_cb, INIT_SET_LCD)
unsigned slot = alloc_slot () unsigned slot = alloc_slot ()
Cap eof_cb (0, alloc_cap ())
while true: while true:
Cap::OMessage msg Cap::OMessage msg
Kernel::wait (&msg, slot) Kernel::wait (&msg, slot)
@ -174,10 +176,11 @@ Num start ():
switch msg.cap_protected.value (): switch msg.cap_protected.value ():
case IRQ_LCD: case IRQ_LCD:
lcd_clr_eof () lcd_clr_eof ()
Cap (slot, 0).invoke () eof_cb.invoke ()
Cap (slot, 0) = Cap ()
break break
case LCD_EOF_CB: case LCD_EOF_CB:
Cap (slot, 1).clone (eof_cb)
Cap (slot, 0).invoke ()
Kernel::register_interrupt (IRQ_LCD) Kernel::register_interrupt (IRQ_LCD)
break break
case LCD_LOG: case LCD_LOG:

View File

@ -19,7 +19,7 @@
#include "kernel.hh" #include "kernel.hh"
void kThread::raise (unsigned code, unsigned data): void kThread::raise (unsigned code, unsigned data):
panic (code, "raise") dpanic (code, "raise")
dbg_log ("raise ") dbg_log ("raise ")
dbg_log_num ((unsigned)current) dbg_log_num ((unsigned)current)
dbg_log_char ('/') dbg_log_char ('/')
@ -48,16 +48,27 @@ kCapRef kThread::find_capability (unsigned code, bool *copy):
unsigned num = c & 0xffff unsigned num = c & 0xffff
if slot >= slots || !caps[slot] || num >= caps[slot]->size: if slot >= slots || !caps[slot] || num >= caps[slot]->size:
if c != CAP_NONE: if c != CAP_NONE:
panic (code, "debug") dpanic (code, "debug")
dbg_log_num ((unsigned)old_current) dbg_log_num ((unsigned)old_current)
dbg_log (": invalid capability ") dbg_log (": invalid capability ")
dbg_log_num (code) dbg_log_num (code)
dbg_log_char ('\n') dbg_log_char ('\n')
dbg_log_num (num)
dbg_log_char (':')
dbg_log_num (slot)
dbg_log (" > ")
if caps[slot]:
dbg_log_num (caps[slot]->size)
else:
dbg_log ("no caps")
dbg_log_char ('\n')
return kCapRef () return kCapRef ()
return kCapRef (caps[slot], num) return kCapRef (caps[slot], num)
void kThread::fill_slot (unsigned slot, kCaps *new_caps): void kThread::fill_slot (unsigned slot, kCaps *new_caps):
if slot >= slots: if slot >= slots:
if slot != ~0:
dpanic (0, "waiting with invalid slot")
return return
if caps[slot]: if caps[slot]:
// TODO: invalidate slot. // TODO: invalidate slot.
@ -90,7 +101,6 @@ bool kReceiver::send_message (Num cap_protected, kCapability::Context *c):
if owner && owner->is_waiting () && (cap_protected.value () == reply_protected_data.value () || !protected_only): if owner && owner->is_waiting () && (cap_protected.value () == reply_protected_data.value () || !protected_only):
if protected_only: if protected_only:
protected_only = false protected_only = false
if owner->recv_slot < owner->slots:
owner->fill_slot (owner->recv_slot, c->caps) owner->fill_slot (owner->recv_slot, c->caps)
kThread_arch_receive (owner, cap_protected, recv_protected, c->data) kThread_arch_receive (owner, cap_protected, recv_protected, c->data)
owner->unwait () owner->unwait ()
@ -133,8 +143,10 @@ static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
invoke (reply_target, reply_protected, &c, NULL) invoke (reply_target, reply_protected, &c, NULL)
static void reply_cap (unsigned target, Num cap_protected, kCapRef *ref): static void reply_cap (unsigned target, Num cap_protected, kCapRef *ref):
if reply: if reply.valid ():
reply.set ((kReceiver *)target, cap_protected, kCapRef (), ref) reply.set ((kReceiver *)target, cap_protected, kCapRef (), ref)
else:
dpanic (0x87677654, "no target to reply capability to")
reply_num (0) reply_num (0)
static void receiver_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c): static void receiver_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c):
@ -193,7 +205,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Num cap_protected, k
return return
default: default:
reply_num (ERR_INVALID_OPERATION) reply_num (ERR_INVALID_OPERATION)
break return
reply_num (0) reply_num (0)
static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c): static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c):
@ -206,6 +218,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
if ret: if ret:
reply_cap (CAPTYPE_RECEIVER | CAP_MASTER, (unsigned)ret, &ret->refs) reply_cap (CAPTYPE_RECEIVER | CAP_MASTER, (unsigned)ret, &ret->refs)
else: else:
dpanic (0x03311992, "out of memory creating receiver")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
case CAPTYPE_MEMORY: case CAPTYPE_MEMORY:
@ -213,6 +226,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
if ret: if ret:
reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)ret, &ret->refs) reply_cap (CAPTYPE_MEMORY | CAP_MASTER, (unsigned)ret, &ret->refs)
else: else:
dpanic (0x13311992, "out of memory creating memory")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
case CAPTYPE_THREAD: case CAPTYPE_THREAD:
@ -220,6 +234,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
if ret: if ret:
reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs) reply_cap (CAPTYPE_THREAD | CAP_MASTER, (unsigned)ret, &ret->refs)
else: else:
dpanic (0x23311992, "out of memory creating thread")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
case CAPTYPE_PAGE: case CAPTYPE_PAGE:
@ -227,6 +242,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
if ret: if ret:
reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs) reply_cap (CAPTYPE_PAGE | CAP_MASTER, (unsigned)ret, &ret->refs)
else: else:
dpanic (0x33311992, "out of memory creating page")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
case CAPTYPE_CAPS: case CAPTYPE_CAPS:
@ -234,6 +250,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
if ret: if ret:
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)ret, &ret->refs) reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)ret, &ret->refs)
else: else:
dpanic (0x43311992, "out of memory creating caps")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
default: default:
@ -270,10 +287,12 @@ static void memory_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
case Memory::MAP: case Memory::MAP:
// FIXME: this should work for fake pages as well. // FIXME: this should work for fake pages as well.
if c->caps->size < 2 || (unsigned)c->caps->cap (1)->target & ~KERNEL_MASK || ((unsigned)c->caps->cap (1)->target & CAPTYPE_MASK) != CAPTYPE_PAGE: if c->caps->size < 2 || (unsigned)c->caps->cap (1)->target & ~KERNEL_MASK || ((unsigned)c->caps->cap (1)->target & CAPTYPE_MASK) != CAPTYPE_PAGE:
dpanic (0x22993341, "Trying to map non-page")
reply_num (~0) reply_num (~0)
return return
kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l
if page->address_space != mem: if page->address_space != mem:
dpanic (0x52993341, "Trying to map foreign page")
reply_num (~0) reply_num (~0)
return return
bool readonly = c->data[1].l & (unsigned)c->caps->cap (1)->target & Page::READONLY bool readonly = c->data[1].l & (unsigned)c->caps->cap (1)->target & Page::READONLY
@ -350,10 +369,12 @@ static void thread_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
break break
case Thread::USE_SLOT: case Thread::USE_SLOT:
if c->data[1].l >= thread->slots || c->caps->size < 2: if c->data[1].l >= thread->slots || c->caps->size < 2:
dpanic (c->data[1].l, "no argument given for USE_SLOT")
reply_num (~0) reply_num (~0)
return return
// FIXME: This doesn't allow using a fake caps. // FIXME: This doesn't allow using a fake caps.
if (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | Caps::USE): if (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | CAP_MASTER) && (unsigned)c->caps->cap (1)->target != (CAPTYPE_CAPS | Caps::USE):
dpanic (0, "argument for USE_SLOT is not a caps")
reply_num (~0) reply_num (~0)
return return
thread->fill_slot (c->data[1].l, (kCaps *)c->caps->cap (1)->cap_protected.l) thread->fill_slot (c->data[1].l, (kCaps *)c->caps->cap (1)->cap_protected.l)
@ -362,6 +383,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
case Thread::SCHEDULE: case Thread::SCHEDULE:
do_schedule = true do_schedule = true
return return
default:
if !(thread->flags & Thread::PRIV): if !(thread->flags & Thread::PRIV):
reply_num (ERR_INVALID_OPERATION) reply_num (ERR_INVALID_OPERATION)
return return
@ -380,21 +402,25 @@ static void thread_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
break break
case Thread::PRIV_ALLOC_RANGE: case Thread::PRIV_ALLOC_RANGE:
if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target) & ~REQUEST_MASK != CAPTYPE_MEMORY: if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
panic (0x54365435, "non-memory argument to alloc_range")
reply_num (~0) reply_num (~0)
return return
kMemory *mem = (kMemory *)c->caps->cap (1)->cap_protected.l kMemory *mem = (kMemory *)c->caps->cap (1)->cap_protected.l
if !mem->use (c->data[1].l): if !mem->use (c->data[1].l):
dpanic (0x34365435, "out of memory during alloc_range")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
unsigned data = phys_alloc (c->data[1].l) unsigned data = phys_alloc (c->data[1].l)
if !data: if !data:
mem->unuse (c->data[1].l) mem->unuse (c->data[1].l)
dpanic (0x14365435, "out of memory during alloc_range")
reply_num (ERR_OUT_OF_MEMORY) reply_num (ERR_OUT_OF_MEMORY)
return return
reply_num (data & ~0xc0000000) reply_num (data & ~0xc0000000)
return return
case Thread::PRIV_ALLOC_PHYSICAL: case Thread::PRIV_ALLOC_PHYSICAL:
if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target) & ~REQUEST_MASK != CAPTYPE_PAGE: if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
panic (0x21342134, "no page provided for alloc physical")
reply_num (~0) reply_num (~0)
return return
kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l
@ -419,6 +445,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Num cap_protected, kCa
break break
case Thread::PRIV_PHYSICAL_ADDRESS: case Thread::PRIV_PHYSICAL_ADDRESS:
if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target) & ~REQUEST_MASK != CAPTYPE_PAGE: if c->caps->size < 2 || ((unsigned)c->caps->cap (1)->target) & ~REQUEST_MASK != CAPTYPE_PAGE:
dpanic (0x99049380, "invalid page for physical address")
reply_num (~0) reply_num (~0)
return return
kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l kPage *page = (kPage *)c->caps->cap (1)->cap_protected.l
@ -463,14 +490,15 @@ static void page_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapa
// Cannot share without a target page. // Cannot share without a target page.
reply_num (~0) reply_num (~0)
return return
if ((unsigned)c->caps->cap (0)->target & ~REQUEST_MASK) != CAPTYPE_PAGE: if ((unsigned)c->caps->cap (1)->target & ~REQUEST_MASK) != CAPTYPE_PAGE:
// FIXME: This makes it impossible to use a fake kPage capability. // FIXME: This makes it impossible to use a fake kPage capability.
break reply_num (~0)
kPage *t = (kPage *)c->caps->cap (0)->cap_protected.l return
kPage *t = (kPage *)c->caps->cap (1)->cap_protected.l
t->forget () t->forget ()
if c->data[0].h & Page::READONLY || cmd & Page::READONLY: if c->data[0].h & Page::READONLY || cmd & Page::READONLY:
t->flags |= Page::READONLY t->flags |= Page::READONLY
if !page->flags & Page::FRAME: if !(page->flags & Page::FRAME):
break break
if c->data[0].h & Page::COPY: if c->data[0].h & Page::COPY:
if ~t->flags & Page::PAYING: if ~t->flags & Page::PAYING:
@ -577,21 +605,74 @@ static void page_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapa
break break
default: default:
reply_num (ERR_INVALID_OPERATION) reply_num (ERR_INVALID_OPERATION)
break return
reply_num (0)
static void print_capref (kCapRef cap):
dbg_log_num ((unsigned)cap.caps)
dbg_log_char (':')
dbg_log_num (cap.index)
static void print_cap (kCapRef cap, kCapRef self):
if cap.deref () == self.deref ():
dbg_log_char ('{')
else:
dbg_log_char ('[')
dbg_log_num ((unsigned)cap.caps)
dbg_log_char (':')
dbg_log_num (cap.index)
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
print_cap (c, self)
if cap.deref () == self.deref ():
dbg_log_char ('}')
else:
dbg_log_char (']')
static void caps_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c): static void caps_invoke (unsigned cmd, unsigned target, Num cap_protected, kCapability::Context *c):
kCaps *caps = (kCapsP)cap_protected.l kCaps *caps = (kCapsP)cap_protected.l
switch cmd: switch cmd:
case Caps::PRINT:
if c->data[1].l >= caps->size:
dpanic (0, "invalid caps for print")
return
kCapRef cap (caps, c->data[1].l)
kCapRef orig (caps, c->data[1].l)
while cap->parent.valid ():
while cap->sibling_prev.valid ():
if cap->parent.deref () != cap->sibling_prev->parent.deref ():
dpanic (0, "parent problem in cap data")
return
if cap.deref () != cap->sibling_prev->sibling_next.deref ():
dpanic (0, "prev error in cap data")
return
cap = cap->sibling_prev
if cap->parent->children.deref () != cap.deref ():
dpanic (0, "parent error in cap data")
return
cap = cap->parent
while cap->sibling_prev.valid ():
if cap->parent.deref () != cap->sibling_prev->parent.deref ():
dpanic (0, "parent parent problem in cap data")
return
if cap.deref () != cap->sibling_prev->sibling_next.deref ():
dpanic (0, "parent prev error in cap data")
return
cap = cap->sibling_prev
while cap.valid ():
print_cap (cap, orig)
cap = cap->sibling_next
dbg_log_char ('\n')
return
default: default:
reply_num (ERR_INVALID_OPERATION) reply_num (ERR_INVALID_OPERATION)
break return
static void kill_reply (kCapability *self): static void kill_reply (kCapability *self):
while self->parent: while self->parent.valid ():
self = self->parent.deref () self = self->parent.deref ()
while self->sibling_prev: while self->sibling_prev.valid ():
self->sibling_prev->invalidate () self->sibling_prev->invalidate ()
while self->sibling_next: while self->sibling_next.valid ():
self->sibling_next->invalidate () self->sibling_next->invalidate ()
self->invalidate () self->invalidate ()
@ -602,11 +683,14 @@ static void kernel_invoke (unsigned target, Num cap_protected, kCapability::Cont
// other parameters' meanings depend on the operation. // other parameters' meanings depend on the operation.
if target == (CAPTYPE_RECEIVER | Receiver::CALL) || target == (CAPTYPE_RECEIVER | Receiver::CALL_ASYNC): if target == (CAPTYPE_RECEIVER | Receiver::CALL) || target == (CAPTYPE_RECEIVER | Receiver::CALL_ASYNC):
// This is a call capability. caps->cap (0) is the capability to call. It should be replaced by the reply capability. // This is a call capability. caps->cap (0) is the capability to call. It should be replaced by the reply capability.
if !c->caps || c->caps->size == 0:
// No caps, so no target to call.
return
reply_target = (kReceiver *)cap_protected.l reply_target = (kReceiver *)cap_protected.l
reply_target->protected_only = target == (CAPTYPE_RECEIVER | Receiver::CALL) reply_target->protected_only = target == (CAPTYPE_RECEIVER | Receiver::CALL)
if must_wait:
old_current->wait ()
if !c->caps || c->caps->size == 0:
// No caps, so no target to call.
dpanic (0x54635675, "no target to call")
return
kReceiver *call_target = c->caps->cap (0)->target kReceiver *call_target = c->caps->cap (0)->target
Num call_cap_protected = c->caps->cap (0)->cap_protected Num call_cap_protected = c->caps->cap (0)->cap_protected
if ((unsigned)call_target & ~KERNEL_MASK) != 0: if ((unsigned)call_target & ~KERNEL_MASK) != 0:
@ -614,7 +698,7 @@ static void kernel_invoke (unsigned target, Num cap_protected, kCapability::Cont
c->caps->cap (0)->invalidate () c->caps->cap (0)->invalidate ()
c->caps->set (0, (kReceiver *)(CAPTYPE_RECEIVER | Receiver::REPLY), cap_protected, kCapRef (), &((kReceiver *)cap_protected.l)->refs) c->caps->set (0, (kReceiver *)(CAPTYPE_RECEIVER | Receiver::REPLY), cap_protected, kCapRef (), &((kReceiver *)cap_protected.l)->refs)
call_target->send_message (call_cap_protected, c) call_target->send_message (call_cap_protected, c)
else if (unsigned)call_target == CAPTYPE_RECEIVER | Receiver::REPLY: else if (unsigned)call_target == (CAPTYPE_RECEIVER | Receiver::REPLY):
// Reply capability: destroy all before invoke. // Reply capability: destroy all before invoke.
kill_reply (c->caps->cap (0)) kill_reply (c->caps->cap (0))
kReceiver *r = (kReceiver *)call_cap_protected.l kReceiver *r = (kReceiver *)call_cap_protected.l
@ -625,12 +709,16 @@ static void kernel_invoke (unsigned target, Num cap_protected, kCapability::Cont
c->caps->cap (0)->invalidate () c->caps->cap (0)->invalidate ()
kernel_invoke ((unsigned)call_target, call_cap_protected, c, NULL) kernel_invoke ((unsigned)call_target, call_cap_protected, c, NULL)
return return
if target == CAPTYPE_RECEIVER | Receiver::REPLY: if must_wait:
old_current->wait ()
if target == (CAPTYPE_RECEIVER | Receiver::REPLY):
// This is a reply capability. // This is a reply capability.
kReceiver *r = (kReceiver *)cap_protected.l kReceiver *r = (kReceiver *)cap_protected.l
kill_reply (self) kill_reply (self)
r->send_message (r->reply_protected_data, c) r->send_message (r->reply_protected_data, c)
return return
if !target:
return
reply = kCapRef (c->caps, 0) reply = kCapRef (c->caps, 0)
unsigned cmd unsigned cmd
if (target & REQUEST_MASK) == CAP_MASTER: if (target & REQUEST_MASK) == CAP_MASTER:
@ -665,12 +753,14 @@ static void kernel_invoke (unsigned target, Num cap_protected, kCapability::Cont
void invoke (kReceiverP target, Num cap_protected, kCapability::Context *c, kCapability *self): void invoke (kReceiverP target, Num cap_protected, kCapability::Context *c, kCapability *self):
if (unsigned)target & ~KERNEL_MASK: if (unsigned)target & ~KERNEL_MASK:
// This is not a kernel capability: send a message to the receiver. // This is not a kernel capability: send a message to the receiver.
if must_wait:
old_current->wait ()
target->send_message (cap_protected, c) target->send_message (cap_protected, c)
return return
// This is a kernel capability. Use a function to allow optimized call capabilities. // This is a kernel capability. Use a function to allow optimized call capabilities.
if !c->caps || c->caps->size < 1: if !c->caps || c->caps->size < 1:
reply_target = NULL reply_target = NULL
else: else:
reply_target = c->caps->cap (1)->target reply_target = c->caps->cap (0)->target
reply_protected = c->caps->cap (1)->cap_protected reply_protected = c->caps->cap (0)->cap_protected
kernel_invoke ((unsigned)target, cap_protected, c, self) kernel_invoke ((unsigned)target, cap_protected, c, self)

212
iris.hhp
View File

@ -122,10 +122,10 @@ struct Memory
#define __receiver_num 0 #define __receiver_num 0
#define __thread_num 1 #define __thread_num 1
#define __memory_num 2 #define __memory_num 2
#define __caps_num 3 #define __call_num 3
#define __call_num 4 #define __parent_num 4
#define __parent_num 5
#define __tmp_num 6 #define __tmp_slot 1
// If this flag is set in a capability, it is copied instead of mapped. // If this flag is set in a capability, it is copied instead of mapped.
// If it is set in the target capability, the Thread waits after the request. // If it is set in the target capability, the Thread waits after the request.
@ -139,15 +139,12 @@ extern Memory __my_memory
extern Cap __my_call extern Cap __my_call
extern Cap __my_parent extern Cap __my_parent
extern Caps __my_caps extern Caps __my_caps
extern Caps __tmp_caps
unsigned alloc_slot () unsigned alloc_slot ()
unsigned alloc_cap () unsigned alloc_cap ()
void free_slot (unsigned slot) void free_slot (unsigned slot)
void free_cap (Cap cap) void free_cap (Cap cap)
#define __tmp_slot 1
struct Cap: struct Cap:
unsigned code unsigned code
inline Cap copy () const inline Cap copy () const
@ -160,11 +157,12 @@ struct Cap:
struct OMessage struct OMessage
inline void invoke (IMessage const *i, OMessage *o) inline void invoke (IMessage const *i, OMessage *o)
inline void call (IMessage *i, OMessage *o) inline void call (IMessage *i, OMessage *o)
inline void invoke (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot)
inline void invoke (Num d0 = 0, Num d1 = 0) inline void invoke (Num d0 = 0, Num d1 = 0)
inline Num call (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0)
inline Num call (Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0) inline Num call (Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0)
inline void clone (Cap target) inline Num icall (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0)
inline Num ocall (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0)
inline Num iocall (Cap c, Num d0 = 0, Num d1 = 0, unsigned oslot = __tmp_slot, unsigned islot = ~0)
inline Cap clone (Cap target = Cap (0, alloc_cap ()))
struct Cap::IMessage: struct Cap::IMessage:
Num data[2] Num data[2]
@ -182,34 +180,15 @@ Cap::Cap () : code (CAP_NONE):
Cap::Cap (unsigned c) : code (c): Cap::Cap (unsigned c) : code (c):
Cap::Cap (unsigned slot, unsigned idx) : code (idx | (slot << 16)): Cap::Cap (unsigned slot, unsigned idx) : code (idx | (slot << 16)):
unsigned Cap::slot () const: unsigned Cap::slot () const:
return code >> 16 return (code >> 16) & 0x7fff
unsigned Cap::idx () const: unsigned Cap::idx () const:
return code & 0xffff return code & 0xffff
void Cap::invoke (IMessage const *i, OMessage *o): void Cap::invoke (IMessage const *i, OMessage *o):
switch i->num: Cap *s = i->set
default: __asm__ volatile ("lw $v0, %3\n"
__asm__ volatile ("lw $t9, %0" :: "m"(i->set[9].code) : "t9") "\tlw $t0, 0($v0)\n"
case 9: "\tlw $t1, 4($v0)\n"
__asm__ volatile ("lw $t8, %0" :: "m"(i->set[8].code) : "t8") "\tlw $v0, %2\n"
case 8:
__asm__ volatile ("lw $t7, %0" :: "m"(i->set[7].code) : "t7")
case 7:
__asm__ volatile ("lw $t6, %0" :: "m"(i->set[6].code) : "t6")
case 6:
__asm__ volatile ("lw $t5, %0" :: "m"(i->set[5].code) : "t5")
case 5:
__asm__ volatile ("lw $t4, %0" :: "m"(i->set[4].code) : "t4")
case 4:
__asm__ volatile ("lw $t3, %0" :: "m"(i->set[3].code) : "t3")
case 3:
__asm__ volatile ("lw $t2, %0" :: "m"(i->set[2].code) : "t2")
case 2:
__asm__ volatile ("lw $t1, %0" :: "m"(i->set[1].code) : "t1")
case 1:
__asm__ volatile ("lw $t0, %0" :: "m"(i->set[0].code) : "t0")
case 0:
break
__asm__ volatile ("lw $v0, %2\n"
"\tlw $a0, 0($v0)\n" "\tlw $a0, 0($v0)\n"
"\tlw $a1, 4($v0)\n" "\tlw $a1, 4($v0)\n"
"\tlw $a2, 8($v0)\n" "\tlw $a2, 8($v0)\n"
@ -228,49 +207,24 @@ void Cap::invoke (IMessage const *i, OMessage *o):
"\tsw $s0, 16($v0)\n" "\tsw $s0, 16($v0)\n"
"\tsw $s1, 20($v0)\n" "\tsw $s1, 20($v0)\n"
"\tsw $s2, 24($v0)\n" "\tsw $s2, 24($v0)\n"
"\tsw $s3, 28($v0)\n" "\tsw $s3, 28($v0)"
: "=m"(o) : "=m"(o)
: "m"(code), "m"(i) : "m"(code), "m"(i), "m"(s)
: "memory", "v0", "s0", "s1", "s2", "s3", "a0", "a1", "a2", "a3") : "memory", "v0", "s0", "s1", "s2", "s3", "a0", "a1", "a2", "a3", "t0", "t1")
void Cap::call (IMessage *i, OMessage *o): void Cap::call (IMessage *i, OMessage *o):
i->set[0] = *this i->set[0] = *this
__my_call.copy ().invoke (i, o) __my_call.copy ().invoke (i, o)
void Cap::invoke (Cap c, Num d0, Num d1, unsigned oslot):
IMessage i
OMessage o
i.islot = ~0
i.oslot = oslot
Cap cs[2]
cs[0] = c
i.set = cs
i.num = 2
i.first = 0
i.data[0] = d0
i.data[1] = d1
invoke (&i, &o)
void Cap::invoke (Num d0, Num d1): void Cap::invoke (Num d0, Num d1):
IMessage i IMessage i
OMessage o OMessage o
i.oslot = ~0 i.oslot = ~0
i.islot = ~0 i.islot = ~0
Cap cs[2]
i.set = cs
i.num = 0 i.num = 0
i.data[0] = d0 i.data[0] = d0
i.data[1] = d1 i.data[1] = d1
invoke (&i, &o) invoke (&i, &o)
Num Cap::call (Cap c, Num d0, Num d1, unsigned oslot, unsigned islot):
IMessage i
OMessage o
Cap cs[2]
cs[1] = c
i.set = cs
i.oslot = oslot
i.islot = islot
i.num = 2
i.first = 0
i.data[0] = d0
i.data[1] = d1
invoke (&i, &o)
return o.data[0]
Num Cap::call (Num d0, Num d1, unsigned oslot, unsigned islot): Num Cap::call (Num d0, Num d1, unsigned oslot, unsigned islot):
IMessage i IMessage i
OMessage o OMessage o
@ -282,13 +236,57 @@ Num Cap::call (Num d0, Num d1, unsigned oslot, unsigned islot):
i.first = 0 i.first = 0
i.data[0] = d0 i.data[0] = d0
i.data[1] = d1 i.data[1] = d1
invoke (&i, &o) call (&i, &o)
return o.data[0] return o.data[0]
void Cap::clone (Cap target): Num Cap::icall (Cap c, Num d0, Num d1, unsigned oslot, unsigned islot):
IMessage i IMessage i
OMessage o OMessage o
Cap c = this->copy () Cap cs[2]
i.set = &c i.set = cs
i.oslot = oslot
i.islot = islot
i.num = 2
i.first = 0
i.data[0] = d0
i.data[1] = d1
call (&i, &o)
Cap (oslot, 0).clone (c)
return o.data[0]
Num Cap::ocall (Cap c, Num d0, Num d1, unsigned oslot, unsigned islot):
IMessage i
OMessage o
Cap cs[2]
cs[1] = c
i.set = cs
i.oslot = oslot
i.islot = islot
i.num = 2
i.first = 0
i.data[0] = d0
i.data[1] = d1
call (&i, &o)
return o.data[0]
Num Cap::iocall (Cap c, Num d0, Num d1, unsigned oslot, unsigned islot):
IMessage i
OMessage o
Cap cs[2]
cs[1] = c
i.set = cs
i.oslot = oslot
i.islot = islot
i.num = 2
i.first = 0
i.data[0] = d0
i.data[1] = d1
call (&i, &o)
Cap (oslot, 0).clone (c)
return o.data[0]
Cap Cap::clone (Cap target):
IMessage i
OMessage o
Cap cs[2]
cs[0] = this->copy ()
i.set = cs
i.oslot = target.slot () i.oslot = target.slot ()
i.first = target.idx () i.first = target.idx ()
i.num = 1 i.num = 1
@ -296,6 +294,7 @@ void Cap::clone (Cap target):
i.data[0] = 0 i.data[0] = 0
i.data[1] = 0 i.data[1] = 0
Cap ().invoke (&i, &o) Cap ().invoke (&i, &o)
return target
struct Receiver : public Cap: struct Receiver : public Cap:
Receiver (unsigned slot, unsigned idx) : Cap (slot, idx): Receiver (unsigned slot, unsigned idx) : Cap (slot, idx):
@ -318,26 +317,26 @@ struct Receiver : public Cap:
// A call capability, waiting for only this reply is disabled. This can only be created by invoking CREATE_CALL_ASYNC_CAPABILITY. // A call capability, waiting for only this reply is disabled. This can only be created by invoking CREATE_CALL_ASYNC_CAPABILITY.
CALL_ASYNC CALL_ASYNC
void set_owner (Cap owner): void set_owner (Cap owner):
invoke (owner, CAP_MASTER_DIRECT | Receiver::SET_OWNER) ocall (owner, CAP_MASTER_DIRECT | Receiver::SET_OWNER)
Cap create_capability (unsigned protected_data, Cap ret = Cap (0, alloc_cap ())): Cap create_capability (unsigned protected_data, Cap ret = Cap (0, alloc_cap ())):
call (ret, CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data) icall (ret, CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
return ret return ret
Num get_reply_protected_data (): Num get_reply_protected_data ():
return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA) return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
void set_reply_protected_data (Num data): void set_reply_protected_data (Num data):
invoke (CAP_MASTER_DIRECT | SET_REPLY_PROTECTED_DATA, data) call (CAP_MASTER_DIRECT | SET_REPLY_PROTECTED_DATA, data)
unsigned get_alarm (): unsigned get_alarm ():
return call (CAP_MASTER_DIRECT | GET_ALARM).l return call (CAP_MASTER_DIRECT | GET_ALARM).l
unsigned add_alarm (unsigned data): unsigned add_alarm (unsigned data):
return call (CAP_MASTER_DIRECT | ADD_ALARM, data).l return call (CAP_MASTER_DIRECT | ADD_ALARM, data).l
void set_alarm (unsigned data): void set_alarm (unsigned data):
invoke (CAP_MASTER_DIRECT | SET_ALARM, data) call (CAP_MASTER_DIRECT | SET_ALARM, data)
static inline void sleep (unsigned value, OMessage *ret, unsigned slot = __tmp_slot) static inline void sleep (unsigned value, OMessage *ret, unsigned slot = __tmp_slot)
Cap create_call_capability (Cap ret = Cap (0, alloc_cap ())): Cap create_call_capability (Cap ret = Cap (0, alloc_cap ())):
call (ret, CAP_MASTER_DIRECT | CREATE_CALL_CAPABILITY) icall (ret, CAP_MASTER_DIRECT | CREATE_CALL_CAPABILITY)
return ret return ret
Cap create_async_call_capability (Cap ret = Cap (0, alloc_cap ())): Cap create_async_call_capability (Cap ret = Cap (0, alloc_cap ())):
call (ret, CAP_MASTER_DIRECT | CREATE_ASYNC_CALL_CAPABILITY) icall (ret, CAP_MASTER_DIRECT | CREATE_ASYNC_CALL_CAPABILITY)
return ret return ret
struct Thread : public Cap: struct Thread : public Cap:
@ -368,11 +367,11 @@ struct Thread : public Cap:
RUNNING = 1 << 29 RUNNING = 1 << 29
USER_FLAGS = ~(PRIV | WAITING | RUNNING) USER_FLAGS = ~(PRIV | WAITING | RUNNING)
void make_priv (): void make_priv ():
__my_thread.invoke (*this, CAP_MASTER_DIRECT | PRIV_MAKE_PRIV) __my_thread.ocall (*this, CAP_MASTER_DIRECT | PRIV_MAKE_PRIV)
unsigned get_info (unsigned info): unsigned get_info (unsigned info):
return call (Num (CAP_MASTER_DIRECT | GET_INFO, info)).l return call (Num (CAP_MASTER_DIRECT | GET_INFO, info)).l
void set_info (unsigned info, unsigned value, unsigned mask = ~0): void set_info (unsigned info, unsigned value, unsigned mask = ~0):
invoke (Num (CAP_MASTER_DIRECT | SET_INFO, info), Num (value, mask)) call (Num (CAP_MASTER_DIRECT | SET_INFO, info), Num (value, mask))
void set_pc (unsigned pc): void set_pc (unsigned pc):
set_info (PC, pc) set_info (PC, pc)
void set_sp (unsigned sp): void set_sp (unsigned sp):
@ -397,12 +396,14 @@ struct Caps : public Cap:
enum request: enum request:
// Not an operation; this capability can be used in Thread::USE_SLOT. // Not an operation; this capability can be used in Thread::USE_SLOT.
USE = 1 USE = 1
PRINT
unsigned use (unsigned slot = alloc_slot ()): unsigned use (unsigned slot = alloc_slot ()):
__my_thread.use (*this, slot) return __my_thread.use (*this, slot)
return slot void print (unsigned idx):
invoke (CAP_MASTER_DIRECT | PRINT, idx)
unsigned Thread::use (Caps caps, unsigned slot): unsigned Thread::use (Caps caps, unsigned slot):
invoke (caps, CAP_MASTER_DIRECT | USE_SLOT, slot) ocall (caps, CAP_MASTER_DIRECT | USE_SLOT, slot)
return slot return slot
struct Page : public Cap: struct Page : public Cap:
@ -436,15 +437,15 @@ struct Page : public Cap:
// This is a read-only flag, saying if this is uncachable memory. // This is a read-only flag, saying if this is uncachable memory.
UNCACHED = 0x20 UNCACHED = 0x20
void share (Cap target, unsigned flags): void share (Cap target, unsigned flags):
invoke (target, CAP_MASTER_DIRECT | SHARE, flags) ocall (target, CAP_MASTER_DIRECT | SHARE, flags)
unsigned get_flags (): unsigned get_flags ():
return call (CAP_MASTER_DIRECT | GET_FLAGS).l return call (CAP_MASTER_DIRECT | GET_FLAGS).l
void set_flags (unsigned new_flags, unsigned mask): void set_flags (unsigned new_flags, unsigned mask):
invoke (CAP_MASTER_DIRECT | SET_FLAGS, Num (new_flags, mask)) call (CAP_MASTER_DIRECT | SET_FLAGS, Num (new_flags, mask))
unsigned physical_address (): unsigned physical_address ():
return __my_thread.call (*this, CAP_MASTER_DIRECT | Thread::PRIV_PHYSICAL_ADDRESS).l return __my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_PHYSICAL_ADDRESS).l
void alloc_physical (unsigned address, bool cachable, bool freeable): void alloc_physical (unsigned address, bool cachable, bool freeable):
__my_thread.invoke (*this, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0) | (freeable ? 2 : 0)) __my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0) | (freeable ? 2 : 0))
struct Memory : public Cap: struct Memory : public Cap:
Memory (unsigned slot, unsigned idx) : Cap (slot, idx): Memory (unsigned slot, unsigned idx) : Cap (slot, idx):
@ -458,52 +459,56 @@ struct Memory : public Cap:
GET_LIMIT GET_LIMIT
SET_LIMIT SET_LIMIT
Page create_page (Page ret = Cap (0, alloc_cap ())): Page create_page (Page ret = Cap (0, alloc_cap ())):
call (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_PAGE)) icall (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_PAGE))
return ret return ret
Thread create_thread (unsigned slots, Thread ret = Cap (0, alloc_cap ())): Thread create_thread (unsigned slots, Thread ret = Cap (0, alloc_cap ())):
call (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_THREAD), slots) icall (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_THREAD), slots)
return ret return ret
Receiver create_receiver (Receiver ret = Cap (0, alloc_cap ())): Receiver create_receiver (Receiver ret = Cap (0, alloc_cap ())):
call (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_RECEIVER)) icall (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_RECEIVER))
return ret return ret
Memory create_memory (Memory ret = Cap (0, alloc_cap ())): Memory create_memory (Memory ret = Cap (0, alloc_cap ())):
call (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_MEMORY)) icall (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_MEMORY))
return ret return ret
Caps create_caps (unsigned size, Caps ret = Cap (0, alloc_cap ())): Caps create_caps (unsigned size, Caps ret = Cap (0, alloc_cap ())):
call (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_CAPS), size) icall (ret, Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_CAPS), size)
return ret return ret
void destroy (Cap target): void destroy (Cap target):
invoke (target, CAP_MASTER_DIRECT | DESTROY) ocall (target, CAP_MASTER_DIRECT | DESTROY)
// TODO: LIST // TODO: LIST
void map (Cap page, unsigned address, bool readonly): void map (Cap page, unsigned address, bool readonly = false):
if readonly: if readonly:
address |= Page::READONLY address |= Page::READONLY
invoke (page, CAP_MASTER_DIRECT | MAP, address) ocall (page, CAP_MASTER_DIRECT | MAP, address)
Page mapping (void *address, Page ret = Cap (0, alloc_cap ())): Page mapping (void *address, Page ret = Cap (0, alloc_cap ())):
call (ret, CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address)) icall (ret, CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address))
return ret return ret
unsigned get_limit (unsigned limit): unsigned get_limit (unsigned limit):
return call (CAP_MASTER_DIRECT | GET_LIMIT).l return call (CAP_MASTER_DIRECT | GET_LIMIT).l
void set_limit (unsigned limit): void set_limit (unsigned limit):
invoke (CAP_MASTER_DIRECT | SET_LIMIT, limit) call (CAP_MASTER_DIRECT | SET_LIMIT, limit)
unsigned alloc_range (unsigned pages):
return __my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_RANGE, pages).l
struct Kernel: struct Kernel:
static void wait (Cap::OMessage *o, unsigned islot = __tmp_slot): static void wait (Cap::OMessage *o, unsigned islot = ~0):
Cap::IMessage i Cap::IMessage i
i.islot = islot i.islot = islot
i.num = 0 i.num = 0
i.first = 0
i.oslot = ~0
Cap cs[2]
i.set = cs
Cap ().copy ().invoke (&i, o) Cap ().copy ().invoke (&i, o)
static void schedule (): static void schedule ():
__my_thread.invoke (CAP_MASTER_DIRECT | Thread::SCHEDULE) __my_thread.invoke (CAP_MASTER_DIRECT | Thread::SCHEDULE)
static void register_interrupt (unsigned num): static void register_interrupt (unsigned num):
__my_thread.invoke (__my_receiver, CAP_MASTER_DIRECT | Thread::PRIV_REGISTER_INTERRUPT, num) __my_thread.ocall (__my_receiver, CAP_MASTER_DIRECT | Thread::PRIV_REGISTER_INTERRUPT, num)
static void unregister_interrupt (unsigned num): static void unregister_interrupt (unsigned num):
__my_thread.invoke (CAP_MASTER_DIRECT | Thread::PRIV_REGISTER_INTERRUPT, num) __my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REGISTER_INTERRUPT, num)
static Cap get_top_memory (): static Cap get_top_memory (Cap ret = Cap (0, alloc_cap ())):
__my_thread.call (__tmp_slot, CAP_MASTER_DIRECT | Thread::PRIV_GET_TOP_MEMORY) __my_thread.icall (ret, CAP_MASTER_DIRECT | Thread::PRIV_GET_TOP_MEMORY)
return Cap (__tmp_slot, 0) return ret
static unsigned alloc_range (Cap memory, unsigned pages):
__my_thread.call (memory, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_RANGE, pages)
void Receiver::sleep (unsigned value, OMessage *ret, unsigned slot): void Receiver::sleep (unsigned value, OMessage *ret, unsigned slot):
__my_receiver.set_alarm (value) __my_receiver.set_alarm (value)
@ -516,6 +521,9 @@ void Receiver::sleep (unsigned value, OMessage *ret, unsigned slot):
#define kdebug_char(c) do {} while (0) #define kdebug_char(c) do {} while (0)
#endif #endif
#define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0) #define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0)
#define __stringify2(x) #x
#define __stringify(x) __stringify2 (x)
#define kdebug_line() do { kdebug (__stringify (__LINE__)); kdebug_char ('\n'); } while (0)
static void kdebug_num (unsigned n): static void kdebug_num (unsigned n):
unsigned i unsigned i

View File

@ -51,7 +51,7 @@ struct kCapRef:
kCapsP caps kCapsP caps
unsigned index unsigned index
inline kCapability *deref () inline kCapability *deref ()
operator bool (): bool valid ():
return deref () != NULL return deref () != NULL
kCapability *operator-> (): kCapability *operator-> ():
return deref () return deref ()
@ -167,7 +167,7 @@ struct kMemory : public kObject:
unsigned limit, used unsigned limit, used
kMemory_arch arch kMemory_arch arch
inline bool map (kPage *page, unsigned address, bool write) inline bool map (kPage *page, unsigned address, bool readonly)
inline void unmap (kPage *page, unsigned address) inline void unmap (kPage *page, unsigned address)
inline kPage *get_mapping (unsigned address, bool *readonly) inline kPage *get_mapping (unsigned address, bool *readonly)
@ -199,15 +199,26 @@ struct kMemory : public kObject:
// 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 sent to dbg_caps (when in use).
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m))
void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "") void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
EXTERN unsigned dbg_code #ifndef NDEBUG
EXTERN Num dbg_code
EXTERN kCapRef dbg_cap EXTERN kCapRef 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) void dbg_log_num (unsigned num)
void dbg_send (unsigned num, unsigned bits)
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m)) void check (unsigned num, char const *msg)
#define dpanic(n, msg) panic (n, msg)
#else
#define dbg_log_char(x) do {} while (0)
#define dbg_log(x) do {} while (0)
#define dbg_log_num(n) do {} while (0)
#define dbg_send(n, m) do {} while (0)
#define check (n, x) do {} while (0)
#define dpanic(n, x) do {} while (0)
#endif
/// Defined in schedule.ccp /// Defined in schedule.ccp
void schedule () void schedule ()
@ -220,7 +231,7 @@ EXTERN kMemory idle_memory
EXTERN kPage idle_page EXTERN kPage idle_page
EXTERN kThreadP first_scheduled EXTERN kThreadP first_scheduled
EXTERN kThreadP current, old_current EXTERN kThreadP current, old_current
EXTERN bool do_schedule EXTERN bool do_schedule, must_wait
// Defined in memory.ccp // Defined in memory.ccp
unsigned init_memory (unsigned mem) unsigned init_memory (unsigned mem)
@ -244,8 +255,8 @@ kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address, bool *readonly)
void kPage_arch_update_mapping (kPage *page) void kPage_arch_update_mapping (kPage *page)
void arch_register_interrupt (unsigned num, kReceiverP r) void arch_register_interrupt (unsigned num, kReceiverP r)
bool kMemory::map (kPage *page, unsigned address, bool write): bool kMemory::map (kPage *page, unsigned address, bool readonly = false):
return kMemory_arch_map (this, page, address, write) return kMemory_arch_map (this, page, address, readonly)
void kMemory::unmap (kPage *page, unsigned address): void kMemory::unmap (kPage *page, unsigned address):
kMemory_arch_unmap (this, page, address) kMemory_arch_unmap (this, page, address)
kPage *kMemory::get_mapping (unsigned address, bool *readonly): kPage *kMemory::get_mapping (unsigned address, bool *readonly):

View File

@ -29,6 +29,12 @@ unsigned phys_alloc (unsigned num):
void phys_free (unsigned page, unsigned num): void phys_free (unsigned page, unsigned num):
// Not supported. // Not supported.
#ifndef NDEBUG
void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = o->next:
if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
panic (num, msg)
#endif
#else #else
struct kFreePages: struct kFreePages:
@ -51,20 +57,20 @@ unsigned phys_alloc (unsigned num):
continue continue
if choice && choice->num < p->num: if choice && choice->num < p->num:
continue continue
if p->num == num:
if p->prev:
p->prev->next = p->next
else:
first_free = p->next
if p->next:
p->next->prev = p->prev
clear_page ((unsigned)p, num)
return (unsigned)p
choice = p choice = p
if !choice: if !choice:
// TODO: reorganizing may work to allow allocation. // TODO: reorganizing may work to allow allocation.
dbg_log ("range memory allocation failed") dpanic (0x03948859, "range memory allocation failed")
return 0 return 0
if choice->num == num:
if choice->prev:
choice->prev->next = choice->next
else:
first_free = choice->next
if choice->next:
choice->next->prev = choice->prev
clear_page ((unsigned)choice, num)
return (unsigned)choice
choice->num -= num choice->num -= num
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS) unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
clear_page (ret, num) clear_page (ret, num)
@ -122,6 +128,28 @@ void phys_free (unsigned page, unsigned num):
n->next->prev = n n->next->prev = n
p->next = n p->next = n
n->num = num n->num = num
#ifndef NDEBUG
void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = (kObject *)o->next:
for kFreePages *p = first_free; p; p = p->next:
if (unsigned)o >= (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
panic (num, msg)
#endif
#endif
#ifndef NDEBUG
void check_memory (kMemory *mem, unsigned num, char const *msg):
check_impl (mem->pages, num, msg)
check_impl (mem->threads, num, msg)
check_impl (mem->receivers, num, msg)
check_impl (mem->capses, num, msg)
check_impl (mem->memories, num, msg)
for kMemory *m = mem->memories; m; m = (kMemory *)m->next:
check_memory (m, num, msg)
void check (unsigned num, char const *msg):
check_memory (&top_memory, num, msg)
#endif #endif
unsigned raw_zalloc (): unsigned raw_zalloc ():
@ -132,7 +160,8 @@ void raw_pfree (unsigned page):
unsigned kMemory::zalloc (): unsigned kMemory::zalloc ():
if !use (): if !use ():
dbg_log ("limit reached: allocation not allowed") dpanic (0x34638920, "limit reached: allocation not allowed")
dbg_log ("limit reached: allocation not allowed\n")
return NULL return NULL
return raw_zalloc () return raw_zalloc ()

View File

@ -21,96 +21,85 @@
void kThread_arch_init (kThread *thread): void kThread_arch_init (kThread *thread):
thread->arch.at = 0 thread->arch.at = 0
thread->arch.v0 = 0 for unsigned i = 0; i < 2; ++i:
thread->arch.v1 = 0 thread->arch.v[i] = 0
thread->arch.a0 = 0 thread->arch.k[i] = 0
thread->arch.a1 = 0 for unsigned i = 0; i < 4; ++i:
thread->arch.a2 = 0 thread->arch.a[i] = 0
thread->arch.a3 = 0 for unsigned i = 0; i < 10; ++i:
thread->arch.t0 = 0 thread->arch.t[i] = 0
thread->arch.t1 = 0
thread->arch.t2 = 0
thread->arch.t3 = 0
thread->arch.t4 = 0
thread->arch.t5 = 0
thread->arch.t6 = 0
thread->arch.t7 = 0
thread->arch.t8 = 0
thread->arch.t9 = 0
thread->arch.gp = 0 thread->arch.gp = 0
thread->arch.fp = 0 thread->arch.fp = 0
thread->arch.ra = 0 thread->arch.ra = 0
thread->arch.hi = 0 thread->arch.hi = 0
thread->arch.lo = 0 thread->arch.lo = 0
thread->arch.k0 = 0
thread->arch.k1 = 0
void kThread_arch_receive (kThread *thread, Num cap_protected, Num recv_protected, Num *data): void kThread_arch_receive (kThread *thread, Num cap_protected, Num recv_protected, Num *data):
thread->arch.a0 = data[0].l thread->arch.a[0] = data[0].l
thread->arch.a1 = data[0].h thread->arch.a[1] = data[0].h
thread->arch.a2 = data[1].l thread->arch.a[2] = data[1].l
thread->arch.a3 = data[1].h thread->arch.a[3] = data[1].h
thread->arch.s0 = cap_protected.l thread->arch.s[0] = cap_protected.l
thread->arch.s1 = cap_protected.h thread->arch.s[1] = cap_protected.h
thread->arch.s2 = recv_protected.l thread->arch.s[2] = recv_protected.l
thread->arch.s3 = recv_protected.h thread->arch.s[3] = recv_protected.h
unsigned *kThread_arch_info (kThread *thread, unsigned num): unsigned *kThread_arch_info (kThread *thread, unsigned num):
switch num: switch num:
case 1: case 1:
return &thread->arch.at return &thread->arch.at
case 2: case 2:
return &thread->arch.v0 return &thread->arch.v[0]
case 3: case 3:
return &thread->arch.v1 return &thread->arch.v[1]
case 4: case 4:
return &thread->arch.a0 return &thread->arch.a[0]
case 5: case 5:
return &thread->arch.a1 return &thread->arch.a[1]
case 6: case 6:
return &thread->arch.a2 return &thread->arch.a[2]
case 7: case 7:
return &thread->arch.a3 return &thread->arch.a[3]
case 8: case 8:
return &thread->arch.t0 return &thread->arch.t[0]
case 9: case 9:
return &thread->arch.t1 return &thread->arch.t[1]
case 10: case 10:
return &thread->arch.t2 return &thread->arch.t[2]
case 11: case 11:
return &thread->arch.t3 return &thread->arch.t[3]
case 12: case 12:
return &thread->arch.t4 return &thread->arch.t[4]
case 13: case 13:
return &thread->arch.t5 return &thread->arch.t[5]
case 14: case 14:
return &thread->arch.t6 return &thread->arch.t[6]
case 15: case 15:
return &thread->arch.t7 return &thread->arch.t[7]
case 16: case 16:
return &thread->arch.s0 return &thread->arch.s[0]
case 17: case 17:
return &thread->arch.s1 return &thread->arch.s[1]
case 18: case 18:
return &thread->arch.s2 return &thread->arch.s[2]
case 19: case 19:
return &thread->arch.s3 return &thread->arch.s[3]
case 20: case 20:
return &thread->arch.s4 return &thread->arch.s[4]
case 21: case 21:
return &thread->arch.s5 return &thread->arch.s[5]
case 22: case 22:
return &thread->arch.s6 return &thread->arch.s[6]
case 23: case 23:
return &thread->arch.s7 return &thread->arch.s[7]
case 24: case 24:
return &thread->arch.t8 return &thread->arch.t[8]
case 25: case 25:
return &thread->arch.t9 return &thread->arch.t[9]
case 26: case 26:
return &thread->arch.k0 return &thread->arch.k[0]
case 27: case 27:
return &thread->arch.k1 return &thread->arch.k[1]
case 28: case 28:
return &thread->arch.gp return &thread->arch.gp
case 29: case 29:
@ -205,6 +194,7 @@ static unsigned make_entry_lo (kPage *page, bool readonly):
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address, bool readonly): bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address, bool readonly):
if address >= 0x80000000: if address >= 0x80000000:
panic (0x32134293, "trying to map to kernel address")
return false return false
address &= PAGE_MASK address &= PAGE_MASK
if !mem->arch.directory: if !mem->arch.directory:

View File

@ -72,47 +72,23 @@
#define SAVE_PC (6 * 4) #define SAVE_PC (6 * 4)
#define SAVE_SP (SAVE_PC + 4) #define SAVE_SP (SAVE_PC + 4)
#define SAVE_AT (SAVE_SP + 4) #define SAVE_AT (SAVE_SP + 4)
#define SAVE_V0 (SAVE_AT + 4) #define SAVE_V (SAVE_AT + 4)
#define SAVE_V1 (SAVE_V0 + 4) #define SAVE_A (SAVE_V + 2 * 4)
#define SAVE_A0 (SAVE_V1 + 4) #define SAVE_T (SAVE_A + 4 * 4)
#define SAVE_A1 (SAVE_A0 + 4) #define SAVE_S (SAVE_T + 10 * 4)
#define SAVE_A2 (SAVE_A1 + 4) #define SAVE_GP (SAVE_S + 8 * 4)
#define SAVE_A3 (SAVE_A2 + 4)
#define SAVE_T0 (SAVE_A3 + 4)
#define SAVE_T1 (SAVE_T0 + 4)
#define SAVE_T2 (SAVE_T1 + 4)
#define SAVE_T3 (SAVE_T2 + 4)
#define SAVE_T4 (SAVE_T3 + 4)
#define SAVE_T5 (SAVE_T4 + 4)
#define SAVE_T6 (SAVE_T5 + 4)
#define SAVE_T7 (SAVE_T6 + 4)
#define SAVE_T8 (SAVE_T7 + 4)
#define SAVE_T9 (SAVE_T8 + 4)
#define SAVE_S0 (SAVE_T9 + 4)
#define SAVE_S1 (SAVE_S0 + 4)
#define SAVE_S2 (SAVE_S1 + 4)
#define SAVE_S3 (SAVE_S2 + 4)
#define SAVE_S4 (SAVE_S3 + 4)
#define SAVE_S5 (SAVE_S4 + 4)
#define SAVE_S6 (SAVE_S5 + 4)
#define SAVE_S7 (SAVE_S6 + 4)
#define SAVE_GP (SAVE_S7 + 4)
#define SAVE_FP (SAVE_GP + 4) #define SAVE_FP (SAVE_GP + 4)
#define SAVE_RA (SAVE_FP + 4) #define SAVE_RA (SAVE_FP + 4)
#define SAVE_HI (SAVE_RA + 4) #define SAVE_HI (SAVE_RA + 4)
#define SAVE_LO (SAVE_HI + 4) #define SAVE_LO (SAVE_HI + 4)
#define SAVE_K0 (SAVE_LO + 4) #define SAVE_K (SAVE_LO + 4)
#define SAVE_K1 (SAVE_K0 + 4)
#ifndef ASM #ifndef ASM
void flush_tlb (unsigned asid) void flush_tlb (unsigned asid)
struct kThread_arch: struct kThread_arch:
unsigned at, v0, v1, a0, a1, a2, a3 unsigned at, v[2], a[4], t[10], s[8], gp, fp, ra, hi, lo, k[2]
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
unsigned s0, s1, s2, s3, s4, s5, s6, s7
unsigned gp, fp, ra, hi, lo, k0, k1
// The following is used for page mapping. // The following is used for page mapping.
// Each Memory has a two directories with 0x400 entries, // Each Memory has a two directories with 0x400 entries,

View File

@ -118,49 +118,48 @@ start_idle: // 280
// TODO: save only fragile registers now, the rest on task switch. // TODO: save only fragile registers now, the rest on task switch.
kernel_exit: kernel_exit:
#ifndef NDEBUG #ifndef NDEBUG
// Allow interrupts to set EPC and friends. // Interrupts were enabled in the kernel; set them to usermode setting again.
mfc0 $k0, $CP0_STATUS mfc0 $k0, $CP0_STATUS
ori $k0, $k0, 0xff13 ori $k0, $k0, 0xff13
mtc0 $k0, $CP0_STATUS mtc0 $k0, $CP0_STATUS
#endif #endif
sw $v0, -0xd8c($zero)
lw $k0, SAVE_PC($v0) lw $k0, SAVE_PC($v0)
mtc0 $k0, $CP0_EPC mtc0 $k0, $CP0_EPC
lw $k0, SAVE_LO($v0) lw $k0, SAVE_LO($v0)
lw $k1, SAVE_HI($v0) lw $k1, SAVE_HI($v0)
mtlo $k0 mtlo $k0
mthi $k1 mthi $k1
lw $v1, SAVE_V1($v0) lw $v1, SAVE_V + 1 * 4($v0)
lw $a0, SAVE_A0($v0) lw $a0, SAVE_A + 0 * 4($v0)
lw $a1, SAVE_A1($v0) lw $a1, SAVE_A + 1 * 4($v0)
lw $a2, SAVE_A2($v0) lw $a2, SAVE_A + 2 * 4($v0)
lw $a3, SAVE_A3($v0) lw $a3, SAVE_A + 3 * 4($v0)
lw $t0, SAVE_T0($v0) lw $t0, SAVE_T + 0 * 4($v0)
lw $t1, SAVE_T1($v0) lw $t1, SAVE_T + 1 * 4($v0)
lw $t2, SAVE_T2($v0) lw $t2, SAVE_T + 2 * 4($v0)
lw $t3, SAVE_T3($v0) lw $t3, SAVE_T + 3 * 4($v0)
lw $t4, SAVE_T4($v0) lw $t4, SAVE_T + 4 * 4($v0)
lw $t5, SAVE_T5($v0) lw $t5, SAVE_T + 5 * 4($v0)
lw $t6, SAVE_T6($v0) lw $t6, SAVE_T + 6 * 4($v0)
lw $t7, SAVE_T7($v0) lw $t7, SAVE_T + 7 * 4($v0)
lw $t8, SAVE_T8($v0) lw $t8, SAVE_T + 8 * 4($v0)
lw $t9, SAVE_T9($v0) lw $t9, SAVE_T + 9 * 4($v0)
lw $s0, SAVE_S0($v0) lw $s0, SAVE_S + 0 * 4($v0)
lw $s1, SAVE_S1($v0) lw $s1, SAVE_S + 1 * 4($v0)
lw $s2, SAVE_S2($v0) lw $s2, SAVE_S + 2 * 4($v0)
lw $s3, SAVE_S3($v0) lw $s3, SAVE_S + 3 * 4($v0)
lw $s4, SAVE_S4($v0) lw $s4, SAVE_S + 4 * 4($v0)
lw $s5, SAVE_S5($v0) lw $s5, SAVE_S + 5 * 4($v0)
lw $s6, SAVE_S6($v0) lw $s6, SAVE_S + 6 * 4($v0)
lw $s7, SAVE_S7($v0) lw $s7, SAVE_S + 7 * 4($v0)
lw $fp, SAVE_FP($v0) lw $fp, SAVE_FP($v0)
lw $ra, SAVE_RA($v0) lw $ra, SAVE_RA($v0)
lw $at, SAVE_AT($v0) lw $at, SAVE_AT($v0)
lw $k0, SAVE_K0($v0) lw $k0, SAVE_K + 0 * 4($v0)
lw $k1, SAVE_V0($v0) lw $k1, SAVE_V + 0 * 4($v0)
sw $k1, -0xd90($zero) sw $k1, -0xd90($zero)
lw $k1, SAVE_K1($v0) lw $k1, SAVE_K + 1 * 4($v0)
sw $v0, -0xd8c($zero)
lw $sp, SAVE_SP($v0) lw $sp, SAVE_SP($v0)
lw $gp, SAVE_GP($v0) lw $gp, SAVE_GP($v0)
lw $v0, -0xd90($zero) lw $v0, -0xd90($zero)
@ -175,36 +174,36 @@ save_regs:
sw $sp, SAVE_SP($k0) sw $sp, SAVE_SP($k0)
sw $fp, SAVE_FP($k0) sw $fp, SAVE_FP($k0)
sw $k1, SAVE_K1($k0) sw $k1, SAVE_K + 4($k0)
lw $k1, -0xd90($zero) lw $k1, -0xd90($zero)
sw $k1, SAVE_K0($k0) sw $k1, SAVE_K + 0($k0)
lw $k1, -0xd88($zero) lw $k1, -0xd88($zero)
sw $k1, SAVE_RA($k0) sw $k1, SAVE_RA($k0)
sw $v0, SAVE_V0($k0) sw $v0, SAVE_V + 0 * 4($k0)
sw $v1, SAVE_V1($k0) sw $v1, SAVE_V + 1 * 4($k0)
sw $a0, SAVE_A0($k0) sw $a0, SAVE_A + 0 * 4($k0)
sw $a1, SAVE_A1($k0) sw $a1, SAVE_A + 1 * 4($k0)
sw $a2, SAVE_A2($k0) sw $a2, SAVE_A + 2 * 4($k0)
sw $a3, SAVE_A3($k0) sw $a3, SAVE_A + 3 * 4($k0)
sw $t0, SAVE_T0($k0) sw $t0, SAVE_T + 0 * 4($k0)
sw $t1, SAVE_T1($k0) sw $t1, SAVE_T + 1 * 4($k0)
sw $t2, SAVE_T2($k0) sw $t2, SAVE_T + 2 * 4($k0)
sw $t3, SAVE_T3($k0) sw $t3, SAVE_T + 3 * 4($k0)
sw $t4, SAVE_T4($k0) sw $t4, SAVE_T + 4 * 4($k0)
sw $t5, SAVE_T5($k0) sw $t5, SAVE_T + 5 * 4($k0)
sw $t6, SAVE_T6($k0) sw $t6, SAVE_T + 6 * 4($k0)
sw $t7, SAVE_T7($k0) sw $t7, SAVE_T + 7 * 4($k0)
sw $t8, SAVE_T8($k0) sw $t8, SAVE_T + 8 * 4($k0)
sw $t9, SAVE_T9($k0) sw $t9, SAVE_T + 9 * 4($k0)
sw $s0, SAVE_S0($k0) sw $s0, SAVE_S + 0 * 4($k0)
sw $s1, SAVE_S1($k0) sw $s1, SAVE_S + 1 * 4($k0)
sw $s2, SAVE_S2($k0) sw $s2, SAVE_S + 2 * 4($k0)
sw $s3, SAVE_S3($k0) sw $s3, SAVE_S + 3 * 4($k0)
sw $s4, SAVE_S4($k0) sw $s4, SAVE_S + 4 * 4($k0)
sw $s5, SAVE_S5($k0) sw $s5, SAVE_S + 5 * 4($k0)
sw $s6, SAVE_S6($k0) sw $s6, SAVE_S + 6 * 4($k0)
sw $s7, SAVE_S7($k0) sw $s7, SAVE_S + 7 * 4($k0)
mfhi $v0 mfhi $v0
mflo $v1 mflo $v1
sw $v0, SAVE_HI($k0) sw $v0, SAVE_HI($k0)

View File

@ -22,6 +22,10 @@
#include "../kernel.hh" #include "../kernel.hh"
#include <elf.h> #include <elf.h>
#define NUM_SLOTS 4
#define NUM_CAPS 16
#define NUM_TMP_CAPS 2
static void init_idle (): static void init_idle ():
// initialize idle task as if it is currently running. // initialize idle task as if it is currently running.
idle.prev = NULL idle.prev = NULL
@ -111,7 +115,7 @@ static void init_threads ():
for unsigned i = 0; i < NUM_THREADS; ++i: for unsigned i = 0; i < NUM_THREADS; ++i:
kMemory *mem = top_memory.alloc_memory () kMemory *mem = top_memory.alloc_memory ()
assert (mem) assert (mem)
kThread *thread = mem->alloc_thread (3) kThread *thread = mem->alloc_thread (NUM_SLOTS)
kPage **pages = (kPage **)mem->zalloc () kPage **pages = (kPage **)mem->zalloc ()
Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i] Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i]
for unsigned j = 0; j < SELFMAG; ++j: for unsigned j = 0; j < SELFMAG; ++j:
@ -174,7 +178,7 @@ static void init_threads ():
panic (0x02220022, "out of memory"); panic (0x02220022, "out of memory");
return return
page->flags = Page::PAYING | Page::FRAME page->flags = Page::PAYING | Page::FRAME
if !mem->map (page, p, true): if !mem->map (page, p):
panic (0x33557799, "unable to map initial bss page") panic (0x33557799, "unable to map initial bss page")
return return
else: else:
@ -195,10 +199,13 @@ static void init_threads ():
kPage *stackpage = mem->alloc_page () kPage *stackpage = mem->alloc_page ()
stackpage->frame = mem->zalloc () stackpage->frame = mem->zalloc ()
stackpage->flags = Page::PAYING | Page::FRAME stackpage->flags = Page::PAYING | Page::FRAME
if !stackpage || !mem->map (stackpage, 0x7ffff000, true): if !stackpage || !mem->map (stackpage, 0x7ffff000):
panic (0x13151719, "unable to map initial stack page") panic (0x13151719, "unable to map initial stack page")
return return
thread->caps[0] = mem->alloc_caps (16) thread->caps[0] = mem->alloc_caps (NUM_CAPS)
thread->caps[__tmp_slot] = mem->alloc_caps (NUM_TMP_CAPS)
thread->arch.a[0] = NUM_SLOTS
thread->arch.a[1] = NUM_CAPS
kReceiver *recv = mem->alloc_receiver () kReceiver *recv = mem->alloc_receiver ()
recv->owner = thread recv->owner = thread
thread->receivers = recv thread->receivers = recv
@ -220,7 +227,10 @@ static void init_threads ():
// Initialize the kernel, finish by falling into the idle task. // Initialize the kernel, finish by falling into the idle task.
void init (unsigned mem): void init (unsigned mem):
#ifndef NDEBUG
dbg_code = 0 dbg_code = 0
#endif
must_wait = false
// Disable interrupts and set interrupt vectors to normal. // Disable interrupts and set interrupt vectors to normal.
cp0_set0 (CP0_STATUS) cp0_set0 (CP0_STATUS)
// Initialize kernel variables to empty. // Initialize kernel variables to empty.

View File

@ -25,6 +25,8 @@ void arch_flush_cache ():
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line)) __asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
static void handle_exit (): static void handle_exit ():
// 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
if !current || (current == &idle): if !current || (current == &idle):
schedule () schedule ()
if !current: if !current:
@ -35,6 +37,7 @@ static void handle_exit ():
current = &idle current = &idle
if old_current == current: if old_current == current:
return return
//dbg_send ((unsigned)current >> 12, 3)
arch_flush_cache () arch_flush_cache ()
if current != &idle: if current != &idle:
if (kMemory *)asids[current->address_space->arch.asid] != current->address_space: if (kMemory *)asids[current->address_space->arch.asid] != current->address_space:
@ -124,40 +127,40 @@ void flush_tlb (unsigned asid):
static void arch_invoke (): static void arch_invoke ():
kCapRef target kCapRef target
bool wait target = old_current->find_capability (old_current->arch.v[0], &must_wait)
target = old_current->find_capability (old_current->arch.v0, &wait)
do_schedule = false do_schedule = false
kCapability::Context msg kCapability::Context msg
unsigned num = old_current->arch.s2 unsigned num = old_current->arch.s[2]
unsigned first = old_current->arch.s3 unsigned first = old_current->arch.s[3]
if num: if num > 2:
if num > 10: dpanic (0x23451234, "too many capabilities")
num = 10 num = 2
if old_current->arch.s[1] < old_current->slots:
msg.caps = old_current->caps[old_current->arch.s[1]]
if msg.caps:
for unsigned i = 0; i < num && first + i < msg.caps->size; ++i:
unsigned code = old_current->arch.t[i]
msg.caps->cap (first + i)->invalidate ()
bool copy bool copy
if old_current->arch.s1 < old_current->slots: kCapRef t = old_current->find_capability (code, &copy)
msg.caps = old_current->caps[old_current->arch.s1] if t.valid ():
if msg.caps && first < msg.caps->size: msg.caps->clone (first + i, t, copy)
for unsigned i = first; i < num && i < msg.caps->size; ++i:
msg.caps->cap (i)->invalidate ()
kCapRef t = old_current->find_capability ((&old_current->arch.t0)[i], &copy)
if t:
msg.caps->clone (i, t, copy)
else: else:
if num:
dpanic (0x34566244, "num without caps")
if old_current->arch.s[1] != ~0:
dpanic (0x28849932, "non-~0 slot too high")
msg.caps = NULL msg.caps = NULL
else: if must_wait:
msg.caps = NULL old_current->recv_slot = old_current->arch.s[0]
if wait: if !target.valid ():
old_current->recv_slot = old_current->arch.s0 if must_wait:
old_current->wait () old_current->wait ()
if !target:
if (old_current->arch.v0 & ~CAP_COPY) != ~CAP_COPY:
panic (old_current->arch.v0, "debug")
// There must be no action here.
return return
msg.data[0] = Num (old_current->arch.a0, old_current->arch.a1) msg.data[0] = Num (old_current->arch.a[0], old_current->arch.a[1])
msg.data[1] = Num (old_current->arch.a2, old_current->arch.a3) msg.data[1] = Num (old_current->arch.a[2], old_current->arch.a[3])
target->invoke (&msg) target->invoke (&msg)
if do_schedule && !wait: if do_schedule && !must_wait:
// If the call was to schedule without wait, it isn't done yet. // If the call was to schedule without wait, it isn't done yet.
schedule () schedule ()
else if old_current != current && (old_current->flags & (Thread::RUNNING | Thread::WAITING)) == Thread::RUNNING: else if old_current != current && (old_current->flags & (Thread::RUNNING | Thread::WAITING)) == Thread::RUNNING:
@ -216,28 +219,35 @@ kThread *exception ():
// Syscall. // Syscall.
current->pc += 4 current->pc += 4
arch_invoke () arch_invoke ()
//check (0x88392883, "check error")
break break
case 9: case 9:
// Breakpoint. // Breakpoint.
#if 0 #if 0 || defined (NDEBUG)
current->raise (ERR_BREAKPOINT, 0) //current->raise (ERR_BREAKPOINT, 0)
#ifndef NDEBUG
current->pc += 4
#endif
#else #else
current->pc += 4 current->pc += 4
if current->arch.a0: if current->arch.a[0]:
if dbg_cap: if dbg_cap.valid ():
panic (0, "Break instruction while log capability was already set") dpanic (0, "Break instruction while log capability was already set")
break break
bool dummy bool dummy
dbg_cap = current->find_capability (current->arch.a1, &dummy) dbg_cap = current->find_capability (current->arch.a[1], &dummy)
if !dbg_cap: if !dbg_cap.valid ():
panic (0, "no log capability provided") dpanic (0, "no log capability provided")
break break
dbg_log ("debug capability registered. thread = ")
dbg_log_num ((unsigned)current)
dbg_log_char ('\n')
break break
if dbg_cap: if dbg_cap.valid ():
dbg_log_char (current->arch.a1) dbg_log_char (current->arch.a[1])
break
break break
#endif #endif
break
case 10: case 10:
// Reserved instruction. // Reserved instruction.
current->raise (ERR_RESERVED_INSTRUCTION, 0) current->raise (ERR_RESERVED_INSTRUCTION, 0)

View File

@ -140,9 +140,9 @@
static void __map_io (unsigned physical, unsigned mapping): static void __map_io (unsigned physical, unsigned mapping):
Page p = __my_memory.create_page () Page p = __my_memory.create_page ()
// false means not cachable; false means don't free when done. // false means not cachable; false means don't free when done.
p.alloc_physical (physical, 0, 0) p.alloc_physical (physical, false, false)
// true means writable. __my_memory.map (p, mapping)
__my_memory.map (p, mapping, true) free_cap (p)
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0) #define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0) #define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0)

View File

@ -19,18 +19,14 @@
#define ARCH #define ARCH
#include "kernel.hh" #include "kernel.hh"
#if 0
void dbg_log_char (unsigned ch): void dbg_log_char (unsigned ch):
if !dbg_cap: if !dbg_cap.valid ():
return return
Capability::Context c kCapability::Context c
c->recv_memory = NULL c.caps = NULL
c->caps = NULL
c.data[0] = ch c.data[0] = ch
c.data[1] = 0 c.data[1] = 0
dbg_cap->invoke (&c) dbg_cap->invoke (&c)
if dbg_cap->target->owner:
current = dbg_cap->target->owner
void dbg_log (char const *str): void dbg_log (char const *str):
while *str: while *str:
@ -42,26 +38,27 @@ void dbg_log_num (unsigned num):
dbg_log_char (encode[(num >> (4 * (7 - i))) & 0xf]) dbg_log_char (encode[(num >> (4 * (7 - i))) & 0xf])
return return
#if 1 || defined (NDEBUG)
void panic_impl (unsigned n, unsigned line, char const *name, char const *message): void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
Thread *who = current
// Stop all threads. // Stop all threads.
while first_scheduled: while first_scheduled:
first_scheduled->unrun () first_scheduled->unrun ()
for Receiver *r = first_alarm; r; r = r->next_alarm: for kReceiver *r = first_alarm; r; r = r->next_alarm:
if r->owner: if r->owner:
r->owner->unrun () r->owner->unrun ()
for unsigned i = 0; i < 32; ++i: for unsigned i = 0; i < 32; ++i:
if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner: if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner:
arch_interrupt_receiver[i]->owner->unrun () arch_interrupt_receiver[i]->owner->unrun ()
#ifndef NDEBUG
// If a log capability is registered, run its owner. // If a log capability is registered, run its owner.
if dbg_cap && dbg_cap->target->owner: if dbg_cap.valid () && 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: current = ") dbg_log ("Panic: caller = ")
dbg_log_num ((unsigned)who) dbg_log_num ((unsigned)old_current)
if who: if old_current:
dbg_log_char ('@') dbg_log_char ('@')
dbg_log_num ((unsigned)who->pc) dbg_log_num (old_current->pc)
dbg_log ("; ") dbg_log ("; ")
dbg_log (name) dbg_log (name)
dbg_log_char (':') dbg_log_char (':')
@ -72,6 +69,15 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
dbg_log_num (n) 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.
#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')
#endif
#else #else
void delay (unsigned ms): void delay (unsigned ms):
for unsigned t = 0; t < 8000 * ms; ++t: for unsigned t = 0; t < 8000 * ms; ++t:
@ -89,12 +95,9 @@ void set_leds (bool a, bool b):
else: else:
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
void dbg_log_char (unsigned ch): void dbg_send (unsigned n, unsigned bits):
void dbg_log (char const *str): for unsigned i = 0; i < bits; ++i:
void dbg_log_num (unsigned num): bool v = n & (1 << (bits - 1))
static void send (unsigned n):
for unsigned i = 0; i < 32; ++i:
bool v = n & (1 << 31)
set_leds (v, !v) set_leds (v, !v)
delay (350) delay (350)
set_leds (false, false) set_leds (false, false)
@ -107,7 +110,7 @@ static void send (unsigned n):
void panic_impl (unsigned n, unsigned line, char const *name, char const *message): void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
unsigned epc unsigned epc
cp0_get (CP0_EPC, epc) cp0_get (CP0_EPC, epc)
send (epc) dbg_send (epc, 32)
while true: while true:
send (n) dbg_send (n, 32)
#endif #endif