mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
working lcd log with panic
This commit is contained in:
@@ -314,4 +314,3 @@ void arch_register_interrupt (unsigned num, Receiver *r):
|
||||
intc_unmask_irq (num)
|
||||
else:
|
||||
intc_mask_irq (num)
|
||||
dbg_code = 0
|
||||
|
||||
@@ -121,16 +121,22 @@ static void init_threads ():
|
||||
for unsigned j = 0; j < SELFMAG; ++j:
|
||||
if header->e_ident[j] != ELFMAG[j]:
|
||||
panic (i * 0x1000 + j, "invalid ELF magic")
|
||||
return
|
||||
if header->e_ident[EI_CLASS] != ELFCLASS32:
|
||||
panic (i * 0x1000 + EI_CLASS, "invalid ELF class")
|
||||
return
|
||||
if header->e_ident[EI_DATA] != ELFDATA2LSB:
|
||||
panic (i * 0x1000 + EI_DATA, "invalid ELF data")
|
||||
return
|
||||
if header->e_ident[EI_VERSION] != EV_CURRENT:
|
||||
panic (i * 0x1000 + EI_VERSION, "invalid ELF version")
|
||||
return
|
||||
if header->e_type != ET_EXEC:
|
||||
panic (i * 0x1000 + 0x10, "invalid ELF type")
|
||||
return
|
||||
if header->e_machine != EM_MIPS_RS3_LE && header->e_machine != EM_MIPS:
|
||||
panic (i * 0x1000 + 0x12, "invalid ELF machine")
|
||||
return
|
||||
thread->pc = header->e_entry
|
||||
thread->sp = 0x80000000
|
||||
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
|
||||
if ((file_offset + shdr->sh_size) >> PAGE_BITS) >= (PAGE_SIZE >> 2):
|
||||
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:
|
||||
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||
unsigned idx = file_offset + section_offset
|
||||
@@ -154,24 +161,30 @@ static void init_threads ():
|
||||
mem->use ()
|
||||
if !mem->map (pages[idx], p, writable):
|
||||
panic (0x22446688, "unable to map initial page")
|
||||
return
|
||||
else:
|
||||
if !writable:
|
||||
panic (0x33399993, "unwritable bss section")
|
||||
return
|
||||
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:
|
||||
page = mem->alloc_page ()
|
||||
if !page:
|
||||
panic (0x00220022, "out of memory")
|
||||
return
|
||||
page->data.frame = mem->zalloc ()
|
||||
if !page->data.frame:
|
||||
panic (0x02220022, "out of memory");
|
||||
return
|
||||
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")
|
||||
return
|
||||
else:
|
||||
if !writable:
|
||||
panic (0x20203030, "bss section starts on read-only page")
|
||||
return
|
||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||
if a >= shdr->sh_addr + shdr->sh_size:
|
||||
break
|
||||
@@ -188,6 +201,7 @@ static void init_threads ():
|
||||
stackpage->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||
if !stackpage || !mem->map (stackpage, 0x7ffff000, true):
|
||||
panic (0x13151719, "unable to map initial stack page")
|
||||
return
|
||||
Receiver *recv = mem->alloc_receiver ()
|
||||
recv->owner = thread
|
||||
thread->receivers = recv
|
||||
|
||||
@@ -24,17 +24,17 @@ void arch_flush_cache ():
|
||||
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
|
||||
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
||||
|
||||
static void handle_exit (Thread *old_current):
|
||||
static void handle_exit ():
|
||||
if !current || (current == &idle):
|
||||
schedule ()
|
||||
if !current:
|
||||
current = &idle
|
||||
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")
|
||||
if !current:
|
||||
current = &idle
|
||||
if old_current == current:
|
||||
return
|
||||
dbg_send ((unsigned)current >> PAGE_BITS, 3)
|
||||
arch_flush_cache ()
|
||||
if current != &idle:
|
||||
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.
|
||||
Thread *tlb_refill ():
|
||||
//panic (0x88776655, "TLB refill")
|
||||
Thread *old_current = current
|
||||
old_current = current
|
||||
if !directory:
|
||||
panic (0x44449999, "No directory")
|
||||
handle_exit ()
|
||||
return current
|
||||
unsigned EntryHi
|
||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||
unsigned *t = directory[EntryHi >> 21]
|
||||
if !t:
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
panic (0x99992222, "No page table")
|
||||
// - 2 instead of - 1 means reset bit 0
|
||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||
cp0_set (CP0_ENTRY_LO0, t[idx])
|
||||
cp0_set (CP0_ENTRY_LO1, t[idx + 1])
|
||||
__asm__ volatile ("tlbwr")
|
||||
handle_exit (old_current)
|
||||
else:
|
||||
// - 2 instead of - 1 means reset bit 0
|
||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||
cp0_set (CP0_ENTRY_LO0, t[idx])
|
||||
cp0_set (CP0_ENTRY_LO1, t[idx + 1])
|
||||
__asm__ volatile ("tlbwr")
|
||||
handle_exit ()
|
||||
return current
|
||||
|
||||
/// An interrupt which is not an exception has occurred.
|
||||
Thread *interrupt ():
|
||||
//panic (0x88877722, "Interrupt")
|
||||
Thread *old_current = current
|
||||
old_current = current
|
||||
unsigned ipr = INTC_IPR
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
if ipr & (1 << i):
|
||||
@@ -103,14 +106,13 @@ Thread *interrupt ():
|
||||
c.data[j] = 0
|
||||
c.cap[j] = NULL
|
||||
c.copy[j] = false
|
||||
dbg_code = (unsigned)arch_interrupt_receiver[i]->owner
|
||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||
arch_interrupt_receiver[i] = NULL
|
||||
if ipr & (1 << IRQ_OST0):
|
||||
ost_clear_uf (0)
|
||||
intc_ack_irq (IRQ_OST0)
|
||||
timer_interrupt ()
|
||||
handle_exit (old_current)
|
||||
handle_exit ()
|
||||
return current
|
||||
|
||||
void flush_tlb (unsigned asid):
|
||||
@@ -127,85 +129,91 @@ void flush_tlb (unsigned asid):
|
||||
static void arch_invoke ():
|
||||
Capability *target
|
||||
bool wait
|
||||
Thread *caller = current
|
||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
||||
target = old_current->address_space->find_capability (old_current->arch.v0, &wait)
|
||||
do_schedule = false
|
||||
if wait:
|
||||
unschedule ()
|
||||
caller->wait ()
|
||||
old_current->wait ()
|
||||
if !target:
|
||||
dbg_send (0, 0)
|
||||
//dbg_send (0, 0)
|
||||
// There must be no action here.
|
||||
else:
|
||||
Capability::Context c
|
||||
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[2] = caller->address_space->find_capability (caller->arch.a2, &c.copy[2])
|
||||
c.cap[3] = caller->address_space->find_capability (caller->arch.a3, &c.copy[3])
|
||||
c.data[0] = caller->arch.t0
|
||||
c.data[1] = caller->arch.t1
|
||||
c.data[2] = caller->arch.t2
|
||||
c.data[3] = caller->arch.t3
|
||||
c.cap[0] = old_current->address_space->find_capability (old_current->arch.a0, &c.copy[0])
|
||||
c.cap[1] = old_current->address_space->find_capability (old_current->arch.a1, &c.copy[1])
|
||||
c.cap[2] = old_current->address_space->find_capability (old_current->arch.a2, &c.copy[2])
|
||||
c.cap[3] = old_current->address_space->find_capability (old_current->arch.a3, &c.copy[3])
|
||||
c.data[0] = old_current->arch.t0
|
||||
c.data[1] = old_current->arch.t1
|
||||
c.data[2] = old_current->arch.t2
|
||||
c.data[3] = old_current->arch.t3
|
||||
target->invoke (&c)
|
||||
if do_schedule:
|
||||
// If the call was to schedule without wait, it isn't done yet.
|
||||
if !wait:
|
||||
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 caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||
current = caller
|
||||
if old_current != current && (old_current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||
current = old_current
|
||||
|
||||
/// A general exception has occurred.
|
||||
Thread *exception ():
|
||||
Thread *old_current = current
|
||||
old_current = current
|
||||
unsigned cause
|
||||
cp0_get (CP0_CAUSE, cause)
|
||||
switch (cause >> 2) & 0x1f:
|
||||
case 0:
|
||||
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
||||
panic (0x01223344, "Interrupt on exception vector.")
|
||||
break
|
||||
case 1:
|
||||
// TLB modification.
|
||||
panic (0x11223344, "TLB modification.")
|
||||
break
|
||||
case 2:
|
||||
// TLB load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
panic (0x21223344, "TLB load or instruction fetch.")
|
||||
break
|
||||
case 3:
|
||||
// TLB store.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
panic (0x31223344, "TLB store.")
|
||||
break
|
||||
case 4:
|
||||
// Address error load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a)
|
||||
//dbg_send (a)
|
||||
panic (0x41223344, "Address error load or instruction fetch.")
|
||||
break
|
||||
case 5:
|
||||
// Address error store.
|
||||
dbg_send (current->arch.v1, 4)
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (*(unsigned *)(a & ~3), 32)
|
||||
dbg_send (a, 32)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a, 32)
|
||||
//dbg_send (current->arch.v1, 4)
|
||||
//unsigned a
|
||||
//cp0_get (CP0_EPC, a)
|
||||
//dbg_send (*(unsigned *)(a & ~3), 32)
|
||||
//dbg_send (a, 32)
|
||||
//cp0_get (CP0_BAD_V_ADDR, a)
|
||||
//dbg_send (a, 32)
|
||||
panic (0x51223344, "Address error store.")
|
||||
break
|
||||
case 6:
|
||||
// Bus error instruction fetch.
|
||||
panic (0x61223344, "Bus error instruction fetch.")
|
||||
break
|
||||
case 7:
|
||||
// Bus error load or store.
|
||||
panic (0x71223344, "Bus error load or store.")
|
||||
break
|
||||
case 8:
|
||||
// Syscall.
|
||||
current->pc += 4
|
||||
@@ -218,10 +226,12 @@ Thread *exception ():
|
||||
if current->arch.a0:
|
||||
if dbg_cap:
|
||||
panic (0x34259380, "Break instruction while log capability was already set")
|
||||
break
|
||||
bool dummy
|
||||
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
||||
if !dbg_cap:
|
||||
panic (0x06111129, "no log capability provided")
|
||||
break
|
||||
break
|
||||
if dbg_cap:
|
||||
dbg_log_char (current->arch.a1)
|
||||
@@ -230,27 +240,35 @@ Thread *exception ():
|
||||
case 10:
|
||||
// Reserved instruction.
|
||||
panic (0xa1223344, "Reserved instruction.")
|
||||
break
|
||||
case 11:
|
||||
// Coprocessor unusable.
|
||||
panic (0xb1223344, "Coprocessor unusable.")
|
||||
break
|
||||
case 12:
|
||||
// Arithmetic overflow.
|
||||
panic (0xc1223344, "Arithmetic overflow.")
|
||||
break
|
||||
case 13:
|
||||
// Trap.
|
||||
panic (0xd1223344, "Trap.")
|
||||
break
|
||||
case 15:
|
||||
// Floating point exception.
|
||||
panic (0xe1223344, "Floating point exception.")
|
||||
break
|
||||
case 23:
|
||||
// Reference to WatchHi/WatchLo address.
|
||||
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
|
||||
break
|
||||
case 24:
|
||||
// Machine check.
|
||||
panic (0xf3223344, "Machine check.")
|
||||
break
|
||||
case 30:
|
||||
// Cache error (EJTAG only).
|
||||
panic (0xf4223344, "Cache error (EJTAG only).")
|
||||
break
|
||||
case 14:
|
||||
case 16:
|
||||
case 17:
|
||||
@@ -267,14 +285,16 @@ Thread *exception ():
|
||||
case 31:
|
||||
// Reserved.
|
||||
panic (0xf5223344, "Reserved exception code")
|
||||
break
|
||||
default:
|
||||
panic (0xf6223344, "Impossible exception code")
|
||||
handle_exit (old_current)
|
||||
break
|
||||
handle_exit ()
|
||||
return current
|
||||
|
||||
/// There's a cache error. Big trouble. Probably not worth trying to recover.
|
||||
Thread *cache_error ():
|
||||
panic (0x33333333, "cache error")
|
||||
Thread *old_current = current
|
||||
handle_exit (old_current)
|
||||
old_current = current
|
||||
handle_exit ()
|
||||
return current
|
||||
|
||||
Reference in New Issue
Block a user