mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-30 21:11:06 +02:00
working lcd log with panic
This commit is contained in:
parent
592713adec
commit
b7d9b1554c
@ -262,8 +262,7 @@ class Pwm:
|
|||||||
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
|
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
|
||||||
|
|
||||||
int main ():
|
int main ():
|
||||||
for unsigned i = 0; i < 10; ++i:
|
schedule ()
|
||||||
schedule ()
|
|
||||||
*(unsigned *)~3 = 0
|
*(unsigned *)~3 = 0
|
||||||
|
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
|
@ -67,20 +67,23 @@ static void setup ():
|
|||||||
invoke_01 (pwm, 1)
|
invoke_01 (pwm, 1)
|
||||||
|
|
||||||
int main ():
|
int main ():
|
||||||
for unsigned i = 0; i < 10; ++i:
|
schedule ()
|
||||||
schedule ()
|
|
||||||
setup ()
|
|
||||||
kdebug ("start init")
|
kdebug ("start init")
|
||||||
|
setup ()
|
||||||
|
kdebug ("run init")
|
||||||
while true:
|
while true:
|
||||||
Message msg
|
Message msg
|
||||||
wait (&msg)
|
wait (&msg)
|
||||||
switch msg.protected_data:
|
switch msg.protected_data:
|
||||||
case KBD:
|
case KBD:
|
||||||
invoke_01 (lockleds, 0x4 | (msg.data[0] >> 16))
|
kdebug ("keyboard event")
|
||||||
break
|
break
|
||||||
case TP:
|
case TP:
|
||||||
invoke_01 (lockleds, 0x2 | (msg.data[0] >> 16))
|
kdebug ("touchpad event")
|
||||||
break
|
break
|
||||||
case POWERBUTTON:
|
case POWERBUTTON:
|
||||||
case BATTERY:
|
kdebug ("powerbutton event")
|
||||||
|
break
|
||||||
|
case BATTERY:
|
||||||
|
kdebug ("battery event")
|
||||||
break
|
break
|
||||||
|
@ -106,7 +106,7 @@ static void log_num (unsigned n):
|
|||||||
char const *encode = "0123456789abcdef"
|
char const *encode = "0123456789abcdef"
|
||||||
log_char ('[')
|
log_char ('[')
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
log_char (encode[(n >> (7 - i)) & 0xf])
|
log_char (encode[(n >> (4 * (7 - i))) & 0xf])
|
||||||
log_char (']')
|
log_char (']')
|
||||||
|
|
||||||
static void log_msg (Message *msg):
|
static void log_msg (Message *msg):
|
||||||
|
23
invoke.ccp
23
invoke.ccp
@ -86,6 +86,7 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
|||||||
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
||||||
if !c->cap[i]:
|
if !c->cap[i]:
|
||||||
panic (0xdddddddd, "out of memory")
|
panic (0xdddddddd, "out of memory")
|
||||||
|
return false
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
owner->address_space->free_capability (c->cap[j])
|
owner->address_space->free_capability (c->cap[j])
|
||||||
c->cap[j] = orig[j]
|
c->cap[j] = orig[j]
|
||||||
@ -313,24 +314,25 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
switch (unsigned)c->cap[0]->target & CAPTYPE_MASK:
|
switch (unsigned)c->cap[0]->target & CAPTYPE_MASK:
|
||||||
case CAPTYPE_RECEIVER:
|
case CAPTYPE_RECEIVER:
|
||||||
mem->free_receiver ((Receiver *)c->cap[0]->protected_data)
|
mem->free_receiver ((Receiver *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
case CAPTYPE_MEMORY:
|
case CAPTYPE_MEMORY:
|
||||||
mem->free_memory ((Memory *)c->cap[0]->protected_data)
|
mem->free_memory ((Memory *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
case CAPTYPE_THREAD:
|
case CAPTYPE_THREAD:
|
||||||
mem->free_thread ((Thread *)c->cap[0]->protected_data)
|
mem->free_thread ((Thread *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
case CAPTYPE_PAGE:
|
case CAPTYPE_PAGE:
|
||||||
mem->free_page ((Page *)c->cap[0]->protected_data)
|
mem->free_page ((Page *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
case CAPTYPE_CAPABILITY:
|
case CAPTYPE_CAPABILITY:
|
||||||
mem->free_capability ((Capability *)c->cap[0]->protected_data)
|
mem->free_capability ((Capability *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
case CAPTYPE_CAPPAGE:
|
case CAPTYPE_CAPPAGE:
|
||||||
mem->free_cappage ((Cappage *)c->cap[0]->protected_data)
|
mem->free_cappage ((Cappage *)c->cap[0]->protected_data)
|
||||||
return
|
break
|
||||||
default:
|
default:
|
||||||
panic (0x55228930, "invalid case")
|
panic (0x55228930, "invalid case")
|
||||||
|
return
|
||||||
break
|
break
|
||||||
case CAP_MEMORY_LIST:
|
case CAP_MEMORY_LIST:
|
||||||
// TODO
|
// TODO
|
||||||
@ -386,13 +388,9 @@ 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:
|
||||||
if !(thread->is_waiting ()):
|
thread->wait ()
|
||||||
if thread == current:
|
|
||||||
unschedule ()
|
|
||||||
thread->wait ()
|
|
||||||
else
|
else
|
||||||
if thread->is_waiting ():
|
thread->unwait ()
|
||||||
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 ()
|
||||||
@ -798,6 +796,7 @@ static void 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
|
||||||
return
|
return
|
||||||
|
|
||||||
void Capability::invoke (Capability::Context *c):
|
void Capability::invoke (Capability::Context *c):
|
||||||
|
10
kernel.hhp
10
kernel.hhp
@ -66,6 +66,8 @@ struct Thread : public Object <Thread>:
|
|||||||
Thread_arch arch
|
Thread_arch arch
|
||||||
unsigned flags
|
unsigned flags
|
||||||
Thread *schedule_prev, *schedule_next
|
Thread *schedule_prev, *schedule_next
|
||||||
|
Thread *exception
|
||||||
|
void raise (unsigned code)
|
||||||
void run ()
|
void run ()
|
||||||
void unrun ()
|
void unrun ()
|
||||||
void wait ()
|
void wait ()
|
||||||
@ -173,9 +175,7 @@ struct Memory : public Object <Memory>:
|
|||||||
extern "C":
|
extern "C":
|
||||||
// Panic. n is sent over caps led. message is currently ignored.
|
// Panic. n is sent over caps led. message is currently ignored.
|
||||||
void panic (unsigned n, char const *message = "")
|
void panic (unsigned n, char const *message = "")
|
||||||
// Debug: switch caps led
|
// Debug: send a message to the user.
|
||||||
void dbg_led (bool one, bool two, bool three)
|
|
||||||
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
|
EXTERN unsigned dbg_code
|
||||||
EXTERN Capability *dbg_cap
|
EXTERN Capability *dbg_cap
|
||||||
@ -184,8 +184,6 @@ extern "C":
|
|||||||
|
|
||||||
/// Defined in schedule.ccp
|
/// Defined in schedule.ccp
|
||||||
void schedule ()
|
void schedule ()
|
||||||
// Make sure the current process is no longer scheduled. This is called just before wait (), if the current process is the target.
|
|
||||||
void unschedule ()
|
|
||||||
void timer_interrupt ()
|
void timer_interrupt ()
|
||||||
|
|
||||||
EXTERN Memory top_memory
|
EXTERN Memory top_memory
|
||||||
@ -194,7 +192,7 @@ EXTERN Thread idle
|
|||||||
EXTERN Memory idle_memory
|
EXTERN Memory idle_memory
|
||||||
EXTERN Page idle_page
|
EXTERN Page idle_page
|
||||||
EXTERN Thread *first_scheduled
|
EXTERN Thread *first_scheduled
|
||||||
EXTERN Thread *current
|
EXTERN Thread *current, *old_current
|
||||||
EXTERN bool do_schedule
|
EXTERN bool do_schedule
|
||||||
|
|
||||||
// Defined in memory.cc
|
// Defined in memory.cc
|
||||||
|
@ -20,6 +20,7 @@ unsigned init_memory (unsigned mem):
|
|||||||
unsigned phys_alloc (unsigned num):
|
unsigned phys_alloc (unsigned num):
|
||||||
if free_begin + num * PAGE_SIZE > free_end:
|
if free_begin + num * PAGE_SIZE > free_end:
|
||||||
panic (0xaaaaaaaa, "out of memory")
|
panic (0xaaaaaaaa, "out of memory")
|
||||||
|
return 0
|
||||||
unsigned ret = free_begin
|
unsigned ret = free_begin
|
||||||
free_begin += num * PAGE_SIZE
|
free_begin += num * PAGE_SIZE
|
||||||
clear_page (ret, num)
|
clear_page (ret, num)
|
||||||
@ -131,7 +132,7 @@ void raw_pfree (unsigned page):
|
|||||||
|
|
||||||
unsigned Memory::zalloc ():
|
unsigned Memory::zalloc ():
|
||||||
if !use ():
|
if !use ():
|
||||||
assert (false)
|
panic (0x4536928, "no memory due to limit")
|
||||||
return NULL
|
return NULL
|
||||||
return raw_zalloc ()
|
return raw_zalloc ()
|
||||||
|
|
||||||
|
@ -314,4 +314,3 @@ 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
|
|
||||||
|
@ -121,16 +121,22 @@ static void init_threads ():
|
|||||||
for unsigned j = 0; j < SELFMAG; ++j:
|
for unsigned j = 0; j < SELFMAG; ++j:
|
||||||
if header->e_ident[j] != ELFMAG[j]:
|
if header->e_ident[j] != ELFMAG[j]:
|
||||||
panic (i * 0x1000 + j, "invalid ELF magic")
|
panic (i * 0x1000 + j, "invalid ELF magic")
|
||||||
|
return
|
||||||
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
||||||
panic (i * 0x1000 + EI_CLASS, "invalid ELF class")
|
panic (i * 0x1000 + EI_CLASS, "invalid ELF class")
|
||||||
|
return
|
||||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||||
panic (i * 0x1000 + EI_DATA, "invalid ELF data")
|
panic (i * 0x1000 + EI_DATA, "invalid ELF data")
|
||||||
|
return
|
||||||
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
||||||
panic (i * 0x1000 + EI_VERSION, "invalid ELF version")
|
panic (i * 0x1000 + EI_VERSION, "invalid ELF version")
|
||||||
|
return
|
||||||
if header->e_type != ET_EXEC:
|
if header->e_type != ET_EXEC:
|
||||||
panic (i * 0x1000 + 0x10, "invalid ELF type")
|
panic (i * 0x1000 + 0x10, "invalid ELF type")
|
||||||
|
return
|
||||||
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
||||||
panic (i * 0x1000 + 0x12, "invalid ELF machine")
|
panic (i * 0x1000 + 0x12, "invalid ELF machine")
|
||||||
|
return
|
||||||
thread->pc = header->e_entry
|
thread->pc = header->e_entry
|
||||||
thread->sp = 0x80000000
|
thread->sp = 0x80000000
|
||||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||||
@ -143,6 +149,7 @@ static void init_threads ():
|
|||||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||||
if ((file_offset + shdr->sh_size) >> PAGE_BITS) >= (PAGE_SIZE >> 2):
|
if ((file_offset + shdr->sh_size) >> PAGE_BITS) >= (PAGE_SIZE >> 2):
|
||||||
panic (0x87446809, "initial thread too large")
|
panic (0x87446809, "initial thread too large")
|
||||||
|
return
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
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 section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||||
unsigned idx = file_offset + section_offset
|
unsigned idx = file_offset + section_offset
|
||||||
@ -154,24 +161,30 @@ static void init_threads ():
|
|||||||
mem->use ()
|
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")
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
if !writable:
|
if !writable:
|
||||||
panic (0x33399993, "unwritable bss section")
|
panic (0x33399993, "unwritable bss section")
|
||||||
|
return
|
||||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
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)
|
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")
|
||||||
|
return
|
||||||
page->data.frame = mem->zalloc ()
|
page->data.frame = mem->zalloc ()
|
||||||
if !page->data.frame:
|
if !page->data.frame:
|
||||||
panic (0x02220022, "out of memory");
|
panic (0x02220022, "out of memory");
|
||||||
|
return
|
||||||
page->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
page->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||||
if !mem->map (page, p, true):
|
if !mem->map (page, p, true):
|
||||||
panic (0x33557799, "unable to map initial bss page")
|
panic (0x33557799, "unable to map initial bss page")
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
if !writable:
|
if !writable:
|
||||||
panic (0x20203030, "bss section starts on read-only page")
|
panic (0x20203030, "bss section starts on read-only page")
|
||||||
|
return
|
||||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); 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
|
||||||
@ -188,6 +201,7 @@ static void init_threads ():
|
|||||||
stackpage->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
stackpage->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||||
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
||||||
panic (0x13151719, "unable to map initial stack page")
|
panic (0x13151719, "unable to map initial stack page")
|
||||||
|
return
|
||||||
Receiver *recv = mem->alloc_receiver ()
|
Receiver *recv = mem->alloc_receiver ()
|
||||||
recv->owner = thread
|
recv->owner = thread
|
||||||
thread->receivers = recv
|
thread->receivers = recv
|
||||||
|
@ -24,17 +24,17 @@ void arch_flush_cache ():
|
|||||||
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
|
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
|
||||||
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
||||||
|
|
||||||
static void handle_exit (Thread *old_current):
|
static void handle_exit ():
|
||||||
if !current || (current == &idle):
|
if !current || (current == &idle):
|
||||||
schedule ()
|
schedule ()
|
||||||
if !current:
|
if !current:
|
||||||
current = &idle
|
current = &idle
|
||||||
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
|
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
|
||||||
dbg_send ((unsigned)current >> PAGE_BITS, 3)
|
|
||||||
panic (0x99338844, "non-scheduled thread running")
|
panic (0x99338844, "non-scheduled thread running")
|
||||||
|
if !current:
|
||||||
|
current = &idle
|
||||||
if old_current == current:
|
if old_current == current:
|
||||||
return
|
return
|
||||||
dbg_send ((unsigned)current >> PAGE_BITS, 3)
|
|
||||||
arch_flush_cache ()
|
arch_flush_cache ()
|
||||||
if current != &idle:
|
if current != &idle:
|
||||||
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||||
@ -62,31 +62,34 @@ static void handle_exit (Thread *old_current):
|
|||||||
/// Otherwise, the ultra-fast code in entry.S is used.
|
/// Otherwise, the ultra-fast code in entry.S is used.
|
||||||
Thread *tlb_refill ():
|
Thread *tlb_refill ():
|
||||||
//panic (0x88776655, "TLB refill")
|
//panic (0x88776655, "TLB refill")
|
||||||
Thread *old_current = current
|
old_current = current
|
||||||
if !directory:
|
if !directory:
|
||||||
panic (0x44449999, "No directory")
|
panic (0x44449999, "No directory")
|
||||||
|
handle_exit ()
|
||||||
|
return current
|
||||||
unsigned EntryHi
|
unsigned EntryHi
|
||||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||||
unsigned *t = directory[EntryHi >> 21]
|
unsigned *t = directory[EntryHi >> 21]
|
||||||
if !t:
|
if !t:
|
||||||
unsigned a
|
unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_EPC, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
cp0_get (CP0_BAD_V_ADDR, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
panic (0x99992222, "No page table")
|
panic (0x99992222, "No page table")
|
||||||
// - 2 instead of - 1 means reset bit 0
|
else:
|
||||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
// - 2 instead of - 1 means reset bit 0
|
||||||
cp0_set (CP0_ENTRY_LO0, t[idx])
|
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||||
cp0_set (CP0_ENTRY_LO1, t[idx + 1])
|
cp0_set (CP0_ENTRY_LO0, t[idx])
|
||||||
__asm__ volatile ("tlbwr")
|
cp0_set (CP0_ENTRY_LO1, t[idx + 1])
|
||||||
handle_exit (old_current)
|
__asm__ volatile ("tlbwr")
|
||||||
|
handle_exit ()
|
||||||
return current
|
return current
|
||||||
|
|
||||||
/// An interrupt which is not an exception has occurred.
|
/// An interrupt which is not an exception has occurred.
|
||||||
Thread *interrupt ():
|
Thread *interrupt ():
|
||||||
//panic (0x88877722, "Interrupt")
|
//panic (0x88877722, "Interrupt")
|
||||||
Thread *old_current = current
|
old_current = current
|
||||||
unsigned ipr = INTC_IPR
|
unsigned ipr = INTC_IPR
|
||||||
for unsigned i = 0; i < 32; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
if ipr & (1 << i):
|
if ipr & (1 << i):
|
||||||
@ -103,14 +106,13 @@ 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)
|
||||||
arch_interrupt_receiver[i] = NULL
|
arch_interrupt_receiver[i] = NULL
|
||||||
if ipr & (1 << IRQ_OST0):
|
if ipr & (1 << IRQ_OST0):
|
||||||
ost_clear_uf (0)
|
ost_clear_uf (0)
|
||||||
intc_ack_irq (IRQ_OST0)
|
intc_ack_irq (IRQ_OST0)
|
||||||
timer_interrupt ()
|
timer_interrupt ()
|
||||||
handle_exit (old_current)
|
handle_exit ()
|
||||||
return current
|
return current
|
||||||
|
|
||||||
void flush_tlb (unsigned asid):
|
void flush_tlb (unsigned asid):
|
||||||
@ -127,85 +129,91 @@ void flush_tlb (unsigned asid):
|
|||||||
static void arch_invoke ():
|
static void arch_invoke ():
|
||||||
Capability *target
|
Capability *target
|
||||||
bool wait
|
bool wait
|
||||||
Thread *caller = current
|
target = old_current->address_space->find_capability (old_current->arch.v0, &wait)
|
||||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
|
||||||
do_schedule = false
|
do_schedule = false
|
||||||
if wait:
|
if wait:
|
||||||
unschedule ()
|
old_current->wait ()
|
||||||
caller->wait ()
|
|
||||||
if !target:
|
if !target:
|
||||||
dbg_send (0, 0)
|
//dbg_send (0, 0)
|
||||||
// There must be no action here.
|
// There must be no action here.
|
||||||
else:
|
else:
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
c.cap[0] = old_current->address_space->find_capability (old_current->arch.a0, &c.copy[0])
|
||||||
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
c.cap[1] = old_current->address_space->find_capability (old_current->arch.a1, &c.copy[1])
|
||||||
c.cap[2] = caller->address_space->find_capability (caller->arch.a2, &c.copy[2])
|
c.cap[2] = old_current->address_space->find_capability (old_current->arch.a2, &c.copy[2])
|
||||||
c.cap[3] = caller->address_space->find_capability (caller->arch.a3, &c.copy[3])
|
c.cap[3] = old_current->address_space->find_capability (old_current->arch.a3, &c.copy[3])
|
||||||
c.data[0] = caller->arch.t0
|
c.data[0] = old_current->arch.t0
|
||||||
c.data[1] = caller->arch.t1
|
c.data[1] = old_current->arch.t1
|
||||||
c.data[2] = caller->arch.t2
|
c.data[2] = old_current->arch.t2
|
||||||
c.data[3] = caller->arch.t3
|
c.data[3] = old_current->arch.t3
|
||||||
target->invoke (&c)
|
target->invoke (&c)
|
||||||
if do_schedule:
|
if do_schedule:
|
||||||
// If the call was to schedule without wait, it isn't done yet.
|
// If the call was to schedule without wait, it isn't done yet.
|
||||||
if !wait:
|
if !wait:
|
||||||
schedule ()
|
schedule ()
|
||||||
else:
|
//else:
|
||||||
// If the caller received an immediate reply from the kernel, it is no longer set as current. Don't let it lose its timeslice.
|
// If the caller received an immediate 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:
|
if old_current != current && (old_current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||||
current = caller
|
current = old_current
|
||||||
|
|
||||||
/// A general exception has occurred.
|
/// A general exception has occurred.
|
||||||
Thread *exception ():
|
Thread *exception ():
|
||||||
Thread *old_current = current
|
old_current = current
|
||||||
unsigned cause
|
unsigned cause
|
||||||
cp0_get (CP0_CAUSE, cause)
|
cp0_get (CP0_CAUSE, cause)
|
||||||
switch (cause >> 2) & 0x1f:
|
switch (cause >> 2) & 0x1f:
|
||||||
case 0:
|
case 0:
|
||||||
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
||||||
panic (0x01223344, "Interrupt on exception vector.")
|
panic (0x01223344, "Interrupt on exception vector.")
|
||||||
|
break
|
||||||
case 1:
|
case 1:
|
||||||
// TLB modification.
|
// TLB modification.
|
||||||
panic (0x11223344, "TLB modification.")
|
panic (0x11223344, "TLB modification.")
|
||||||
|
break
|
||||||
case 2:
|
case 2:
|
||||||
// TLB load or instruction fetch.
|
// TLB load or instruction fetch.
|
||||||
unsigned a
|
unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_EPC, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
panic (0x21223344, "TLB load or instruction fetch.")
|
panic (0x21223344, "TLB load or instruction fetch.")
|
||||||
|
break
|
||||||
case 3:
|
case 3:
|
||||||
// TLB store.
|
// TLB store.
|
||||||
unsigned a
|
unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_EPC, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
cp0_get (CP0_BAD_V_ADDR, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
panic (0x31223344, "TLB store.")
|
panic (0x31223344, "TLB store.")
|
||||||
|
break
|
||||||
case 4:
|
case 4:
|
||||||
// Address error load or instruction fetch.
|
// Address error load or instruction fetch.
|
||||||
unsigned a
|
unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_EPC, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
cp0_get (CP0_BAD_V_ADDR, a)
|
||||||
dbg_send (a)
|
//dbg_send (a)
|
||||||
panic (0x41223344, "Address error load or instruction fetch.")
|
panic (0x41223344, "Address error load or instruction fetch.")
|
||||||
|
break
|
||||||
case 5:
|
case 5:
|
||||||
// Address error store.
|
// Address error store.
|
||||||
dbg_send (current->arch.v1, 4)
|
//dbg_send (current->arch.v1, 4)
|
||||||
unsigned a
|
//unsigned a
|
||||||
cp0_get (CP0_EPC, a)
|
//cp0_get (CP0_EPC, a)
|
||||||
dbg_send (*(unsigned *)(a & ~3), 32)
|
//dbg_send (*(unsigned *)(a & ~3), 32)
|
||||||
dbg_send (a, 32)
|
//dbg_send (a, 32)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
//cp0_get (CP0_BAD_V_ADDR, a)
|
||||||
dbg_send (a, 32)
|
//dbg_send (a, 32)
|
||||||
panic (0x51223344, "Address error store.")
|
panic (0x51223344, "Address error store.")
|
||||||
|
break
|
||||||
case 6:
|
case 6:
|
||||||
// Bus error instruction fetch.
|
// Bus error instruction fetch.
|
||||||
panic (0x61223344, "Bus error instruction fetch.")
|
panic (0x61223344, "Bus error instruction fetch.")
|
||||||
|
break
|
||||||
case 7:
|
case 7:
|
||||||
// Bus error load or store.
|
// Bus error load or store.
|
||||||
panic (0x71223344, "Bus error load or store.")
|
panic (0x71223344, "Bus error load or store.")
|
||||||
|
break
|
||||||
case 8:
|
case 8:
|
||||||
// Syscall.
|
// Syscall.
|
||||||
current->pc += 4
|
current->pc += 4
|
||||||
@ -218,10 +226,12 @@ Thread *exception ():
|
|||||||
if current->arch.a0:
|
if current->arch.a0:
|
||||||
if dbg_cap:
|
if dbg_cap:
|
||||||
panic (0x34259380, "Break instruction while log capability was already set")
|
panic (0x34259380, "Break instruction while log capability was already set")
|
||||||
|
break
|
||||||
bool dummy
|
bool dummy
|
||||||
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
||||||
if !dbg_cap:
|
if !dbg_cap:
|
||||||
panic (0x06111129, "no log capability provided")
|
panic (0x06111129, "no log capability provided")
|
||||||
|
break
|
||||||
break
|
break
|
||||||
if dbg_cap:
|
if dbg_cap:
|
||||||
dbg_log_char (current->arch.a1)
|
dbg_log_char (current->arch.a1)
|
||||||
@ -230,27 +240,35 @@ Thread *exception ():
|
|||||||
case 10:
|
case 10:
|
||||||
// Reserved instruction.
|
// Reserved instruction.
|
||||||
panic (0xa1223344, "Reserved instruction.")
|
panic (0xa1223344, "Reserved instruction.")
|
||||||
|
break
|
||||||
case 11:
|
case 11:
|
||||||
// Coprocessor unusable.
|
// Coprocessor unusable.
|
||||||
panic (0xb1223344, "Coprocessor unusable.")
|
panic (0xb1223344, "Coprocessor unusable.")
|
||||||
|
break
|
||||||
case 12:
|
case 12:
|
||||||
// Arithmetic overflow.
|
// Arithmetic overflow.
|
||||||
panic (0xc1223344, "Arithmetic overflow.")
|
panic (0xc1223344, "Arithmetic overflow.")
|
||||||
|
break
|
||||||
case 13:
|
case 13:
|
||||||
// Trap.
|
// Trap.
|
||||||
panic (0xd1223344, "Trap.")
|
panic (0xd1223344, "Trap.")
|
||||||
|
break
|
||||||
case 15:
|
case 15:
|
||||||
// Floating point exception.
|
// Floating point exception.
|
||||||
panic (0xe1223344, "Floating point exception.")
|
panic (0xe1223344, "Floating point exception.")
|
||||||
|
break
|
||||||
case 23:
|
case 23:
|
||||||
// Reference to WatchHi/WatchLo address.
|
// Reference to WatchHi/WatchLo address.
|
||||||
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
|
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
|
||||||
|
break
|
||||||
case 24:
|
case 24:
|
||||||
// Machine check.
|
// Machine check.
|
||||||
panic (0xf3223344, "Machine check.")
|
panic (0xf3223344, "Machine check.")
|
||||||
|
break
|
||||||
case 30:
|
case 30:
|
||||||
// Cache error (EJTAG only).
|
// Cache error (EJTAG only).
|
||||||
panic (0xf4223344, "Cache error (EJTAG only).")
|
panic (0xf4223344, "Cache error (EJTAG only).")
|
||||||
|
break
|
||||||
case 14:
|
case 14:
|
||||||
case 16:
|
case 16:
|
||||||
case 17:
|
case 17:
|
||||||
@ -267,14 +285,16 @@ Thread *exception ():
|
|||||||
case 31:
|
case 31:
|
||||||
// Reserved.
|
// Reserved.
|
||||||
panic (0xf5223344, "Reserved exception code")
|
panic (0xf5223344, "Reserved exception code")
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
panic (0xf6223344, "Impossible exception code")
|
panic (0xf6223344, "Impossible exception code")
|
||||||
handle_exit (old_current)
|
break
|
||||||
|
handle_exit ()
|
||||||
return current
|
return current
|
||||||
|
|
||||||
/// There's a cache error. Big trouble. Probably not worth trying to recover.
|
/// There's a cache error. Big trouble. Probably not worth trying to recover.
|
||||||
Thread *cache_error ():
|
Thread *cache_error ():
|
||||||
panic (0x33333333, "cache error")
|
panic (0x33333333, "cache error")
|
||||||
Thread *old_current = current
|
old_current = current
|
||||||
handle_exit (old_current)
|
handle_exit ()
|
||||||
return current
|
return current
|
||||||
|
64
panic.ccp
64
panic.ccp
@ -19,40 +19,6 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
// Port 0
|
|
||||||
#define CAPS 27
|
|
||||||
#define CAPS_HALF ((CAPS - 16) << 1)
|
|
||||||
#define SCROLL 9
|
|
||||||
#define SCROLL_HALF (SCROLL << 1)
|
|
||||||
// Port 2
|
|
||||||
#define NUM 22
|
|
||||||
#define NUM_HALF ((NUM - 16) << 1)
|
|
||||||
|
|
||||||
void dbg_led (bool one, bool two, bool three):
|
|
||||||
GPIO_GPALR (0) &= ~(3 << SCROLL_HALF)
|
|
||||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & ~(3 << SCROLL_HALF)) | (1 << SCROLL_HALF)
|
|
||||||
GPIO_GPAUR (0) &= ~(3 << CAPS_HALF)
|
|
||||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & ~(3 << CAPS_HALF)) | (1 << CAPS_HALF)
|
|
||||||
GPIO_GPAUR (2) &= ~(3 << NUM_HALF)
|
|
||||||
GPIO_GPIDUR (2) = (GPIO_GPIDUR (2) & ~(3 << NUM_HALF)) | (1 << NUM_HALF)
|
|
||||||
if one:
|
|
||||||
GPIO_GPDR (2) &= ~(1 << NUM)
|
|
||||||
else:
|
|
||||||
GPIO_GPDR (2) |= 1 << NUM
|
|
||||||
if two:
|
|
||||||
GPIO_GPDR (0) &= ~(1 << CAPS)
|
|
||||||
else:
|
|
||||||
GPIO_GPDR (0) |= 1 << CAPS
|
|
||||||
if three:
|
|
||||||
GPIO_GPDR (0) &= ~(1 << SCROLL)
|
|
||||||
else:
|
|
||||||
GPIO_GPDR (0) |= 1 << SCROLL
|
|
||||||
|
|
||||||
void dbg_sleep (unsigned ms):
|
|
||||||
for unsigned i = 0; i < 2673 * ms; ++i:
|
|
||||||
GPIO_GPALR (0) = GPIO_GPALR (0)
|
|
||||||
GPIO_GPIDLR (0) = GPIO_GPIDLR (0)
|
|
||||||
|
|
||||||
void dbg_log_char (unsigned ch):
|
void dbg_log_char (unsigned ch):
|
||||||
if !dbg_cap:
|
if !dbg_cap:
|
||||||
return
|
return
|
||||||
@ -63,6 +29,8 @@ void dbg_log_char (unsigned ch):
|
|||||||
c.data[i] = 0
|
c.data[i] = 0
|
||||||
c.data[0] = ch
|
c.data[0] = ch
|
||||||
dbg_cap->invoke (&c)
|
dbg_cap->invoke (&c)
|
||||||
|
if dbg_cap->target->owner:
|
||||||
|
current = dbg_cap->target->owner
|
||||||
|
|
||||||
void dbg_log (char const *str):
|
void dbg_log (char const *str):
|
||||||
while *str:
|
while *str:
|
||||||
@ -71,37 +39,19 @@ void dbg_log (char const *str):
|
|||||||
void dbg_send (unsigned code, unsigned bits):
|
void dbg_send (unsigned code, unsigned bits):
|
||||||
if bits > 32:
|
if bits > 32:
|
||||||
bits = 32
|
bits = 32
|
||||||
#if 0
|
|
||||||
char const *encode = "0123456789abcdef"
|
char const *encode = "0123456789abcdef"
|
||||||
dbg_log_char ('[')
|
dbg_log_char ('[')
|
||||||
dbg_log_char (encode[(bits >> 4) & 0xf])
|
dbg_log_char (encode[(bits >> 4) & 0xf])
|
||||||
dbg_log_char (encode[bits & 0xf])
|
dbg_log_char (encode[bits & 0xf])
|
||||||
dbg_log_char (':')
|
dbg_log_char (':')
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
dbg_log_char (encode[(code >> (7 - i)) & 0xf])
|
dbg_log_char (encode[(code >> (4 * (7 - i))) & 0xf])
|
||||||
dbg_log_char (']')
|
dbg_log_char (']')
|
||||||
return
|
return
|
||||||
#else
|
|
||||||
for int i = bits - 1; i >= 0; --i:
|
|
||||||
bool on = code & (1 << i)
|
|
||||||
dbg_led (false, false, false)
|
|
||||||
dbg_sleep (200)
|
|
||||||
if on:
|
|
||||||
dbg_led (true, false, false)
|
|
||||||
else:
|
|
||||||
dbg_led (false, true, false)
|
|
||||||
dbg_sleep (400)
|
|
||||||
dbg_led (false, false, false)
|
|
||||||
dbg_sleep (200)
|
|
||||||
dbg_led (true, true, false)
|
|
||||||
dbg_sleep (50)
|
|
||||||
dbg_led (false, false, false)
|
|
||||||
dbg_sleep (50)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void panic (unsigned n, char const *message):
|
void panic (unsigned n, char const *message):
|
||||||
|
Thread *who = current
|
||||||
// Stop all threads.
|
// Stop all threads.
|
||||||
unschedule ()
|
|
||||||
while first_scheduled:
|
while first_scheduled:
|
||||||
first_scheduled->unrun ()
|
first_scheduled->unrun ()
|
||||||
for Receiver *r = first_alarm; r; r = r->next_alarm:
|
for Receiver *r = first_alarm; r; r = r->next_alarm:
|
||||||
@ -114,8 +64,8 @@ void panic (unsigned n, char const *message):
|
|||||||
if dbg_cap && dbg_cap->target->owner:
|
if dbg_cap && dbg_cap->target->owner:
|
||||||
dbg_cap->target->owner->run ()
|
dbg_cap->target->owner->run ()
|
||||||
// Use the (now running) log thread to display the message.
|
// Use the (now running) log thread to display the message.
|
||||||
|
dbg_log ("Panic: ")
|
||||||
|
dbg_send (n)
|
||||||
dbg_log (message)
|
dbg_log (message)
|
||||||
dbg_log_char ('\n')
|
dbg_log_char ('\n')
|
||||||
else:
|
// If no log capability is registered, the machine just hangs.
|
||||||
while true:
|
|
||||||
dbg_send (n)
|
|
||||||
|
@ -89,12 +89,6 @@ void schedule ():
|
|||||||
if !current:
|
if !current:
|
||||||
current = first_scheduled
|
current = first_scheduled
|
||||||
|
|
||||||
void unschedule ():
|
|
||||||
Thread *old = current
|
|
||||||
schedule ()
|
|
||||||
if old == current:
|
|
||||||
current = NULL
|
|
||||||
|
|
||||||
void timer_interrupt ():
|
void timer_interrupt ():
|
||||||
Receiver *recv, *next
|
Receiver *recv, *next
|
||||||
for recv = first_alarm; recv; recv = next:
|
for recv = first_alarm; recv; recv = next:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user