mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-01 17:42:05 +02:00
lcd working
This commit is contained in:
parent
cc1dc267d5
commit
bee84d53ec
42
alloc.ccp
42
alloc.ccp
@ -22,20 +22,20 @@
|
|||||||
#define NEXT(x) (((Object_base **)(x))[-1])
|
#define NEXT(x) (((Object_base **)(x))[-1])
|
||||||
#define SIZE (2 * sizeof (Object_base *))
|
#define SIZE (2 * sizeof (Object_base *))
|
||||||
|
|
||||||
bool Memory::use ():
|
bool Memory::use (unsigned num):
|
||||||
// Go up to parents, incrementing used.
|
// Go up to parents, incrementing used.
|
||||||
for Memory *m = this; m; m = m->address_space:
|
for Memory *m = this; m; m = m->address_space:
|
||||||
if used >= limit:
|
if used + num > limit:
|
||||||
// Not allowed. Restore used for all children.
|
// Not allowed. Restore used for all children.
|
||||||
for Memory *r = this; r != m; r = r->address_space:
|
for Memory *r = this; r != m; r = r->address_space:
|
||||||
--r->used
|
r->used -= num
|
||||||
return false
|
return false
|
||||||
++m->used
|
m->used += num
|
||||||
return true
|
return true
|
||||||
|
|
||||||
void Memory::unuse ():
|
void Memory::unuse (unsigned num):
|
||||||
for Memory *m = this; m; m = m->address_space:
|
for Memory *m = this; m; m = m->address_space:
|
||||||
--m->used
|
m->used -= num
|
||||||
|
|
||||||
void *Memory::search_free (unsigned size, void **first):
|
void *Memory::search_free (unsigned size, void **first):
|
||||||
Free *f
|
Free *f
|
||||||
@ -50,6 +50,7 @@ void *Memory::search_free (unsigned size, void **first):
|
|||||||
if !f:
|
if !f:
|
||||||
unsigned p = palloc ()
|
unsigned p = palloc ()
|
||||||
if !p:
|
if !p:
|
||||||
|
assert (false)
|
||||||
return NULL
|
return NULL
|
||||||
f = (Free *)(p + SIZE)
|
f = (Free *)(p + SIZE)
|
||||||
f->marker = ~0
|
f->marker = ~0
|
||||||
@ -134,21 +135,18 @@ Thread *Memory::alloc_thread ():
|
|||||||
ret->pc = 0
|
ret->pc = 0
|
||||||
ret->sp = 0
|
ret->sp = 0
|
||||||
Thread_arch_init (ret)
|
Thread_arch_init (ret)
|
||||||
ret->sleep_count = ~0
|
|
||||||
ret->flags = 0
|
ret->flags = 0
|
||||||
ret->schedule_prev = NULL
|
ret->schedule_prev = NULL
|
||||||
ret->schedule_next = NULL
|
ret->schedule_next = NULL
|
||||||
ret->receivers = NULL
|
ret->receivers = NULL
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Message *Memory::alloc_message (Receiver *target, unsigned protected_data):
|
Message *Memory::alloc_message (Receiver *target):
|
||||||
Message *ret = (Message *)search_free (sizeof (Message), (void **)&target->messages)
|
Message *ret = (Message *)search_free (sizeof (Message), (void **)&target->messages)
|
||||||
if !ret:
|
if !ret:
|
||||||
return NULL
|
return NULL
|
||||||
for unsigned i = 0; i < 4; ++i:
|
if !ret->next:
|
||||||
ret->capabilities[i] = NULL
|
target->last_message = ret
|
||||||
ret->data[i] = 0
|
|
||||||
ret->protected_data = protected_data
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Receiver *Memory::alloc_receiver ():
|
Receiver *Memory::alloc_receiver ():
|
||||||
@ -158,8 +156,10 @@ Receiver *Memory::alloc_receiver ():
|
|||||||
ret->owner = NULL
|
ret->owner = NULL
|
||||||
ret->prev_owned = NULL
|
ret->prev_owned = NULL
|
||||||
ret->next_owned = NULL
|
ret->next_owned = NULL
|
||||||
|
ret->alarm_count = ~0
|
||||||
ret->capabilities = NULL
|
ret->capabilities = NULL
|
||||||
ret->messages = NULL
|
ret->messages = NULL
|
||||||
|
ret->last_message = NULL
|
||||||
ret->reply_protected_data = ~0
|
ret->reply_protected_data = ~0
|
||||||
ret->protected_only = false
|
ret->protected_only = false
|
||||||
return ret
|
return ret
|
||||||
@ -251,9 +251,18 @@ void Memory::free_thread (Thread *thread):
|
|||||||
thread->receivers->orphan ()
|
thread->receivers->orphan ()
|
||||||
free_obj (thread)
|
free_obj (thread)
|
||||||
|
|
||||||
void Memory::free_message (Message *message):
|
void Memory::free_message (Receiver *owner, Message *message):
|
||||||
|
if message->prev:
|
||||||
|
message->prev->next = message->next
|
||||||
|
else:
|
||||||
|
owner->messages = message->next
|
||||||
|
if message->next:
|
||||||
|
message->next->prev = message->prev
|
||||||
|
else:
|
||||||
|
owner->last_message = message->prev
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
free_capability (message->capabilities[i])
|
if message->capabilities[i]:
|
||||||
|
free_capability (message->capabilities[i])
|
||||||
free_obj (message)
|
free_obj (message)
|
||||||
|
|
||||||
void Memory::free_receiver (Receiver *receiver):
|
void Memory::free_receiver (Receiver *receiver):
|
||||||
@ -261,7 +270,7 @@ void Memory::free_receiver (Receiver *receiver):
|
|||||||
while receiver->capabilities:
|
while receiver->capabilities:
|
||||||
receiver->capabilities->invalidate ()
|
receiver->capabilities->invalidate ()
|
||||||
while receiver->messages:
|
while receiver->messages:
|
||||||
free_message (receiver->messages)
|
free_message (receiver, receiver->messages)
|
||||||
free_obj (receiver)
|
free_obj (receiver)
|
||||||
|
|
||||||
void Receiver::orphan ():
|
void Receiver::orphan ():
|
||||||
@ -346,7 +355,8 @@ void Page::forget ():
|
|||||||
data.share_prev = NULL
|
data.share_prev = NULL
|
||||||
data.share_next = NULL
|
data.share_next = NULL
|
||||||
else:
|
else:
|
||||||
if ~data.flags & PAGE_FLAG_PHYSICAL:
|
// If the page has a frame and should be freed, free it.
|
||||||
|
if !((data.flags ^ PAGE_FLAG_FRAME) & (PAGE_FLAG_PHYSICAL | PAGE_FLAG_FRAME)):
|
||||||
raw_pfree (data.frame)
|
raw_pfree (data.frame)
|
||||||
data.frame = 0
|
data.frame = 0
|
||||||
data.flags &= ~(PAGE_FLAG_FRAME | PAGE_FLAG_SHARED | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED)
|
data.flags &= ~(PAGE_FLAG_FRAME | PAGE_FLAG_SHARED | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED)
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
__start:
|
__start:
|
||||||
bal 1f
|
bal 1f
|
||||||
|
__hack_label:
|
||||||
nop
|
nop
|
||||||
.word _gp
|
.word _gp
|
||||||
1:
|
1:
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
// For some reason, it only works if the rows are input and the columns are output.
|
// For some reason, it only works if the rows are input and the columns are output.
|
||||||
|
|
||||||
static void event (bool release, unsigned row, unsigned col):
|
static void event (bool release, unsigned row, unsigned col):
|
||||||
kdebug ((release ? 0x10000 : 0) | (row << 8) | col)
|
|
||||||
|
|
||||||
#define COL_MASK 0x2000ffff
|
#define COL_MASK 0x2000ffff
|
||||||
#define ROW_MASK 0x000000ff
|
#define ROW_MASK 0x000000ff
|
||||||
|
@ -20,6 +20,13 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
|
#define assert(x) do { while (!(x)) kdebug (0, 0); } while (0)
|
||||||
|
|
||||||
|
// For now, support only 16 bpp.
|
||||||
|
// Screen is 800x480 tft.
|
||||||
|
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||||
|
#define frame_size (v * h * Bpp)
|
||||||
|
|
||||||
// Pin definitions, all in port 2.
|
// Pin definitions, all in port 2.
|
||||||
#define PWM_ENABLE (1 << 30)
|
#define PWM_ENABLE (1 << 30)
|
||||||
#define SPEN (1 << 0) //LCD_SPL
|
#define SPEN (1 << 0) //LCD_SPL
|
||||||
@ -37,22 +44,25 @@ static void set_backlight (bool state):
|
|||||||
PWM_CTR (0) = 0x3f
|
PWM_CTR (0) = 0x3f
|
||||||
GPIO_GPDR (2) &= ~PWM_ENABLE
|
GPIO_GPDR (2) &= ~PWM_ENABLE
|
||||||
|
|
||||||
static void reset ():
|
struct Descriptor:
|
||||||
|
unsigned next
|
||||||
|
unsigned frame
|
||||||
|
unsigned id
|
||||||
|
unsigned cmd
|
||||||
|
|
||||||
|
static void reset (unsigned physical_descriptor):
|
||||||
PWM_PER (0) = 300
|
PWM_PER (0) = 300
|
||||||
set_backlight (false)
|
set_backlight (true)
|
||||||
|
|
||||||
// initialize things.
|
// initialize things.
|
||||||
GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA)
|
GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA)
|
||||||
GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA
|
GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET
|
||||||
udelay (50)
|
udelay (50)
|
||||||
GPIO_GPDR (2) &= ~LCD_RET
|
GPIO_GPDR (2) &= ~LCD_RET
|
||||||
ddelay (2)
|
ddelay (2)
|
||||||
GPIO_GPDR (2) |= LCD_RET
|
GPIO_GPDR (2) |= LCD_RET
|
||||||
ddelay (1)
|
ddelay (1)
|
||||||
|
|
||||||
// For now, support only 16 bpp.
|
|
||||||
// Screen is 800x480 tft.
|
|
||||||
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
|
||||||
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
|
||||||
@ -60,55 +70,99 @@ static void reset ():
|
|||||||
LCD_DAH = (hs << 16) | (hs + h)
|
LCD_DAH = (hs << 16) | (hs + h)
|
||||||
LCD_VAT = ((hs + h) << 16) | (vs + v)
|
LCD_VAT = ((hs + h) << 16) | (vs + v)
|
||||||
#define MODE_TFT_GEN 0
|
#define MODE_TFT_GEN 0
|
||||||
#define PCLK_N (1 << 10)
|
|
||||||
#define VSYNC_N (1 << 8)
|
#define VSYNC_N (1 << 8)
|
||||||
LCD_CFG = MODE_TFT_GEN | PCLK_N | VSYNC_N
|
LCD_CFG = MODE_TFT_GEN | VSYNC_N
|
||||||
|
|
||||||
cpm_stop_lcd ()
|
cpm_stop_lcd ()
|
||||||
|
|
||||||
unsigned pllout = cpm_get_pllout ()
|
|
||||||
unsigned pixclock = fps * (hs + h) * (vs + v)
|
unsigned pixclock = fps * (hs + h) * (vs + v)
|
||||||
|
unsigned pllout = cpm_get_pllout ()
|
||||||
CPM_CFCR2 = pllout / pixclock - 1
|
CPM_CFCR2 = pllout / pixclock - 1
|
||||||
|
|
||||||
unsigned val = pllout / (pixclock * 4) - 1
|
unsigned val = pllout / (pixclock * 4) - 1
|
||||||
while val < 0xf && pllout / (val + 1) > 150000000:
|
assert (pllout / (val + 1) <= 150000000)
|
||||||
++val
|
assert (val <= 0xf)
|
||||||
cpm_set_lcdclk_div (val)
|
cpm_set_lcdclk_div (val)
|
||||||
CPM_CFCR |= CPM_CFCR_UPE
|
CPM_CFCR |= CPM_CFCR_UPE
|
||||||
|
|
||||||
cpm_start_lcd ()
|
cpm_start_lcd ()
|
||||||
|
|
||||||
udelay (1000)
|
udelay (1000)
|
||||||
//LCD_DA0 = framebuffer
|
LCD_DA0 = physical_descriptor
|
||||||
unsigned frame_size = v * h * Bpp
|
|
||||||
LCD_CMD0 = LCD_CMD_SOFINT | LCD_CMD_EOFINT | (frame_size << LCD_CMD_LEN_BIT)
|
|
||||||
lcd_set_ena ()
|
lcd_set_ena ()
|
||||||
lcd_enable_eof_intr ()
|
lcd_enable_eof_intr ()
|
||||||
|
|
||||||
int main ():
|
int main ():
|
||||||
|
// TODO: The descriptor takes an entire uncached page, because I don't know how to force a cache write-back. It's much better to do that instead.
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
map_pwm0 ()
|
map_pwm0 ()
|
||||||
map_lcd ()
|
map_lcd ()
|
||||||
map_cpm ()
|
map_cpm ()
|
||||||
|
|
||||||
reset ()
|
unsigned pages = (frame_size + 16 + ~PAGE_MASK) >> PAGE_BITS
|
||||||
|
assert (pages > CAPPAGE_SIZE && pages <= 2 * CAPPAGE_SIZE)
|
||||||
|
unsigned physical = alloc_range (__my_memory, pages)
|
||||||
|
assert (physical)
|
||||||
|
//Capability cappage[2]
|
||||||
|
//unsigned base[2]
|
||||||
|
//cappage[0] = memory_create_cappage (__my_memory, &base[0])
|
||||||
|
//cappage[1] = memory_create_cappage (__my_memory, &base[1])
|
||||||
|
for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
|
||||||
|
Capability page = memory_create_page (__my_memory)
|
||||||
|
//cappage_set (cappage[0], page, i)
|
||||||
|
alloc_physical (page, physical + i * PAGE_SIZE, 0, 1)
|
||||||
|
memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, 1)
|
||||||
|
drop (page)
|
||||||
|
for unsigned i = 0; i < pages - CAPPAGE_SIZE; ++i:
|
||||||
|
Capability page = memory_create_page (__my_memory)
|
||||||
|
//cappage_set (cappage[1], page, i)
|
||||||
|
alloc_physical (page, physical + (i + CAPPAGE_SIZE) * PAGE_SIZE, 0, 1)
|
||||||
|
memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + (i + CAPPAGE_SIZE) * PAGE_SIZE, 1)
|
||||||
|
drop (page)
|
||||||
|
unsigned og = 0
|
||||||
|
for unsigned y = 0; y < 480; ++y:
|
||||||
|
unsigned g = (y << 6) / 480
|
||||||
|
if g != og:
|
||||||
|
og = g
|
||||||
|
g = 0x3f
|
||||||
|
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||||
|
for unsigned x = 0; x < 800; ++x:
|
||||||
|
unsigned r = (x << 5) / 800
|
||||||
|
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||||
|
if r != olr:
|
||||||
|
olr = r
|
||||||
|
r = 0x1f
|
||||||
|
unsigned oyb = b
|
||||||
|
if y > 0:
|
||||||
|
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||||
|
if b != ob || b != oyb:
|
||||||
|
ob = b
|
||||||
|
b = 0x1f
|
||||||
|
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
|
||||||
|
Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size)
|
||||||
|
unsigned physical_descriptor = physical + frame_size
|
||||||
|
descriptor->next = physical_descriptor
|
||||||
|
descriptor->frame = physical
|
||||||
|
descriptor->id = 0xdeadbeef
|
||||||
|
descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
|
||||||
|
reset (physical_descriptor)
|
||||||
register_interrupt (IRQ_LCD)
|
register_interrupt (IRQ_LCD)
|
||||||
set_backlight (true)
|
set_backlight (true)
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
Message msg
|
Message msg
|
||||||
if !wait (&msg):
|
wait (&msg)
|
||||||
continue
|
|
||||||
switch msg.protected_data:
|
switch msg.protected_data:
|
||||||
case IRQ_LCD:
|
case IRQ_LCD:
|
||||||
kdebug (0)
|
lcd_clr_eof ()
|
||||||
LCD_STATE &= ~LCD_STATE_EOF
|
|
||||||
register_interrupt (IRQ_LCD)
|
register_interrupt (IRQ_LCD)
|
||||||
// TODO: allow callback
|
// TODO: allow callback
|
||||||
break
|
break
|
||||||
|
#if 0
|
||||||
case LCD_BACKLIGHT:
|
case LCD_BACKLIGHT:
|
||||||
set_backlight (msg.data[0])
|
set_backlight (msg.data[0])
|
||||||
break
|
break
|
||||||
case LCD_RESET:
|
case LCD_RESET:
|
||||||
reset ()
|
//reset (physical_descriptor)
|
||||||
break
|
break
|
||||||
|
#endif
|
||||||
|
197
invoke.ccp
197
invoke.ccp
@ -20,46 +20,59 @@
|
|||||||
|
|
||||||
// From user-provided, thus untrusted, data, find a capability.
|
// From user-provided, thus untrusted, data, find a capability.
|
||||||
Capability *Memory::find_capability (unsigned code, bool *copy):
|
Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||||
if !code:
|
|
||||||
return NULL
|
|
||||||
*copy = code & 2 ? true : false
|
*copy = code & 2 ? true : false
|
||||||
|
if !(code & ~3):
|
||||||
|
return NULL
|
||||||
if code & 1:
|
if code & 1:
|
||||||
// Cappage capability
|
// Cappage capability
|
||||||
unsigned num = (code & ~PAGE_MASK) >> 2
|
unsigned num = (code & ~PAGE_MASK) >> 2
|
||||||
if num >= CAPPAGE_SIZE:
|
if num >= CAPPAGE_SIZE:
|
||||||
|
panic (0x15544551, "invalid cappage index")
|
||||||
return NULL
|
return NULL
|
||||||
Capability *page = (Capability *)(code & PAGE_MASK)
|
unsigned page = code & PAGE_MASK
|
||||||
for Cappage *p = cappages; p; p = p->next:
|
for Cappage *p = cappages; p; p = p->next:
|
||||||
if p->data.frame == (unsigned)page:
|
if p->data.frame == page:
|
||||||
return &page[num]
|
return p->cap (num)
|
||||||
else:
|
else:
|
||||||
// Normal capability
|
// Normal capability
|
||||||
code &= ~3
|
Capability *target = (Capability *)(code & ~3)
|
||||||
for Capability *c = capabilities; c; c = c->next:
|
for Capability *c = capabilities; c; c = c->next:
|
||||||
if c == (Capability *)code:
|
if c == target:
|
||||||
return c
|
return c
|
||||||
|
dbg_send (code)
|
||||||
|
panic (0xfffeee00, "invalid capability")
|
||||||
return NULL
|
return NULL
|
||||||
|
|
||||||
// Try to deliver a message.
|
// Try to deliver a message.
|
||||||
bool Receiver::try_deliver ():
|
bool Receiver::try_deliver ():
|
||||||
if !messages || !owner || !owner->is_waiting ():
|
if !messages:
|
||||||
return false
|
return false
|
||||||
Message *m = messages
|
if !owner || !owner->is_waiting ():
|
||||||
|
dbg_send (3, 3)
|
||||||
|
return false
|
||||||
|
Message *m = last_message
|
||||||
if protected_only:
|
if protected_only:
|
||||||
for ; m; m = m->next:
|
for ; m; m = m->prev:
|
||||||
if m->protected_data == reply_protected_data:
|
if m->protected_data == reply_protected_data:
|
||||||
|
protected_only = false
|
||||||
break
|
break
|
||||||
if !m:
|
if !m:
|
||||||
return false
|
panic (0x32547688, "protected only")
|
||||||
|
return false
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
c.data[i] = m->data[i]
|
||||||
if m->capabilities[i]:
|
if m->capabilities[i]:
|
||||||
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||||
if !c.cap[i]:
|
if !c.cap[i]:
|
||||||
|
panic (0xffaaaaaa, "out of memory")
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
owner->address_space->free_capability (c.cap[i])
|
owner->address_space->free_capability (c.cap[i])
|
||||||
return false
|
return false
|
||||||
|
else:
|
||||||
|
c.cap[i] = NULL
|
||||||
Thread_arch_receive (owner, m->protected_data, &c)
|
Thread_arch_receive (owner, m->protected_data, &c)
|
||||||
|
address_space->free_message (this, m)
|
||||||
owner->unwait ()
|
owner->unwait ()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
@ -67,22 +80,41 @@ bool Receiver::try_deliver ():
|
|||||||
bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||||
bool tried_direct = false
|
bool tried_direct = false
|
||||||
if owner && owner->is_waiting () && (protected_data == reply_protected_data || !protected_only):
|
if owner && owner->is_waiting () && (protected_data == reply_protected_data || !protected_only):
|
||||||
|
Capability *orig[4]
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
if c->cap[i]:
|
if c->cap[i]:
|
||||||
c->cap[i] = owner->address_space->clone_capability (c->cap[i], c->copy[i])
|
orig[i] = c->cap[i]
|
||||||
|
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
||||||
if !c->cap[i]:
|
if !c->cap[i]:
|
||||||
|
panic (0xdddddddd, "out of memory")
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
owner->address_space->free_capability (c->cap[i])
|
owner->address_space->free_capability (c->cap[j])
|
||||||
|
c->cap[j] = orig[j]
|
||||||
|
c->cap[i] = orig[i]
|
||||||
tried_direct = true
|
tried_direct = true
|
||||||
break
|
break
|
||||||
if !tried_direct:
|
if !tried_direct:
|
||||||
|
if protected_data == reply_protected_data:
|
||||||
|
protected_only = false
|
||||||
Thread_arch_receive (owner, protected_data, c)
|
Thread_arch_receive (owner, protected_data, c)
|
||||||
owner->unwait ()
|
owner->unwait ()
|
||||||
return true
|
return true
|
||||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||||
Message *msg = address_space->alloc_message (this, protected_data)
|
Message *msg = address_space->alloc_message (this)
|
||||||
if !msg:
|
if !msg:
|
||||||
|
panic (0xbbbbbbbb, "out of memory")
|
||||||
return false
|
return false
|
||||||
|
msg->protected_data = protected_data
|
||||||
|
if protected_data == reply_protected_data:
|
||||||
|
// Put this message in the end (where it will be first seen). Clear the protected_only flag.
|
||||||
|
protected_only = false
|
||||||
|
if msg->next:
|
||||||
|
msg->next->prev = NULL
|
||||||
|
messages = msg->next
|
||||||
|
msg->next = NULL
|
||||||
|
msg->prev = last_message
|
||||||
|
msg->prev->next = msg
|
||||||
|
last_message = msg
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
msg->data[i] = c->data[i]
|
msg->data[i] = c->data[i]
|
||||||
if !c->cap[i]:
|
if !c->cap[i]:
|
||||||
@ -90,9 +122,10 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
|||||||
else:
|
else:
|
||||||
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
||||||
if !msg->capabilities[i]:
|
if !msg->capabilities[i]:
|
||||||
|
panic (0xcccccccc, "out of memory")
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
address_space->free_capability (msg->capabilities[j])
|
address_space->free_capability (msg->capabilities[j])
|
||||||
address_space->free_message (msg)
|
address_space->free_message (this, msg)
|
||||||
return false
|
return false
|
||||||
if tried_direct:
|
if tried_direct:
|
||||||
Thread_arch_receive_fail (owner)
|
Thread_arch_receive_fail (owner)
|
||||||
@ -144,6 +177,22 @@ static void reply_cap (Capability *cap, bool copy):
|
|||||||
else if reply_receiver:
|
else if reply_receiver:
|
||||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||||
|
|
||||||
|
static void reply_cappage (Cappage *cap, unsigned target):
|
||||||
|
Capability r
|
||||||
|
fill_cap (&r, target, (unsigned)cap)
|
||||||
|
Capability::Context c
|
||||||
|
for unsigned i = 1; i < 4; ++i:
|
||||||
|
c.data[i] = 0
|
||||||
|
c.cap[i] = NULL
|
||||||
|
c.copy[i] = false
|
||||||
|
c.data[0] = cap->data.frame
|
||||||
|
c.cap[0] = &r
|
||||||
|
c.copy[0] = true
|
||||||
|
if reply:
|
||||||
|
reply->invoke (&c)
|
||||||
|
else if reply_receiver:
|
||||||
|
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||||
|
|
||||||
static void reply_num (unsigned num):
|
static void reply_num (unsigned num):
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
c.data[0] = num
|
c.data[0] = num
|
||||||
@ -186,12 +235,35 @@ static void receiver_invoke (unsigned target, unsigned protected_data, Capabilit
|
|||||||
case CAP_RECEIVER_CREATE_CALL_CAPABILITY:
|
case CAP_RECEIVER_CREATE_CALL_CAPABILITY:
|
||||||
reply_cap (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL) | (c->data[1] ? 1 << CAP_RECEIVER_CALL_ASYNC : 0), protected_data)
|
reply_cap (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL) | (c->data[1] ? 1 << CAP_RECEIVER_CALL_ASYNC : 0), protected_data)
|
||||||
break
|
break
|
||||||
case CAP_RECEIVER_GET_REPLY_PROTECTED_DATA:
|
case CAP_RECEIVER_REPLY_PROTECTED_DATA:
|
||||||
reply_nums (receiver->reply_protected_data, receiver->protected_only ? 1 : 0)
|
reply_nums (receiver->reply_protected_data, receiver->protected_only ? 1 : 0)
|
||||||
|
if c->data[1]:
|
||||||
|
receiver->reply_protected_data = c->data[2]
|
||||||
break
|
break
|
||||||
case CAP_RECEIVER_SET_REPLY_PROTECTED_DATA:
|
case CAP_RECEIVER_ALARM:
|
||||||
receiver->reply_protected_data = c->data[1]
|
unsigned old = receiver->alarm_count
|
||||||
receiver->protected_only = c->data[2]
|
reply_num (old)
|
||||||
|
if c->data[1]:
|
||||||
|
receiver->alarm_count = c->data[2]
|
||||||
|
else:
|
||||||
|
receiver->alarm_count += c->data[2]
|
||||||
|
if (old == ~0) ^ (receiver->alarm_count == ~0):
|
||||||
|
// The alarm stopped or started.
|
||||||
|
if old == ~0:
|
||||||
|
// It started.
|
||||||
|
receiver->prev_alarm = NULL
|
||||||
|
receiver->next_alarm = first_alarm
|
||||||
|
if receiver->next_alarm:
|
||||||
|
receiver->next_alarm->prev_alarm = receiver
|
||||||
|
first_alarm = receiver
|
||||||
|
else:
|
||||||
|
// It stopped.
|
||||||
|
if receiver->prev_alarm:
|
||||||
|
receiver->prev_alarm->next_alarm = receiver->next_alarm
|
||||||
|
else:
|
||||||
|
first_alarm = receiver->next_alarm
|
||||||
|
if receiver->next_alarm:
|
||||||
|
receiver->next_alarm->prev_alarm = receiver->prev_alarm
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -234,7 +306,7 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
case CAPTYPE_CAPPAGE:
|
case CAPTYPE_CAPPAGE:
|
||||||
Cappage *ret = mem->alloc_cappage ()
|
Cappage *ret = mem->alloc_cappage ()
|
||||||
if ret:
|
if ret:
|
||||||
reply_cap (CAPTYPE_CAPPAGE | (rights & CAP_CAPPAGE_ALL_RIGHTS), (unsigned)ret)
|
reply_cappage (ret, CAPTYPE_CAPPAGE | (rights & CAP_CAPPAGE_ALL_RIGHTS))
|
||||||
else:
|
else:
|
||||||
reply_num (0)
|
reply_num (0)
|
||||||
break
|
break
|
||||||
@ -320,24 +392,17 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
unsigned v = (*value & c->data[3]) | (c->data[2] & c->data[3])
|
unsigned v = (*value & c->data[3]) | (c->data[2] & c->data[3])
|
||||||
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
|
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
|
||||||
if v & THREAD_FLAG_WAITING:
|
if v & THREAD_FLAG_WAITING:
|
||||||
thread->wait ()
|
if !(thread->is_waiting ()):
|
||||||
|
thread->wait ()
|
||||||
else
|
else
|
||||||
thread->unwait ()
|
if thread->is_waiting ():
|
||||||
|
thread->unwait ()
|
||||||
if (v & THREAD_FLAG_RUNNING) != (*value & THREAD_FLAG_RUNNING):
|
if (v & THREAD_FLAG_RUNNING) != (*value & THREAD_FLAG_RUNNING):
|
||||||
if v & THREAD_FLAG_RUNNING:
|
if v & THREAD_FLAG_RUNNING:
|
||||||
thread->run ()
|
thread->run ()
|
||||||
else
|
else
|
||||||
thread->unrun ()
|
thread->unrun ()
|
||||||
break
|
break
|
||||||
case CAP_THREAD_INFO_SLEEP:
|
|
||||||
value = &thread->sleep_count
|
|
||||||
if thread->flags & THREAD_FLAG_WAITING:
|
|
||||||
unsigned newval = (*value & ~c->data[3]) | (c->data[2] & c->data[3])
|
|
||||||
if *value == ~0 && newval != ~0:
|
|
||||||
thread->sleep ()
|
|
||||||
else if *value != ~0 && newval == ~0:
|
|
||||||
thread->unsleep ()
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
value = Thread_arch_info (thread, c->data[1])
|
value = Thread_arch_info (thread, c->data[1])
|
||||||
break
|
break
|
||||||
@ -349,13 +414,7 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
break
|
break
|
||||||
case CAP_THREAD_SCHEDULE:
|
case CAP_THREAD_SCHEDULE:
|
||||||
schedule ()
|
schedule ()
|
||||||
break
|
do_schedule = true
|
||||||
case CAP_THREAD_DEBUG:
|
|
||||||
dbg_led (true, true, true)
|
|
||||||
dbg_sleep (100)
|
|
||||||
dbg_led (false, false, false)
|
|
||||||
dbg_sleep (100)
|
|
||||||
//dbg_send (c->data[1], 5)
|
|
||||||
break
|
break
|
||||||
case CAP_THREAD_REGISTER_INTERRUPT:
|
case CAP_THREAD_REGISTER_INTERRUPT:
|
||||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||||
@ -371,18 +430,45 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
((Thread *)c->cap[0]->protected_data)->flags |= THREAD_FLAG_PRIV
|
((Thread *)c->cap[0]->protected_data)->flags |= THREAD_FLAG_PRIV
|
||||||
reply_cap (CAPTYPE_THREAD | (c->data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), c->cap[0]->protected_data)
|
reply_cap (CAPTYPE_THREAD | (c->data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), c->cap[0]->protected_data)
|
||||||
break
|
break
|
||||||
|
case CAP_THREAD_ALLOC_RANGE:
|
||||||
|
// Threads with access to this call are trusted, so not much sanity checking is done.
|
||||||
|
Memory *mem = (Memory *)c->cap[1]->protected_data
|
||||||
|
if !mem->use (c->data[1]):
|
||||||
|
reply_num (0)
|
||||||
|
break
|
||||||
|
unsigned data = phys_alloc (c->data[1])
|
||||||
|
if !data:
|
||||||
|
mem->unuse (c->data[1])
|
||||||
|
reply_num (0)
|
||||||
|
break
|
||||||
|
reply_num (data - 0x80000000)
|
||||||
|
break
|
||||||
case CAP_THREAD_ALLOC_PHYSICAL:
|
case CAP_THREAD_ALLOC_PHYSICAL:
|
||||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||||
Page *page = (Page *)c->cap[0]->protected_data
|
Page *page = (Page *)c->cap[0]->protected_data
|
||||||
page->forget ()
|
page->forget ()
|
||||||
if page->data.flags & PAGE_FLAG_PAYING:
|
if !(c->data[2] & 2):
|
||||||
page->data.flags &= ~PAGE_FLAG_PAYING
|
if page->data.flags & PAGE_FLAG_PAYING:
|
||||||
page->address_space->unuse ()
|
page->data.flags &= ~PAGE_FLAG_PAYING
|
||||||
page->data.frame = c->data[1] & PAGE_MASK
|
page->address_space->unuse ()
|
||||||
if c->data[1] & 1:
|
|
||||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL
|
|
||||||
else:
|
else:
|
||||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED
|
// This is for mapping allocated ranges. They are already paid for. Record that.
|
||||||
|
if page->data.flags & PAGE_FLAG_PAYING:
|
||||||
|
page->address_space->unuse ()
|
||||||
|
else:
|
||||||
|
page->data.flags |= PAGE_FLAG_PAYING
|
||||||
|
page->data.frame = c->data[1]
|
||||||
|
page->data.flags |= PAGE_FLAG_FRAME
|
||||||
|
if !(c->data[2] & 1):
|
||||||
|
page->data.flags |= PAGE_FLAG_UNCACHED
|
||||||
|
if !(c->data[2] & 2):
|
||||||
|
page->data.flags |= PAGE_FLAG_PHYSICAL
|
||||||
|
Page_arch_update_mapping (page)
|
||||||
|
break
|
||||||
|
case CAP_THREAD_PHYSICAL_ADDRESS:
|
||||||
|
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||||
|
Page *page = (Page *)c->cap[1]->protected_data
|
||||||
|
reply_num (page->data.frame & ~0xc0000000)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -652,7 +738,7 @@ static void capability_invoke (unsigned target, unsigned protected_data, Capabil
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
||||||
static bool kernel_invoke (unsigned target, unsigned protected_data, Capability::Context *c, Capability *self):
|
static void kernel_invoke (unsigned target, unsigned protected_data, Capability::Context *c, Capability *self):
|
||||||
// Kernel calling convention:
|
// Kernel calling convention:
|
||||||
// data[0] is the request.
|
// data[0] is the request.
|
||||||
// cap[0] is the reply capability
|
// cap[0] is the reply capability
|
||||||
@ -674,7 +760,7 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
// Kernel call: don't create actual capablities.
|
// Kernel call: don't create actual capablities.
|
||||||
c->cap[0] = NULL
|
c->cap[0] = NULL
|
||||||
kernel_invoke ((unsigned)c0->target, c0->protected_data, c, c0)
|
kernel_invoke ((unsigned)c0->target, c0->protected_data, c, c0)
|
||||||
return true
|
return
|
||||||
if (target & (CAPTYPE_MASK | (1 << CAP_RECEIVER_REPLY))) == (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_REPLY)):
|
if (target & (CAPTYPE_MASK | (1 << CAP_RECEIVER_REPLY))) == (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_REPLY)):
|
||||||
// This is a reply capability.
|
// This is a reply capability.
|
||||||
Receiver *r = (Receiver *)protected_data
|
Receiver *r = (Receiver *)protected_data
|
||||||
@ -686,16 +772,16 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
while self->sibling_next:
|
while self->sibling_next:
|
||||||
self->sibling_next->invalidate ()
|
self->sibling_next->invalidate ()
|
||||||
self->invalidate ()
|
self->invalidate ()
|
||||||
return true
|
return
|
||||||
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
||||||
// You are not allowed to perform this operation.
|
// You are not allowed to perform this operation.
|
||||||
dbg_send (1, 2)
|
dbg_send (1, 2)
|
||||||
dbg_send (c->data[0])
|
dbg_send (c->data[0])
|
||||||
return true
|
return
|
||||||
reply = c->cap[0]
|
reply = c->cap[0]
|
||||||
if c->data[0] == CAP_DEGRADE:
|
if c->data[0] == CAP_DEGRADE:
|
||||||
reply_cap (target & c->data[1], protected_data)
|
reply_cap (target & c->data[1], protected_data)
|
||||||
return true
|
return
|
||||||
switch target & CAPTYPE_MASK:
|
switch target & CAPTYPE_MASK:
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
receiver_invoke (target, protected_data, c)
|
receiver_invoke (target, protected_data, c)
|
||||||
@ -717,12 +803,13 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
panic (0x99337744, "invalid capability type invoked")
|
panic (0x99337744, "invalid capability type invoked")
|
||||||
return true
|
return
|
||||||
|
|
||||||
bool Capability::invoke (Capability::Context *c):
|
void Capability::invoke (Capability::Context *c):
|
||||||
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.
|
||||||
return target->send_message (protected_data, c)
|
target->send_message (protected_data, c)
|
||||||
|
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.
|
||||||
reply_receiver = NULL
|
reply_receiver = NULL
|
||||||
return kernel_invoke ((unsigned)target, protected_data, c, this)
|
kernel_invoke ((unsigned)target, protected_data, c, this)
|
||||||
|
432
iris.h
432
iris.h
@ -52,8 +52,8 @@ extern "C" {
|
|||||||
#define CAP_RECEIVER_SET_OWNER 1
|
#define CAP_RECEIVER_SET_OWNER 1
|
||||||
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
||||||
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
||||||
#define CAP_RECEIVER_GET_REPLY_PROTECTED_DATA 4
|
#define CAP_RECEIVER_REPLY_PROTECTED_DATA 4
|
||||||
#define CAP_RECEIVER_SET_REPLY_PROTECTED_DATA 5
|
#define CAP_RECEIVER_ALARM 5
|
||||||
#define CAP_RECEIVER_ALL_RIGHTS 0x7f
|
#define CAP_RECEIVER_ALL_RIGHTS 0x7f
|
||||||
/* Not an operation; a capability with this bit set is a call capability. */
|
/* Not an operation; a capability with this bit set is a call capability. */
|
||||||
#define CAP_RECEIVER_CALL 7
|
#define CAP_RECEIVER_CALL 7
|
||||||
@ -73,19 +73,19 @@ extern "C" {
|
|||||||
|
|
||||||
#define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */
|
#define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */
|
||||||
#define CAP_THREAD_SCHEDULE 2
|
#define CAP_THREAD_SCHEDULE 2
|
||||||
#define CAP_THREAD_DEBUG 3
|
#define CAP_THREAD_ALLOC_RANGE 3
|
||||||
|
#define CAP_THREAD_PHYSICAL_ADDRESS 4
|
||||||
#define CAP_THREAD_ALLOC_PHYSICAL 5
|
#define CAP_THREAD_ALLOC_PHYSICAL 5
|
||||||
#define CAP_THREAD_MAKE_PRIV 6
|
#define CAP_THREAD_MAKE_PRIV 6
|
||||||
#define CAP_THREAD_GET_TOP_MEMORY 7
|
#define CAP_THREAD_GET_TOP_MEMORY 7
|
||||||
#define CAP_THREAD_REGISTER_INTERRUPT 8
|
#define CAP_THREAD_REGISTER_INTERRUPT 8
|
||||||
#define CAP_THREAD_ALL_RIGHTS 0x1f
|
#define CAP_THREAD_ALL_RIGHTS 0x0f
|
||||||
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL))
|
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL) | (1 << CAP_THREAD_PHYSICAL_ADDRESS))
|
||||||
|
|
||||||
/* These get/set_info are not arch-specific. */
|
/* These get/set_info are not arch-specific. */
|
||||||
#define CAP_THREAD_INFO_PC ~0
|
#define CAP_THREAD_INFO_PC ~0
|
||||||
#define CAP_THREAD_INFO_SP ~1
|
#define CAP_THREAD_INFO_SP ~1
|
||||||
#define CAP_THREAD_INFO_FLAGS ~2
|
#define CAP_THREAD_INFO_FLAGS ~2
|
||||||
#define CAP_THREAD_INFO_SLEEP ~3
|
|
||||||
/* Flag values for processor state */
|
/* Flag values for processor state */
|
||||||
#define THREAD_FLAG_PRIV 0x80000000
|
#define THREAD_FLAG_PRIV 0x80000000
|
||||||
#define THREAD_FLAG_WAITING 0x40000000
|
#define THREAD_FLAG_WAITING 0x40000000
|
||||||
@ -141,6 +141,11 @@ Capability cap_copy (Capability src)
|
|||||||
return src | 2;
|
return src | 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Capability cappage_cap (unsigned base, unsigned idx)
|
||||||
|
{
|
||||||
|
return base | (idx << 2) | 1;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct Message
|
typedef struct Message
|
||||||
{
|
{
|
||||||
unsigned data[4];
|
unsigned data[4];
|
||||||
@ -148,11 +153,11 @@ typedef struct Message
|
|||||||
unsigned protected_data; /* only used for receiving. */
|
unsigned protected_data; /* only used for receiving. */
|
||||||
} Message;
|
} Message;
|
||||||
|
|
||||||
static int invoke (Capability target, Message *msg)
|
static void invoke (Capability target, Message *msg)
|
||||||
{
|
{
|
||||||
unsigned ret;
|
unsigned ret;
|
||||||
__asm__ volatile ("lw $v0, %1\n"
|
__asm__ volatile ("lw $v0, %0\n"
|
||||||
"\tlw $a3, %2\n"
|
"\tlw $a3, %1\n"
|
||||||
"\tlw $t0, 0($a3)\n"
|
"\tlw $t0, 0($a3)\n"
|
||||||
"\tlw $t1, 4($a3)\n"
|
"\tlw $t1, 4($a3)\n"
|
||||||
"\tlw $t2, 8($a3)\n"
|
"\tlw $t2, 8($a3)\n"
|
||||||
@ -161,20 +166,45 @@ static int invoke (Capability target, Message *msg)
|
|||||||
"\tlw $a1, 20($a3)\n"
|
"\tlw $a1, 20($a3)\n"
|
||||||
"\tlw $a2, 24($a3)\n"
|
"\tlw $a2, 24($a3)\n"
|
||||||
"\tlw $a3, 28($a3)\n"
|
"\tlw $a3, 28($a3)\n"
|
||||||
"\tsyscall\n"
|
"\tsyscall"
|
||||||
"\tmove %0, $v0"
|
:
|
||||||
: "=r"(ret)
|
|
||||||
: "m"(target), "m"(msg)
|
: "m"(target), "m"(msg)
|
||||||
: "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
: "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wait (Message *msg)
|
static void wait (Message *msg)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
__asm__ volatile ("li $v0, 2\n"
|
__asm__ volatile ("li $v0, 2\n"
|
||||||
"\tsyscall\n"
|
"\tsyscall\n"
|
||||||
"\tsw $v0, %0\n"
|
"\tlw $v0, %0\n"
|
||||||
|
"\tsw $t0, 0($v0)\n"
|
||||||
|
"\tsw $t1, 4($v0)\n"
|
||||||
|
"\tsw $t2, 8($v0)\n"
|
||||||
|
"\tsw $t3, 12($v0)\n"
|
||||||
|
"\tsw $a0, 16($v0)\n"
|
||||||
|
"\tsw $a1, 20($v0)\n"
|
||||||
|
"\tsw $a2, 24($v0)\n"
|
||||||
|
"\tsw $a3, 28($v0)\n"
|
||||||
|
"\tsw $v1, 32($v0)"
|
||||||
|
:
|
||||||
|
: "m"(msg)
|
||||||
|
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void call (Capability target, Message *msg)
|
||||||
|
{
|
||||||
|
Capability t = cap_copy (target);
|
||||||
|
__asm__ volatile ("lw $v0, %0\n"
|
||||||
|
"\tlw $v1, %1\n"
|
||||||
|
"\tlw $t0, 0($v1)\n"
|
||||||
|
"\tlw $t1, 4($v1)\n"
|
||||||
|
"\tlw $t2, 8($v1)\n"
|
||||||
|
"\tlw $t3, 12($v1)\n"
|
||||||
|
"\tlw $a0, 16($v1)\n"
|
||||||
|
"\tlw $a1, 20($v1)\n"
|
||||||
|
"\tlw $a2, 24($v1)\n"
|
||||||
|
"\tlw $a3, 28($v1)\n"
|
||||||
|
"\tsyscall\n"
|
||||||
"\tlw $v0, %1\n"
|
"\tlw $v0, %1\n"
|
||||||
"\tsw $t0, 0($v0)\n"
|
"\tsw $t0, 0($v0)\n"
|
||||||
"\tsw $t1, 4($v0)\n"
|
"\tsw $t1, 4($v0)\n"
|
||||||
@ -185,167 +215,274 @@ static int wait (Message *msg)
|
|||||||
"\tsw $a2, 24($v0)\n"
|
"\tsw $a2, 24($v0)\n"
|
||||||
"\tsw $a3, 28($v0)\n"
|
"\tsw $a3, 28($v0)\n"
|
||||||
"\tsw $v1, 32($v0)"
|
"\tsw $v1, 32($v0)"
|
||||||
: "=m"(ret)
|
:
|
||||||
: "m"(msg)
|
|
||||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int call (Capability target, Message *msg)
|
|
||||||
{
|
|
||||||
unsigned ret;
|
|
||||||
Capability t = cap_copy (target);
|
|
||||||
__asm__ volatile ("lw $v0, %1\n"
|
|
||||||
"\tlw $v1, %2\n"
|
|
||||||
"\tlw $t0, 0($v1)\n"
|
|
||||||
"\tlw $t1, 4($v1)\n"
|
|
||||||
"\tlw $t2, 8($v1)\n"
|
|
||||||
"\tlw $t3, 12($v1)\n"
|
|
||||||
"\tlw $a0, 16($v1)\n"
|
|
||||||
"\tlw $a1, 20($v1)\n"
|
|
||||||
"\tlw $a2, 24($v1)\n"
|
|
||||||
"\tlw $a3, 28($v1)\n"
|
|
||||||
"\tsyscall\n"
|
|
||||||
"\tsw $v0, %0\n"
|
|
||||||
"\tlw $v0, %2\n"
|
|
||||||
"\tsw $t0, 0($v0)\n"
|
|
||||||
"\tsw $t1, 4($v0)\n"
|
|
||||||
"\tsw $t2, 8($v0)\n"
|
|
||||||
"\tsw $t3, 12($v0)\n"
|
|
||||||
"\tsw $a0, 16($v0)\n"
|
|
||||||
"\tsw $a1, 20($v0)\n"
|
|
||||||
"\tsw $a2, 24($v0)\n"
|
|
||||||
"\tsw $a3, 28($v0)\n"
|
|
||||||
"\tsw $v1, 32($v0)"
|
|
||||||
: "=m"(ret)
|
|
||||||
: "m"(t), "m"(msg)
|
: "m"(t), "m"(msg)
|
||||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int invoke_01 (Capability t, unsigned d)
|
static void invoke_01 (Capability t, unsigned d)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.data[0] = d;
|
msg.data[0] = d;
|
||||||
return invoke (t, &msg);
|
msg.data[1] = 0;
|
||||||
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[0] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int invoke_02 (Capability t, unsigned d0, unsigned d1)
|
static void invoke_02 (Capability t, unsigned d0, unsigned d1)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
return invoke (t, &msg);
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[0] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
static void invoke_03 (Capability t, unsigned d0, unsigned d1, unsigned d2)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = d2;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[0] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
msg.data[2] = d2;
|
msg.data[2] = d2;
|
||||||
msg.data[3] = d3;
|
msg.data[3] = d3;
|
||||||
return invoke (t, &msg);
|
msg.cap[0] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int invoke_11 (Capability t, Capability c, unsigned d)
|
static void invoke_11 (Capability t, Capability c, unsigned d)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d;
|
msg.data[0] = d;
|
||||||
return invoke (t, &msg);
|
msg.data[1] = 0;
|
||||||
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int invoke_12 (Capability t, Capability c, unsigned d0, unsigned d1)
|
static void invoke_12 (Capability t, Capability c, unsigned d0, unsigned d1)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
return invoke (t, &msg);
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invoke_13 (Capability t, Capability c, unsigned d0, unsigned d1, unsigned d2)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = d2;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
invoke (t, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability call_c01 (Capability c, unsigned d)
|
static Capability call_c01 (Capability c, unsigned d)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d;
|
msg.data[0] = d;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[1] = 0;
|
||||||
return ret ? msg.cap[0] : 0;
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.cap[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability call_c02 (Capability c, unsigned d0, unsigned d1)
|
static Capability call_c02 (Capability c, unsigned d0, unsigned d1)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[2] = 0;
|
||||||
return ret ? msg.cap[0] : 0;
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.cap[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability call_c12 (Capability c, Capability c1, unsigned d0, unsigned d1)
|
static Capability call_c12 (Capability c, Capability c1, unsigned d0, unsigned d1)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.cap[1] = c1;
|
msg.cap[1] = c1;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[2] = 0;
|
||||||
return ret ? msg.cap[0] : 0;
|
msg.data[3] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.cap[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned call_n01 (Capability c, unsigned d)
|
static unsigned call_n01 (Capability c, unsigned d)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d;
|
msg.data[0] = d;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[1] = 0;
|
||||||
return ret ? msg.data[0] : 0;
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned call_n11 (Capability c, Capability c1, unsigned d)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.cap[1] = c1;
|
||||||
|
msg.data[0] = d;
|
||||||
|
msg.data[1] = 0;
|
||||||
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned call_n12 (Capability c, Capability c1, unsigned d0, unsigned d1)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.cap[1] = c1;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned call_n02 (Capability c, unsigned d0, unsigned d1)
|
static unsigned call_n02 (Capability c, unsigned d0, unsigned d1)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[2] = 0;
|
||||||
return ret ? msg.data[0] : 0;
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned call_n03 (Capability c, unsigned d0, unsigned d1, unsigned d2)
|
static unsigned call_n03 (Capability c, unsigned d0, unsigned d1, unsigned d2)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
msg.data[2] = d2;
|
msg.data[2] = d2;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[3] = 0;
|
||||||
return ret ? msg.data[0] : 0;
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned call_n13 (Capability c, Capability c1, unsigned d0, unsigned d1, unsigned d2)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.cap[1] = c1;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = d2;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned call_n04 (Capability c, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
static unsigned call_n04 (Capability c, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||||
{
|
{
|
||||||
Message msg;
|
Message msg;
|
||||||
int ret;
|
|
||||||
msg.cap[0] = c;
|
msg.cap[0] = c;
|
||||||
msg.data[0] = d0;
|
msg.data[0] = d0;
|
||||||
msg.data[1] = d1;
|
msg.data[1] = d1;
|
||||||
msg.data[2] = d2;
|
msg.data[2] = d2;
|
||||||
msg.data[3] = d3;
|
msg.data[3] = d3;
|
||||||
ret = call (__my_call, &msg);
|
msg.data[3] = 0;
|
||||||
return ret ? msg.data[0] : 0;
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
return msg.data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static Capability call_p02 (Capability c, unsigned d0, unsigned d1, unsigned *base_return)
|
||||||
|
{
|
||||||
|
Message msg;
|
||||||
|
msg.cap[0] = c;
|
||||||
|
msg.data[0] = d0;
|
||||||
|
msg.data[1] = d1;
|
||||||
|
msg.data[2] = 0;
|
||||||
|
msg.data[3] = 0;
|
||||||
|
msg.cap[1] = 0;
|
||||||
|
msg.cap[2] = 0;
|
||||||
|
msg.cap[3] = 0;
|
||||||
|
call (__my_call, &msg);
|
||||||
|
*base_return = msg.data[0];
|
||||||
|
return msg.cap[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability degrade (Capability src, unsigned mask)
|
static Capability degrade (Capability src, unsigned mask)
|
||||||
@ -353,11 +490,6 @@ static Capability degrade (Capability src, unsigned mask)
|
|||||||
return call_c02 (src, CAP_DEGRADE, mask);
|
return call_c02 (src, CAP_DEGRADE, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kdebug (unsigned code)
|
|
||||||
{
|
|
||||||
invoke_02 (__my_thread, CAP_THREAD_DEBUG, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void schedule ()
|
static void schedule ()
|
||||||
{
|
{
|
||||||
invoke_01 (__my_thread, CAP_THREAD_SCHEDULE);
|
invoke_01 (__my_thread, CAP_THREAD_SCHEDULE);
|
||||||
@ -368,24 +500,29 @@ static void register_interrupt (unsigned num)
|
|||||||
invoke_12 (__my_thread, __my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num);
|
invoke_12 (__my_thread, __my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability get_top_memory ()
|
|
||||||
{
|
|
||||||
return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unregister_interrupt (unsigned num)
|
static void unregister_interrupt (unsigned num)
|
||||||
{
|
{
|
||||||
invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
|
invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alloc_physical (Capability page, unsigned address, int cachable)
|
static Capability get_top_memory ()
|
||||||
{
|
{
|
||||||
invoke_12 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0));
|
return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int receiver_set_owner (Capability receiver, Capability owner)
|
static void alloc_physical (Capability page, unsigned address, int cachable, int freeable)
|
||||||
{
|
{
|
||||||
return invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER);
|
invoke_13 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, address & PAGE_MASK, (cachable ? 1 : 0) | (freeable ? 2 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned alloc_range (Capability memory, unsigned pages)
|
||||||
|
{
|
||||||
|
return call_n12 (__my_thread, memory, CAP_THREAD_ALLOC_RANGE, pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void receiver_set_owner (Capability receiver, Capability owner)
|
||||||
|
{
|
||||||
|
invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability receiver_create_capability (Capability receiver, unsigned protected_data)
|
static Capability receiver_create_capability (Capability receiver, unsigned protected_data)
|
||||||
@ -393,14 +530,45 @@ static Capability receiver_create_capability (Capability receiver, unsigned prot
|
|||||||
return call_c02 (receiver, CAP_RECEIVER_CREATE_CAPABILITY, protected_data);
|
return call_c02 (receiver, CAP_RECEIVER_CREATE_CAPABILITY, protected_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int receiver_get_reply_protected_data (Capability receiver, unsigned data)
|
static unsigned receiver_reply_protected_data (Capability receiver, int set, unsigned data)
|
||||||
{
|
{
|
||||||
return call_n01 (receiver, CAP_RECEIVER_GET_REPLY_PROTECTED_DATA);
|
return call_n03 (receiver, CAP_RECEIVER_REPLY_PROTECTED_DATA, (unsigned)set, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int receiver_set_reply_protected_data (Capability receiver, unsigned data)
|
static unsigned receiver_get_reply_protected_data (Capability receiver)
|
||||||
{
|
{
|
||||||
return invoke_02 (receiver, CAP_RECEIVER_SET_REPLY_PROTECTED_DATA, data);
|
return receiver_reply_protected_data (receiver, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned receiver_set_reply_protected_data (Capability receiver, unsigned data)
|
||||||
|
{
|
||||||
|
return receiver_reply_protected_data (receiver, 1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned receiver_alarm (Capability receiver, int set, unsigned data)
|
||||||
|
{
|
||||||
|
return call_n03 (receiver, CAP_RECEIVER_ALARM, (unsigned)set, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned receiver_get_alarm (Capability receiver)
|
||||||
|
{
|
||||||
|
return receiver_alarm (receiver, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned receiver_add_alarm (Capability receiver, unsigned data)
|
||||||
|
{
|
||||||
|
return receiver_alarm (receiver, 0, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned receiver_set_alarm (Capability receiver, unsigned data)
|
||||||
|
{
|
||||||
|
return receiver_alarm (receiver, 1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_sleep (unsigned value, Message *ret)
|
||||||
|
{
|
||||||
|
receiver_set_alarm (__my_receiver, value);
|
||||||
|
wait (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability receiver_create_call_capability (Capability receiver)
|
static Capability receiver_create_call_capability (Capability receiver)
|
||||||
@ -438,37 +606,38 @@ static Capability memory_create_memory (Capability memory)
|
|||||||
return memory_create (memory, CAPTYPE_MEMORY | REQUEST_MASK);
|
return memory_create (memory, CAPTYPE_MEMORY | REQUEST_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability memory_create_cappage (Capability memory)
|
static Capability memory_create_cappage (Capability memory, unsigned *base_return)
|
||||||
{
|
{
|
||||||
return memory_create (memory, CAPTYPE_CAPPAGE | REQUEST_MASK);
|
return call_p02 (memory, CAP_MEMORY_CREATE, CAPTYPE_CAPPAGE | REQUEST_MASK, base_return);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int memory_destroy (Capability memory, Capability target)
|
static void memory_destroy (Capability memory, Capability target)
|
||||||
{
|
{
|
||||||
return invoke_11 (memory, target, CAP_MEMORY_DESTROY);
|
invoke_11 (memory, target, CAP_MEMORY_DESTROY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: #define CAP_MEMORY_LIST 3 */
|
/* TODO: #define CAP_MEMORY_LIST 3 */
|
||||||
|
|
||||||
static int memory_map (Capability memory, Capability page, unsigned address, int writable)
|
static void memory_map (Capability memory, Capability page, unsigned address, int writable)
|
||||||
{
|
{
|
||||||
if (writable)
|
if (writable)
|
||||||
address |= 1 << CAP_PAGE_WRITE;
|
address |= 1 << CAP_PAGE_WRITE;
|
||||||
return invoke_12 (memory, page, CAP_MEMORY_MAP, address);
|
invoke_12 (memory, page, CAP_MEMORY_MAP, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Capability memory_mapping (Capability memory, unsigned address)
|
static Capability memory_mapping (Capability memory, void *address)
|
||||||
{
|
{
|
||||||
return call_c02 (memory, CAP_MEMORY_MAPPING, address);
|
return call_c02 (memory, CAP_MEMORY_MAPPING, (unsigned)address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned memory_limit (Capability memory, unsigned limit)
|
static unsigned memory_limit (Capability memory, unsigned limit)
|
||||||
{
|
{
|
||||||
return call_c02 (memory, CAP_MEMORY_MAPPING, address);
|
return call_c02 (memory, CAP_MEMORY_LIMIT, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drop (Capability cap)
|
static void drop (Capability cap)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,29 +676,6 @@ static unsigned thread_wait (Capability thread, int wait)
|
|||||||
return thread_flags (thread, wait ? THREAD_FLAG_WAITING : 0, THREAD_FLAG_WAITING);
|
return thread_flags (thread, wait ? THREAD_FLAG_WAITING : 0, THREAD_FLAG_WAITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned thread_sleep (Capability thread, unsigned value)
|
|
||||||
{
|
|
||||||
return thread_info (thread, CAP_THREAD_INFO_SLEEP, value, ~0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int my_sleep (unsigned value, Message *ret)
|
|
||||||
{
|
|
||||||
ret->data[0] = CAP_THREAD_INFO;
|
|
||||||
ret->data[1] = CAP_THREAD_INFO_SLEEP;
|
|
||||||
ret->data[2] = value;
|
|
||||||
ret->data[3] = ~0;
|
|
||||||
ret->cap[0] = 0;
|
|
||||||
ret->cap[1] = 0;
|
|
||||||
ret->cap[2] = 0;
|
|
||||||
ret->cap[3] = 0;
|
|
||||||
return call (__my_thread, ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned thread_get_sleep (Capability thread)
|
|
||||||
{
|
|
||||||
return thread_info (thread, CAP_THREAD_INFO_SLEEP, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned thread_get_pc (Capability thread)
|
static unsigned thread_get_pc (Capability thread)
|
||||||
{
|
{
|
||||||
return thread_info (thread, CAP_THREAD_INFO_PC, 0, 0);
|
return thread_info (thread, CAP_THREAD_INFO_PC, 0, 0);
|
||||||
@ -540,9 +686,9 @@ static unsigned thread_get_sp (Capability thread)
|
|||||||
return thread_info (thread, CAP_THREAD_INFO_SP, 0, 0);
|
return thread_info (thread, CAP_THREAD_INFO_SP, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int page_share (Capability page, Capability target, unsigned flags)
|
static void page_share (Capability page, Capability target, unsigned flags)
|
||||||
{
|
{
|
||||||
return invoke_12 (page, target, CAP_PAGE_SHARE, flags);
|
invoke_12 (page, target, CAP_PAGE_SHARE, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask)
|
static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask)
|
||||||
@ -550,16 +696,24 @@ static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask)
|
|||||||
return call_n03 (page, CAP_PAGE_FLAGS, new_flags, mask);
|
return call_n03 (page, CAP_PAGE_FLAGS, new_flags, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned page_physical_address (Capability page)
|
||||||
|
{
|
||||||
|
return call_n11 (__my_thread, page, CAP_THREAD_PHYSICAL_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
static Capability capability_get (Capability cap)
|
static Capability capability_get (Capability cap)
|
||||||
{
|
{
|
||||||
return call_c01 (cap, CAP_CAPABILITY_GET);
|
return call_c01 (cap, CAP_CAPABILITY_GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cappage_set (Capability page, Capability cap, unsigned index)
|
static void cappage_set (Capability page, Capability cap, unsigned index)
|
||||||
{
|
{
|
||||||
return invoke_12 (page, cap, CAP_CAPPAGE_SET, index);
|
invoke_12 (page, cap, CAP_CAPPAGE_SET, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
|
||||||
|
#define kdebug(d0, d1) do { unsigned data0 = (unsigned)(d0); unsigned data1 = (unsigned)(d1); __asm__ volatile ("lw $a0, %0\n" "\tlw $a1, %1\n" "\tbreak" :: "m" (data0), "m" (data1)); } while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
31
kernel.hhp
31
kernel.hhp
@ -68,10 +68,7 @@ struct Thread : public Object <Thread>:
|
|||||||
unsigned pc, sp
|
unsigned pc, sp
|
||||||
Thread_arch arch
|
Thread_arch arch
|
||||||
unsigned flags
|
unsigned flags
|
||||||
unsigned sleep_count
|
|
||||||
Thread *schedule_prev, *schedule_next
|
Thread *schedule_prev, *schedule_next
|
||||||
void sleep ()
|
|
||||||
void unsleep ()
|
|
||||||
void run ()
|
void run ()
|
||||||
void unrun ()
|
void unrun ()
|
||||||
void wait ()
|
void wait ()
|
||||||
@ -94,14 +91,17 @@ struct Capability : public Object <Capability>:
|
|||||||
Capability *children
|
Capability *children
|
||||||
Capability *sibling_prev, *sibling_next
|
Capability *sibling_prev, *sibling_next
|
||||||
unsigned protected_data
|
unsigned protected_data
|
||||||
bool invoke (Context *c)
|
void invoke (Context *c)
|
||||||
void invalidate ()
|
void invalidate ()
|
||||||
|
|
||||||
struct Receiver : public Object <Receiver>:
|
struct Receiver : public Object <Receiver>:
|
||||||
Thread *owner
|
Thread *owner
|
||||||
Receiver *prev_owned, *next_owned
|
Receiver *prev_owned, *next_owned
|
||||||
|
Receiver *prev_alarm, *next_alarm
|
||||||
|
unsigned alarm_count
|
||||||
Capability *capabilities
|
Capability *capabilities
|
||||||
Message *messages
|
Message *messages
|
||||||
|
Message *last_message
|
||||||
unsigned reply_protected_data
|
unsigned reply_protected_data
|
||||||
bool protected_only
|
bool protected_only
|
||||||
void own (Thread *o)
|
void own (Thread *o)
|
||||||
@ -122,6 +122,8 @@ struct Page : public Object <Page>:
|
|||||||
|
|
||||||
struct Cappage : public Object <Cappage>:
|
struct Cappage : public Object <Cappage>:
|
||||||
ShareData data
|
ShareData data
|
||||||
|
Capability *cap (unsigned idx):
|
||||||
|
return &((Capability *)data.frame)[idx]
|
||||||
void forget ()
|
void forget ()
|
||||||
|
|
||||||
struct Memory : public Object <Memory>:
|
struct Memory : public Object <Memory>:
|
||||||
@ -140,8 +142,8 @@ struct Memory : public Object <Memory>:
|
|||||||
inline Page *get_mapping (unsigned address, bool *writable)
|
inline Page *get_mapping (unsigned address, bool *writable)
|
||||||
|
|
||||||
// Allocation of pages.
|
// Allocation of pages.
|
||||||
bool use ()
|
bool use (unsigned num = 1)
|
||||||
void unuse ()
|
void unuse (unsigned num = 1)
|
||||||
unsigned palloc ()
|
unsigned palloc ()
|
||||||
unsigned zalloc ()
|
unsigned zalloc ()
|
||||||
void pfree (unsigned page)
|
void pfree (unsigned page)
|
||||||
@ -151,7 +153,7 @@ struct Memory : public Object <Memory>:
|
|||||||
void *search_free (unsigned size, void **first)
|
void *search_free (unsigned size, void **first)
|
||||||
Page *alloc_page ()
|
Page *alloc_page ()
|
||||||
Thread *alloc_thread ()
|
Thread *alloc_thread ()
|
||||||
Message *alloc_message (Receiver *target, unsigned protected_data)
|
Message *alloc_message (Receiver *target)
|
||||||
Receiver *alloc_receiver ()
|
Receiver *alloc_receiver ()
|
||||||
Capability *alloc_capability (Receiver *target, Capability *parent, Capability **parent_ptr, unsigned protected_data, Capability *ret = NULL)
|
Capability *alloc_capability (Receiver *target, Capability *parent, Capability **parent_ptr, unsigned protected_data, Capability *ret = NULL)
|
||||||
Capability *clone_capability (Capability *source, bool copy, Capability *ret = NULL)
|
Capability *clone_capability (Capability *source, bool copy, Capability *ret = NULL)
|
||||||
@ -160,7 +162,7 @@ struct Memory : public Object <Memory>:
|
|||||||
|
|
||||||
void free_page (Page *page)
|
void free_page (Page *page)
|
||||||
void free_thread (Thread *thread)
|
void free_thread (Thread *thread)
|
||||||
void free_message (Message *message)
|
void free_message (Receiver *owner, Message *message)
|
||||||
void free_receiver (Receiver *receiver)
|
void free_receiver (Receiver *receiver)
|
||||||
void free_capability (Capability *capability)
|
void free_capability (Capability *capability)
|
||||||
void free_cappage (Cappage *page)
|
void free_cappage (Cappage *page)
|
||||||
@ -178,26 +180,27 @@ extern "C":
|
|||||||
void dbg_led (bool one, bool two, bool three)
|
void dbg_led (bool one, bool two, bool three)
|
||||||
void dbg_sleep (unsigned ms)
|
void dbg_sleep (unsigned ms)
|
||||||
void dbg_send (unsigned code, unsigned bits = 32)
|
void dbg_send (unsigned code, unsigned bits = 32)
|
||||||
|
EXTERN unsigned dbg_code
|
||||||
|
|
||||||
/// Defined in schedule.ccp
|
/// Defined in schedule.ccp
|
||||||
void schedule ()
|
void schedule ()
|
||||||
void timer_interrupt ()
|
void timer_interrupt ()
|
||||||
|
|
||||||
struct FreePage:
|
|
||||||
FreePage *next
|
|
||||||
|
|
||||||
EXTERN Memory top_memory
|
EXTERN Memory top_memory
|
||||||
EXTERN Thread *sleepers, *runners
|
EXTERN Receiver *first_alarm
|
||||||
EXTERN Thread idle
|
EXTERN Thread idle
|
||||||
EXTERN Memory idle_memory
|
EXTERN Memory idle_memory
|
||||||
EXTERN Page idle_page
|
EXTERN Page idle_page
|
||||||
EXTERN Thread *first_scheduled, *first_sleeper
|
EXTERN Thread *first_scheduled
|
||||||
EXTERN Thread *current
|
EXTERN Thread *current
|
||||||
|
EXTERN bool do_schedule
|
||||||
|
|
||||||
// Defined in memory.cc
|
// Defined in memory.cc
|
||||||
unsigned init_memory (unsigned mem)
|
unsigned init_memory (unsigned mem)
|
||||||
unsigned raw_zalloc ()
|
unsigned raw_zalloc ()
|
||||||
void raw_pfree (unsigned page)
|
void raw_pfree (unsigned page)
|
||||||
|
unsigned phys_alloc (unsigned num)
|
||||||
|
void phys_free (unsigned page, unsigned num)
|
||||||
|
|
||||||
// Defined by architecture-specific files.
|
// Defined by architecture-specific files.
|
||||||
void Thread_arch_init (Thread *thread)
|
void Thread_arch_init (Thread *thread)
|
||||||
@ -219,4 +222,6 @@ void Memory::unmap (Page *page, unsigned address):
|
|||||||
Page *Memory::get_mapping (unsigned address, bool *writable):
|
Page *Memory::get_mapping (unsigned address, bool *writable):
|
||||||
return Memory_arch_get_mapping (this, address, writable)
|
return Memory_arch_get_mapping (this, address, writable)
|
||||||
|
|
||||||
|
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
167
memory.ccp
167
memory.ccp
@ -1,53 +1,135 @@
|
|||||||
#pypp 0
|
#pypp 0
|
||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
static FreePage *zero_pages, *junk_pages
|
|
||||||
|
|
||||||
extern unsigned _end
|
extern unsigned _end
|
||||||
|
|
||||||
|
static void clear_page (unsigned page):
|
||||||
|
for unsigned i = 0; i < PAGE_SIZE >> 2; ++i:
|
||||||
|
((unsigned *)page)[i] = 0
|
||||||
|
|
||||||
|
static unsigned free_begin
|
||||||
|
static unsigned free_end
|
||||||
|
|
||||||
unsigned init_memory (unsigned mem):
|
unsigned init_memory (unsigned mem):
|
||||||
zero_pages = NULL
|
free_begin = ((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK
|
||||||
// Fill junk pages with all memory not currently used.
|
free_end = (0x80000000 + mem) & PAGE_MASK
|
||||||
junk_pages = (FreePage *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
return (free_end - free_begin) >> PAGE_BITS
|
||||||
FreePage *p, *next
|
|
||||||
unsigned count = 1
|
unsigned phys_alloc (unsigned num):
|
||||||
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < mem; p = next, next = (FreePage *)((unsigned)p + PAGE_SIZE):
|
if free_begin + num * PAGE_SIZE > free_end:
|
||||||
p->next = next
|
panic (0xaaaaaaaa, "out of memory")
|
||||||
++count
|
unsigned ret = free_begin
|
||||||
p->next = NULL
|
free_begin += num * PAGE_SIZE
|
||||||
return count
|
for unsigned i = 0; i < num; ++i:
|
||||||
|
clear_page (ret + i * PAGE_SIZE)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
void phys_free (unsigned page, unsigned num):
|
||||||
|
// Not supported.
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct FreePages:
|
||||||
|
FreePages *prev, *next
|
||||||
|
unsigned num
|
||||||
|
|
||||||
|
static FreePages *first_free
|
||||||
|
|
||||||
|
unsigned init_memory (unsigned mem):
|
||||||
|
first_free = (FreePages *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
||||||
|
first_free->prev = NULL
|
||||||
|
first_free->next = NULL
|
||||||
|
first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free - 0x80000000)) >> PAGE_BITS
|
||||||
|
return first_free->num
|
||||||
|
|
||||||
|
unsigned phys_alloc (unsigned num):
|
||||||
|
FreePages *choice = NULL
|
||||||
|
for FreePages *p = first_free; p; p = p->next:
|
||||||
|
if p->num < num:
|
||||||
|
continue
|
||||||
|
if choice && choice->num < p->num:
|
||||||
|
continue
|
||||||
|
choice = p
|
||||||
|
if !choice:
|
||||||
|
// TODO: reorganizing may work to allow allocation.
|
||||||
|
panic (0x01100223, "out of large enough memory")
|
||||||
|
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
|
||||||
|
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
|
||||||
|
clear_page (ret, num)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
void phys_free (unsigned page, unsigned num):
|
||||||
|
return
|
||||||
|
unsigned size = num << PAGE_BITS
|
||||||
|
if !first_free || (unsigned)first_free > page:
|
||||||
|
// This is the first free block.
|
||||||
|
FreePages *n = (FreePages *)page
|
||||||
|
n->prev = NULL
|
||||||
|
if (unsigned)first_free == page + size:
|
||||||
|
// It fits exactly before the previous first free block.
|
||||||
|
n->next = first_free->next
|
||||||
|
n->num = num + first_free->num
|
||||||
|
else:
|
||||||
|
// It is a new block.
|
||||||
|
n->next = first_free
|
||||||
|
n->num = num
|
||||||
|
first_free = n
|
||||||
|
if n->next:
|
||||||
|
n->next->prev = n
|
||||||
|
return
|
||||||
|
FreePages *p
|
||||||
|
for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
|
||||||
|
// Do nothing.
|
||||||
|
// The new block should be inserted directly after p.
|
||||||
|
if (unsigned)p->next == page + size:
|
||||||
|
// It can be merged with the block after it: do that.
|
||||||
|
FreePages *n = (FreePages *)page
|
||||||
|
n->prev = p
|
||||||
|
n->next = p->next->next
|
||||||
|
if n->next:
|
||||||
|
n->next->prev = n
|
||||||
|
n->num = num + p->next->num
|
||||||
|
p->next = n
|
||||||
|
if (unsigned)p + (p->num << PAGE_BITS) == (unsigned)n:
|
||||||
|
// It can also be merged with the page before it: do that as well.
|
||||||
|
p->num += n->num
|
||||||
|
p->next = n->next
|
||||||
|
if p->next:
|
||||||
|
p->next->prev = p
|
||||||
|
return
|
||||||
|
// The new block cannot be merged with the block after it.
|
||||||
|
if (unsigned)p + (p->num << PAGE_BITS) == page:
|
||||||
|
// But it can be merged with the one before it: do that.
|
||||||
|
p->num += num
|
||||||
|
return
|
||||||
|
// The new block cannot be merged at all.
|
||||||
|
FreePages *n = (FreePages *)page
|
||||||
|
n->next = p->next
|
||||||
|
n->prev = p
|
||||||
|
if n->next:
|
||||||
|
n->next->prev = n
|
||||||
|
p->next = n
|
||||||
|
n->num = num
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned raw_zalloc ():
|
unsigned raw_zalloc ():
|
||||||
FreePage *ret = zero_pages
|
return phys_alloc (1)
|
||||||
if !ret:
|
|
||||||
ret = junk_pages
|
|
||||||
junk_pages = ret->next
|
|
||||||
for unsigned i = 0; i < (PAGE_SIZE >> 2); ++i:
|
|
||||||
((unsigned *)ret)[i] = 0
|
|
||||||
else:
|
|
||||||
zero_pages = ret->next
|
|
||||||
ret->next = NULL
|
|
||||||
return (unsigned)ret
|
|
||||||
|
|
||||||
void raw_pfree (unsigned page):
|
void raw_pfree (unsigned page):
|
||||||
if !page:
|
return phys_free (page, 1)
|
||||||
return
|
|
||||||
FreePage *p = (FreePage *)page
|
|
||||||
p->next = junk_pages
|
|
||||||
junk_pages = p
|
|
||||||
|
|
||||||
unsigned Memory::palloc ():
|
|
||||||
if !use ():
|
|
||||||
return NULL
|
|
||||||
FreePage *ret = junk_pages
|
|
||||||
if !ret:
|
|
||||||
ret = zero_pages
|
|
||||||
zero_pages = ret->next
|
|
||||||
else:
|
|
||||||
junk_pages = ret->next
|
|
||||||
return (unsigned)ret
|
|
||||||
|
|
||||||
unsigned Memory::zalloc ():
|
unsigned Memory::zalloc ():
|
||||||
if !use ():
|
if !use ():
|
||||||
|
assert (false)
|
||||||
return NULL
|
return NULL
|
||||||
return raw_zalloc ()
|
return raw_zalloc ()
|
||||||
|
|
||||||
@ -55,9 +137,8 @@ void Memory::pfree (unsigned page):
|
|||||||
unuse ()
|
unuse ()
|
||||||
return raw_pfree (page)
|
return raw_pfree (page)
|
||||||
|
|
||||||
void Memory::zfree (unsigned page):
|
unsigned Memory::palloc ():
|
||||||
unuse ()
|
return zalloc ()
|
||||||
FreePage *p = (FreePage *)page
|
|
||||||
p->next = zero_pages
|
|
||||||
zero_pages = p
|
|
||||||
|
|
||||||
|
void Memory::zfree (unsigned page):
|
||||||
|
pfree (page)
|
||||||
|
@ -27,7 +27,7 @@ OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
|
|||||||
arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc
|
arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc
|
||||||
boot_sources = mips/init.cc
|
boot_sources = mips/init.cc
|
||||||
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
|
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
|
||||||
arch_headers = mips/arch.hh
|
arch_headers = mips/arch.hh mips/jz4730.hh
|
||||||
boot_threads = keyboard lcd
|
boot_threads = keyboard lcd
|
||||||
|
|
||||||
uimage:
|
uimage:
|
||||||
@ -35,11 +35,11 @@ uimage:
|
|||||||
mips/entry.o: $(boot_threads)
|
mips/entry.o: $(boot_threads)
|
||||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||||
$(boot_threads): TARGET_FLAGS = -I.
|
$(boot_threads): TARGET_FLAGS = -I.
|
||||||
$(boot_threads): mips/jz4730.hh boot-programs/devices.hh
|
$(boot_threads): boot-programs/devices.hh
|
||||||
|
|
||||||
# Transform ':' into ';' so vim doesn't think there are errors.
|
# Transform ':' into ';' so vim doesn't think there are errors.
|
||||||
uimage: kernel.raw.gz Makefile mips/Makefile.arch
|
uimage: kernel.raw.gz Makefile mips/Makefile.arch
|
||||||
mkimage -A MIPS -O Linux -C gzip -a $(load) -e 0x$(shell /bin/sh -c '$(OBJDUMP) -t kernel | grep __start$$ | cut -b-8') -n "Shevek's kernel" -d $< $@ | sed -e 's/:/;/g'
|
mkimage -A MIPS -O Linux -C gzip -a $(load) -e 0xa$(shell /bin/sh -c '$(OBJDUMP) -t kernel | grep __start$$ | cut -b2-8') -n "Iris" -d $< $@ | sed -e 's/:/;/g'
|
||||||
|
|
||||||
%.o:%.S Makefile mips/Makefile.arch mips/arch.hh
|
%.o:%.S Makefile mips/Makefile.arch mips/arch.hh
|
||||||
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
||||||
@ -49,7 +49,7 @@ kernel: mips/entry.o $(subst .cc,.o,$(kernel_sources)) mips/boot.o $(subst .cc,.
|
|||||||
$(LD) --omagic -Ttext $(load) $^ -o $@
|
$(LD) --omagic -Ttext $(load) $^ -o $@
|
||||||
|
|
||||||
%.raw: %
|
%.raw: %
|
||||||
$(OBJCOPY) -S $(addprefix --remove-section=.,$(junk)) -Obinary $< $@
|
$(OBJCOPY) -S $(OBJCOPYFLAGS) -Obinary $< $@
|
||||||
|
|
||||||
%.gz: %
|
%.gz: %
|
||||||
gzip < $< > $@
|
gzip < $< > $@
|
||||||
|
@ -318,3 +318,4 @@ void arch_register_interrupt (unsigned num, Receiver *r):
|
|||||||
intc_unmask_irq (num)
|
intc_unmask_irq (num)
|
||||||
else:
|
else:
|
||||||
intc_mask_irq (num)
|
intc_mask_irq (num)
|
||||||
|
dbg_code = 0
|
||||||
|
@ -25,13 +25,15 @@
|
|||||||
#define Status 12
|
#define Status 12
|
||||||
#define Config 16
|
#define Config 16
|
||||||
|
|
||||||
|
// Note that this code starts at 0xa0000000, even though it is linked for
|
||||||
|
// 0x80000000. This means that until the jump below, it must be PIC.
|
||||||
__start:
|
__start:
|
||||||
bal 1f
|
bal 1f
|
||||||
nop
|
|
||||||
.word _gp
|
|
||||||
// For some reason the disassembler considers everything
|
// For some reason the disassembler considers everything
|
||||||
// after __start non-code until the next label. So I add a label.
|
// after __start non-code until the next label. So I add a label.
|
||||||
start_hack_for_disassembler:
|
start_hack_for_disassembler:
|
||||||
|
nop
|
||||||
|
.word _gp
|
||||||
1: lw $gp, 0($ra)
|
1: lw $gp, 0($ra)
|
||||||
|
|
||||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||||
|
@ -110,10 +110,11 @@ static unsigned mkcap (Memory *mem, unsigned type, void *obj):
|
|||||||
static void init_threads ():
|
static void init_threads ():
|
||||||
Thread *previous = NULL
|
Thread *previous = NULL
|
||||||
first_scheduled = NULL
|
first_scheduled = NULL
|
||||||
first_sleeper = NULL
|
first_alarm = NULL
|
||||||
Receiver *init_receiver = NULL
|
Receiver *init_receiver = NULL
|
||||||
for unsigned i = 0; i < NUM_THREADS; ++i:
|
for unsigned i = 0; i < NUM_THREADS; ++i:
|
||||||
Memory *mem = top_memory.alloc_memory ()
|
Memory *mem = top_memory.alloc_memory ()
|
||||||
|
assert (mem)
|
||||||
Thread *thread = mem->alloc_thread ()
|
Thread *thread = mem->alloc_thread ()
|
||||||
Page **pages = (Page **)mem->zalloc ()
|
Page **pages = (Page **)mem->zalloc ()
|
||||||
Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i]
|
Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i]
|
||||||
@ -134,36 +135,42 @@ static void init_threads ():
|
|||||||
thread->sp = 0x80000000
|
thread->sp = 0x80000000
|
||||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||||
Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
|
Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
|
||||||
if !(shdr->sh_flags & SHF_ALLOC):
|
if ~shdr->sh_flags & SHF_ALLOC:
|
||||||
continue
|
continue
|
||||||
bool writable = shdr->sh_flags & SHF_WRITE
|
bool writable = shdr->sh_flags & SHF_WRITE
|
||||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||||
if shdr->sh_type != SHT_NOBITS:
|
if shdr->sh_type != SHT_NOBITS:
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p <= ((shdr->sh_addr + shdr->sh_size - 1) & PAGE_MASK); p += PAGE_SIZE:
|
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||||
unsigned idx = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||||
|
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||||
|
unsigned idx = file_offset + section_offset
|
||||||
if !pages[idx]:
|
if !pages[idx]:
|
||||||
pages[idx] = mem->alloc_page ()
|
pages[idx] = mem->alloc_page ()
|
||||||
pages[idx]->data.frame = thread_start[i] + (idx << PAGE_BITS)
|
pages[idx]->data.frame = thread_start[i] + (idx << PAGE_BITS)
|
||||||
pages[idx]->data.flags = (writable ? PAGE_FLAG_WRITABLE : 0) | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
pages[idx]->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||||
++top_memory.limit
|
++top_memory.limit
|
||||||
|
mem->use ()
|
||||||
if !mem->map (pages[idx], p, writable):
|
if !mem->map (pages[idx], p, writable):
|
||||||
panic (0x22446688, "unable to map initial page")
|
panic (0x22446688, "unable to map initial page")
|
||||||
else:
|
else:
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p <= ((shdr->sh_addr + shdr->sh_size - 1) & PAGE_MASK); p += PAGE_SIZE:
|
if !writable:
|
||||||
bool write = false
|
panic (0x33399993, "unwritable bss section")
|
||||||
Page *page = mem->get_mapping (p, &write)
|
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||||
|
Page *page = mem->get_mapping (p, &writable)
|
||||||
if !page:
|
if !page:
|
||||||
page = mem->alloc_page ()
|
page = mem->alloc_page ()
|
||||||
if !page:
|
if !page:
|
||||||
panic (0x00220022, "out of memory")
|
panic (0x00220022, "out of memory")
|
||||||
page->data.frame = mem->zalloc ()
|
page->data.frame = mem->zalloc ()
|
||||||
page->data.flags = (writable ? PAGE_FLAG_WRITABLE : 0) | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
if !page->data.frame:
|
||||||
if !page->data.frame || !mem->map (page, p, true):
|
panic (0x02220022, "out of memory");
|
||||||
|
page->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||||
|
if !mem->map (page, p, true):
|
||||||
panic (0x33557799, "unable to map initial bss page")
|
panic (0x33557799, "unable to map initial bss page")
|
||||||
else:
|
else:
|
||||||
if !write:
|
if !writable:
|
||||||
panic (0x20203030, "bss section starts on read-only page")
|
panic (0x20203030, "bss section starts on read-only page")
|
||||||
for unsigned a = p; a < p + PAGE_SIZE; a += 4:
|
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||||
if a >= shdr->sh_addr + shdr->sh_size:
|
if a >= shdr->sh_addr + shdr->sh_size:
|
||||||
break
|
break
|
||||||
if a < shdr->sh_addr:
|
if a < shdr->sh_addr:
|
||||||
@ -201,11 +208,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):
|
||||||
|
dbg_code = 0
|
||||||
// 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.
|
||||||
sleepers = NULL
|
|
||||||
runners = NULL
|
|
||||||
unsigned count = init_memory (mem)
|
unsigned count = init_memory (mem)
|
||||||
// initialize system control coprocessor.
|
// initialize system control coprocessor.
|
||||||
init_cp0 ()
|
init_cp0 ()
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "../kernel.hh"
|
#include "../kernel.hh"
|
||||||
|
|
||||||
static void handle_exit (Thread *old_current):
|
static void handle_exit (Thread *old_current):
|
||||||
if !current:
|
if !current || (current == &idle):
|
||||||
schedule ()
|
schedule ()
|
||||||
if !current:
|
if !current:
|
||||||
current = &idle
|
current = &idle
|
||||||
@ -77,7 +77,6 @@ Thread *tlb_refill ():
|
|||||||
Thread *interrupt ():
|
Thread *interrupt ():
|
||||||
//panic (0x88877722, "Interrupt")
|
//panic (0x88877722, "Interrupt")
|
||||||
Thread *old_current = current
|
Thread *old_current = current
|
||||||
//dbg_send (INTC_IPR)
|
|
||||||
unsigned ipr = INTC_IPR
|
unsigned ipr = INTC_IPR
|
||||||
for unsigned i = 0; i < 32; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
if ipr & (1 << i):
|
if ipr & (1 << i):
|
||||||
@ -94,6 +93,7 @@ Thread *interrupt ():
|
|||||||
c.data[j] = 0
|
c.data[j] = 0
|
||||||
c.cap[j] = NULL
|
c.cap[j] = NULL
|
||||||
c.copy[j] = false
|
c.copy[j] = false
|
||||||
|
dbg_code = (unsigned)arch_interrupt_receiver[i]->owner
|
||||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||||
if ipr & (1 << IRQ_OST0):
|
if ipr & (1 << IRQ_OST0):
|
||||||
ost_clear_uf (0)
|
ost_clear_uf (0)
|
||||||
@ -118,15 +118,12 @@ static void arch_invoke ():
|
|||||||
bool wait
|
bool wait
|
||||||
Thread *caller = current
|
Thread *caller = current
|
||||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
||||||
|
do_schedule = false
|
||||||
|
if wait:
|
||||||
|
caller->wait ()
|
||||||
if !target:
|
if !target:
|
||||||
// There must be no action here.
|
// There must be no action here.
|
||||||
//dbg_send (3, 2)
|
|
||||||
//dbg_send (caller->arch.v0)
|
|
||||||
// Calling an invalid capability always fails.
|
|
||||||
caller->arch.v0 = 0
|
|
||||||
else:
|
else:
|
||||||
if wait:
|
|
||||||
caller->wait ()
|
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
||||||
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
||||||
@ -136,8 +133,9 @@ static void arch_invoke ():
|
|||||||
c.data[1] = caller->arch.t1
|
c.data[1] = caller->arch.t1
|
||||||
c.data[2] = caller->arch.t2
|
c.data[2] = caller->arch.t2
|
||||||
c.data[3] = caller->arch.t3
|
c.data[3] = caller->arch.t3
|
||||||
caller->arch.v0 = target->invoke (&c) ? 1 : 0
|
target->invoke (&c)
|
||||||
if caller != current && caller != &idle && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
// If the caller received a reply from the kernel, it is no longer set as current. Don't let it lose its timeslice.
|
||||||
|
if caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING && !do_schedule:
|
||||||
current = caller
|
current = caller
|
||||||
|
|
||||||
/// A general exception has occurred.
|
/// A general exception has occurred.
|
||||||
@ -160,15 +158,21 @@ Thread *exception ():
|
|||||||
panic (0x31223344, "TLB load or instruction fetch.")
|
panic (0x31223344, "TLB load or instruction fetch.")
|
||||||
case 3:
|
case 3:
|
||||||
// TLB store.
|
// TLB store.
|
||||||
|
unsigned a
|
||||||
|
cp0_get (CP0_EPC, a)
|
||||||
|
dbg_send (a)
|
||||||
panic (0x41223344, "TLB store.")
|
panic (0x41223344, "TLB store.")
|
||||||
case 4:
|
case 4:
|
||||||
// Address error load or instruction fetch.
|
// Address error load or instruction fetch.
|
||||||
|
unsigned a
|
||||||
|
cp0_get (CP0_EPC, a)
|
||||||
|
dbg_send (a)
|
||||||
panic (0x51223344, "Address error load or instruction fetch.")
|
panic (0x51223344, "Address error load or instruction fetch.")
|
||||||
case 5:
|
case 5:
|
||||||
// Address error store.
|
// Address error store.
|
||||||
unsigned a
|
unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_BAD_V_ADDR, a)
|
||||||
dbg_send (a, 16)
|
dbg_send (a, 32)
|
||||||
panic (0x61223344, "Address error store.")
|
panic (0x61223344, "Address error store.")
|
||||||
case 6:
|
case 6:
|
||||||
// Bus error instruction fetch.
|
// Bus error instruction fetch.
|
||||||
@ -183,7 +187,10 @@ Thread *exception ():
|
|||||||
break
|
break
|
||||||
case 9:
|
case 9:
|
||||||
// Breakpoint.
|
// Breakpoint.
|
||||||
panic (0x91223344, "Breakpoint.")
|
//panic (0x91223344, "Breakpoint.")
|
||||||
|
dbg_send (current->arch.a0, current->arch.a1)
|
||||||
|
current->pc += 4
|
||||||
|
break
|
||||||
case 10:
|
case 10:
|
||||||
// Reserved instruction.
|
// Reserved instruction.
|
||||||
panic (0xa1223344, "Reserved instruction.")
|
panic (0xa1223344, "Reserved instruction.")
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
// Main clock, for cpu, serial port, and with divisors for most other hardware
|
// Main clock, for cpu, serial port, and with divisors for most other hardware
|
||||||
#define JZ_EXTAL 3686400
|
#define JZ_EXTAL 3686400
|
||||||
//#define JZ_EXTAL 3072000
|
|
||||||
// RTC clock
|
// RTC clock
|
||||||
#define RTC_CLOCK 32768
|
#define RTC_CLOCK 32768
|
||||||
|
|
||||||
@ -36,7 +35,7 @@
|
|||||||
#define LCD_PHYSICAL 0x13050000
|
#define LCD_PHYSICAL 0x13050000
|
||||||
#define CIM_PHYSICAL 0x13060000
|
#define CIM_PHYSICAL 0x13060000
|
||||||
#define ETH_PHYSICAL 0x13100000
|
#define ETH_PHYSICAL 0x13100000
|
||||||
#define NBM_PHYSICAL 0x13F00000
|
#define NBM_PHYSICAL 0x13f00000
|
||||||
#define CPM_PHYSICAL 0x10000000
|
#define CPM_PHYSICAL 0x10000000
|
||||||
#define INTC_PHYSICAL 0x10001000
|
#define INTC_PHYSICAL 0x10001000
|
||||||
#define OST_PHYSICAL 0x10002000
|
#define OST_PHYSICAL 0x10002000
|
||||||
@ -98,49 +97,53 @@
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
// In user space, they just need a mapping.
|
// In user space, they just need a mapping.
|
||||||
#define HARB_BASE 0x00000000
|
#define UNMAPPED_BASE 0x00000000
|
||||||
#define EMC_BASE 0x00001000
|
|
||||||
#define DMAC_BASE 0x00002000
|
#define HARB_BASE 0x00001000
|
||||||
#define UHC_BASE 0x00003000
|
#define EMC_BASE 0x00002000
|
||||||
#define UDC_BASE 0x00004000
|
#define DMAC_BASE 0x00003000
|
||||||
#define LCD_BASE 0x00005000
|
#define UHC_BASE 0x00004000
|
||||||
#define CIM_BASE 0x00006000
|
#define UDC_BASE 0x00005000
|
||||||
#define ETH_BASE 0x00007000
|
#define LCD_BASE 0x00006000
|
||||||
#define NBM_BASE 0x00008000
|
#define CIM_BASE 0x00007000
|
||||||
#define CPM_BASE 0x00009000
|
#define ETH_BASE 0x00008000
|
||||||
#define INTC_BASE 0x0000a000
|
#define NBM_BASE 0x00009000
|
||||||
#define OST_BASE 0x0000b000
|
#define CPM_BASE 0x0000a000
|
||||||
#define RTC_BASE 0x0000c000
|
#define INTC_BASE 0x0000b000
|
||||||
#define WDT_BASE 0x0000d000
|
#define OST_BASE 0x0000c000
|
||||||
#define GPIO_BASE 0x0000e000
|
#define RTC_BASE 0x0000d000
|
||||||
#define AIC_BASE 0x0000f000
|
#define WDT_BASE 0x0000e000
|
||||||
#define MSC_BASE 0x00010000
|
#define GPIO_BASE 0x0000f000
|
||||||
#define UART0_BASE 0x00011000
|
#define AIC_BASE 0x00010000
|
||||||
#define UART1_BASE 0x00012000
|
#define MSC_BASE 0x00011000
|
||||||
#define UART2_BASE 0x00013000
|
#define UART0_BASE 0x00012000
|
||||||
#define UART3_BASE 0x00014000
|
#define UART1_BASE 0x00013000
|
||||||
#define FIR_BASE 0x00015000
|
#define UART2_BASE 0x00014000
|
||||||
#define SCC_BASE 0x00016000
|
#define UART3_BASE 0x00015000
|
||||||
#define SCC0_BASE 0x00017000
|
#define FIR_BASE 0x00016000
|
||||||
#define I2C_BASE 0x00018000
|
#define SCC_BASE 0x00017000
|
||||||
#define SSI_BASE 0x00019000
|
#define SCC0_BASE 0x00018000
|
||||||
#define SCC1_BASE 0x0001a000
|
#define I2C_BASE 0x00019000
|
||||||
#define PWM0_BASE 0x0001b000
|
#define SSI_BASE 0x0001a000
|
||||||
#define PWM1_BASE 0x0001c000
|
#define SCC1_BASE 0x0001b000
|
||||||
#define DES_BASE 0x0001d000
|
#define PWM0_BASE 0x0001c000
|
||||||
#define UPRT_BASE 0x0001e000
|
#define PWM1_BASE 0x0001d000
|
||||||
#define KBC_BASE 0x0001f000
|
#define DES_BASE 0x0001e000
|
||||||
|
#define UPRT_BASE 0x0001f000
|
||||||
|
#define KBC_BASE 0x00020000
|
||||||
|
|
||||||
|
// Default lcd framebuffer mapping space.
|
||||||
|
#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00021000)
|
||||||
|
|
||||||
// Map IO memory (requires a priviledged __my_thread capability).
|
// Map IO memory (requires a priviledged __my_thread capability).
|
||||||
#include <iris.h>
|
#include <iris.h>
|
||||||
static void __map_io (unsigned physical, unsigned mapping):
|
static void __map_io (unsigned physical, unsigned mapping):
|
||||||
Capability page = memory_create_page (__my_memory)
|
Capability page = memory_create_page (__my_memory)
|
||||||
// 0 means not cachable.
|
// 0 means not cachable; 0 means don't free when done.
|
||||||
alloc_physical (page, physical, 0)
|
alloc_physical (page, physical, 0, 0)
|
||||||
// 1 means writable.
|
// 1 means writable.
|
||||||
memory_map (__my_memory, page, mapping, 1)
|
memory_map (__my_memory, page, mapping, 1)
|
||||||
//drop (page)
|
drop (page)
|
||||||
#endif
|
|
||||||
|
|
||||||
#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)
|
||||||
@ -175,6 +178,8 @@ static void __map_io (unsigned physical, unsigned mapping):
|
|||||||
#define map_uprt() do { __map_io (UPRT_PHYSICAL, UPRT_BASE); } while (0)
|
#define map_uprt() do { __map_io (UPRT_PHYSICAL, UPRT_BASE); } while (0)
|
||||||
#define map_kbc() do { __map_io (KBC_PHYSICAL, KBC_BASE); } while (0)
|
#define map_kbc() do { __map_io (KBC_PHYSICAL, KBC_BASE); } while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define REG8(x) (*(volatile unsigned char *)(x))
|
#define REG8(x) (*(volatile unsigned char *)(x))
|
||||||
#define REG16(x) (*(volatile unsigned short *)(x))
|
#define REG16(x) (*(volatile unsigned short *)(x))
|
||||||
#define REG32(x) (*(volatile unsigned *)(x))
|
#define REG32(x) (*(volatile unsigned *)(x))
|
||||||
|
@ -97,6 +97,8 @@ void dbg_sleep (unsigned ms):
|
|||||||
__gpio_as_output (CAPSLOCKLED_IO)
|
__gpio_as_output (CAPSLOCKLED_IO)
|
||||||
|
|
||||||
void dbg_send (unsigned code, unsigned bits):
|
void dbg_send (unsigned code, unsigned bits):
|
||||||
|
if bits > 32:
|
||||||
|
bits = 32
|
||||||
for int i = bits - 1; i >= 0; --i:
|
for int i = bits - 1; i >= 0; --i:
|
||||||
bool on = code & (1 << i)
|
bool on = code & (1 << i)
|
||||||
dbg_led (false, false, false)
|
dbg_led (false, false, false)
|
||||||
|
60
schedule.ccp
60
schedule.ccp
@ -34,28 +34,11 @@ static void unrun_thread (Thread *thread):
|
|||||||
if thread->schedule_next:
|
if thread->schedule_next:
|
||||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
thread->schedule_next->schedule_prev = thread->schedule_prev
|
||||||
|
|
||||||
void Thread::sleep ():
|
|
||||||
schedule_next = first_sleeper
|
|
||||||
if schedule_next:
|
|
||||||
schedule_next->schedule_prev = this
|
|
||||||
schedule_prev = NULL
|
|
||||||
first_sleeper = this
|
|
||||||
|
|
||||||
void Thread::unsleep ():
|
|
||||||
if schedule_next:
|
|
||||||
schedule_next->schedule_prev = schedule_prev
|
|
||||||
if schedule_prev:
|
|
||||||
schedule_prev->schedule_next = schedule_next
|
|
||||||
else:
|
|
||||||
first_sleeper = schedule_next
|
|
||||||
|
|
||||||
void Thread::run ():
|
void Thread::run ():
|
||||||
if flags & THREAD_FLAG_RUNNING:
|
if flags & THREAD_FLAG_RUNNING:
|
||||||
return
|
return
|
||||||
flags |= THREAD_FLAG_RUNNING
|
flags |= THREAD_FLAG_RUNNING
|
||||||
if flags & THREAD_FLAG_WAITING:
|
if is_waiting ():
|
||||||
if sleep_count != ~0:
|
|
||||||
sleep ()
|
|
||||||
return
|
return
|
||||||
run_thread (this)
|
run_thread (this)
|
||||||
|
|
||||||
@ -63,48 +46,41 @@ void Thread::unrun ():
|
|||||||
if !(flags & THREAD_FLAG_RUNNING):
|
if !(flags & THREAD_FLAG_RUNNING):
|
||||||
return
|
return
|
||||||
flags &= ~THREAD_FLAG_RUNNING
|
flags &= ~THREAD_FLAG_RUNNING
|
||||||
if flags & THREAD_FLAG_WAITING:
|
if is_waiting ():
|
||||||
if sleep_count != ~0:
|
|
||||||
unsleep ()
|
|
||||||
return
|
return
|
||||||
unrun_thread (this)
|
unrun_thread (this)
|
||||||
|
|
||||||
void Thread::unwait ():
|
void Thread::unwait ():
|
||||||
if !(flags & THREAD_FLAG_WAITING):
|
|
||||||
return
|
|
||||||
flags &= ~THREAD_FLAG_WAITING
|
flags &= ~THREAD_FLAG_WAITING
|
||||||
if sleep_count != ~0:
|
|
||||||
unsleep ()
|
|
||||||
if flags & THREAD_FLAG_RUNNING:
|
if flags & THREAD_FLAG_RUNNING:
|
||||||
run_thread (this)
|
run_thread (this)
|
||||||
|
|
||||||
static void sleep_tick (Thread *thread):
|
static void alarm_tick (Receiver *recv):
|
||||||
if !thread->sleep_count:
|
if !recv->alarm_count:
|
||||||
thread->unwait ()
|
// Send message and stop counting.
|
||||||
// Time-out: let the thread know with a special message.
|
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
c.data[i] = 0
|
c.data[i] = 0
|
||||||
c.cap[i] = NULL
|
c.cap[i] = NULL
|
||||||
c.copy[i] = false
|
c.copy[i] = false
|
||||||
Thread_arch_receive (thread, ~0, &c)
|
recv->send_message (~0, &c)
|
||||||
// Fall through to let sleep be set to ~0, so the next wait will be infinitely long again.
|
if recv->prev_alarm:
|
||||||
--thread->sleep_count
|
recv->prev_alarm->next_alarm = recv->next_alarm
|
||||||
|
else:
|
||||||
|
first_alarm = recv->next_alarm
|
||||||
|
if recv->next_alarm:
|
||||||
|
recv->next_alarm->prev_alarm = recv->prev_alarm
|
||||||
|
// Fall through to let alarm be set to ~0, so the next wait will be infinitely long again.
|
||||||
|
--recv->alarm_count
|
||||||
|
|
||||||
void Thread::wait ():
|
void Thread::wait ():
|
||||||
if flags & THREAD_FLAG_WAITING:
|
|
||||||
return
|
|
||||||
if flags & THREAD_FLAG_RUNNING:
|
if flags & THREAD_FLAG_RUNNING:
|
||||||
unrun_thread (this)
|
unrun_thread (this)
|
||||||
flags |= THREAD_FLAG_WAITING
|
flags |= THREAD_FLAG_WAITING
|
||||||
if sleep_count != ~0:
|
|
||||||
sleep ()
|
|
||||||
// Try to receive a message from a Receiver immediately.
|
// Try to receive a message from a Receiver immediately.
|
||||||
for Receiver *r = receivers; r; r = r->next_owned:
|
for Receiver *r = receivers; r; r = r->next_owned:
|
||||||
if r->try_deliver ():
|
if r->try_deliver ():
|
||||||
return
|
return
|
||||||
if sleep_count != ~0:
|
|
||||||
sleep_tick (this)
|
|
||||||
|
|
||||||
void schedule ():
|
void schedule ():
|
||||||
Thread *old = current
|
Thread *old = current
|
||||||
@ -117,10 +93,10 @@ void schedule ():
|
|||||||
|
|
||||||
void timer_interrupt ():
|
void timer_interrupt ():
|
||||||
//panic (0x88877744, "Timer interrupt")
|
//panic (0x88877744, "Timer interrupt")
|
||||||
Thread *thread, *next
|
Receiver *recv, *next
|
||||||
for thread = first_sleeper; thread; thread = next:
|
for recv = first_alarm; recv; recv = next:
|
||||||
next = thread->next
|
next = recv->next
|
||||||
sleep_tick (thread)
|
alarm_tick (recv)
|
||||||
schedule ()
|
schedule ()
|
||||||
//#ifndef NDEBUG
|
//#ifndef NDEBUG
|
||||||
//static bool ledstate = false
|
//static bool ledstate = false
|
||||||
|
Loading…
Reference in New Issue
Block a user