From b7d9b1554c28f19063e5c80d31f6bec87e6ae350 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Fri, 24 Jul 2009 14:25:53 +0200 Subject: [PATCH] working lcd log with panic --- boot-programs/gpio.ccp | 3 +- boot-programs/init.ccp | 15 +++--- boot-programs/lcd.ccp | 2 +- invoke.ccp | 23 ++++----- kernel.hhp | 10 ++-- memory.ccp | 3 +- mips/arch.ccp | 1 - mips/init.ccp | 14 +++++ mips/interrupts.ccp | 114 ++++++++++++++++++++++++----------------- panic.ccp | 64 +++-------------------- schedule.ccp | 6 --- 11 files changed, 116 insertions(+), 139 deletions(-) diff --git a/boot-programs/gpio.ccp b/boot-programs/gpio.ccp index 6bbae3d..8176801 100644 --- a/boot-programs/gpio.ccp +++ b/boot-programs/gpio.ccp @@ -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. int main (): - for unsigned i = 0; i < 10; ++i: - schedule () + schedule () *(unsigned *)~3 = 0 map_gpio () diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index 505b14f..3f37f1c 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -67,20 +67,23 @@ static void setup (): invoke_01 (pwm, 1) int main (): - for unsigned i = 0; i < 10; ++i: - schedule () - setup () + schedule () kdebug ("start init") + setup () + kdebug ("run init") while true: Message msg wait (&msg) switch msg.protected_data: case KBD: - invoke_01 (lockleds, 0x4 | (msg.data[0] >> 16)) + kdebug ("keyboard event") break case TP: - invoke_01 (lockleds, 0x2 | (msg.data[0] >> 16)) + kdebug ("touchpad event") break case POWERBUTTON: - case BATTERY: + kdebug ("powerbutton event") + break + case BATTERY: + kdebug ("battery event") break diff --git a/boot-programs/lcd.ccp b/boot-programs/lcd.ccp index 8e71c2e..e385f0d 100644 --- a/boot-programs/lcd.ccp +++ b/boot-programs/lcd.ccp @@ -106,7 +106,7 @@ static void log_num (unsigned n): char const *encode = "0123456789abcdef" log_char ('[') for unsigned i = 0; i < 8; ++i: - log_char (encode[(n >> (7 - i)) & 0xf]) + log_char (encode[(n >> (4 * (7 - i))) & 0xf]) log_char (']') static void log_msg (Message *msg): diff --git a/invoke.ccp b/invoke.ccp index 645a773..8a5748c 100644 --- a/invoke.ccp +++ b/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]) if !c->cap[i]: panic (0xdddddddd, "out of memory") + return false for unsigned j = 0; j < i; ++j: owner->address_space->free_capability (c->cap[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: case CAPTYPE_RECEIVER: mem->free_receiver ((Receiver *)c->cap[0]->protected_data) - return + break case CAPTYPE_MEMORY: mem->free_memory ((Memory *)c->cap[0]->protected_data) - return + break case CAPTYPE_THREAD: mem->free_thread ((Thread *)c->cap[0]->protected_data) - return + break case CAPTYPE_PAGE: mem->free_page ((Page *)c->cap[0]->protected_data) - return + break case CAPTYPE_CAPABILITY: mem->free_capability ((Capability *)c->cap[0]->protected_data) - return + break case CAPTYPE_CAPPAGE: mem->free_cappage ((Cappage *)c->cap[0]->protected_data) - return + break default: panic (0x55228930, "invalid case") + return break case CAP_MEMORY_LIST: // 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]) if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING): if v & THREAD_FLAG_WAITING: - if !(thread->is_waiting ()): - if thread == current: - unschedule () - thread->wait () + thread->wait () else - if thread->is_waiting (): - thread->unwait () + thread->unwait () if (v & THREAD_FLAG_RUNNING) != (*value & THREAD_FLAG_RUNNING): if v & THREAD_FLAG_RUNNING: thread->run () @@ -798,6 +796,7 @@ static void kernel_invoke (unsigned target, unsigned protected_data, Capability: break default: panic (0x99337744, "invalid capability type invoked") + return return void Capability::invoke (Capability::Context *c): diff --git a/kernel.hhp b/kernel.hhp index a3a70a7..a4a0fdc 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -66,6 +66,8 @@ struct Thread : public Object : Thread_arch arch unsigned flags Thread *schedule_prev, *schedule_next + Thread *exception + void raise (unsigned code) void run () void unrun () void wait () @@ -173,9 +175,7 @@ struct Memory : public Object : extern "C": // Panic. n is sent over caps led. message is currently ignored. void panic (unsigned n, char const *message = "") - // Debug: switch caps led - void dbg_led (bool one, bool two, bool three) - void dbg_sleep (unsigned ms) + // Debug: send a message to the user. void dbg_send (unsigned code, unsigned bits = 32) EXTERN unsigned dbg_code EXTERN Capability *dbg_cap @@ -184,8 +184,6 @@ extern "C": /// Defined in schedule.ccp 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 () EXTERN Memory top_memory @@ -194,7 +192,7 @@ EXTERN Thread idle EXTERN Memory idle_memory EXTERN Page idle_page EXTERN Thread *first_scheduled -EXTERN Thread *current +EXTERN Thread *current, *old_current EXTERN bool do_schedule // Defined in memory.cc diff --git a/memory.ccp b/memory.ccp index 186f805..351229f 100644 --- a/memory.ccp +++ b/memory.ccp @@ -20,6 +20,7 @@ unsigned init_memory (unsigned mem): unsigned phys_alloc (unsigned num): if free_begin + num * PAGE_SIZE > free_end: panic (0xaaaaaaaa, "out of memory") + return 0 unsigned ret = free_begin free_begin += num * PAGE_SIZE clear_page (ret, num) @@ -131,7 +132,7 @@ void raw_pfree (unsigned page): unsigned Memory::zalloc (): if !use (): - assert (false) + panic (0x4536928, "no memory due to limit") return NULL return raw_zalloc () diff --git a/mips/arch.ccp b/mips/arch.ccp index 76c20e5..2bcc665 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -314,4 +314,3 @@ void arch_register_interrupt (unsigned num, Receiver *r): intc_unmask_irq (num) else: intc_mask_irq (num) - dbg_code = 0 diff --git a/mips/init.ccp b/mips/init.ccp index 3be46ad..099ae8c 100644 --- a/mips/init.ccp +++ b/mips/init.ccp @@ -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 diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index 570b3f6..785e201 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -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 diff --git a/panic.ccp b/panic.ccp index 3988cdf..00127b4 100644 --- a/panic.ccp +++ b/panic.ccp @@ -19,40 +19,6 @@ #define ARCH #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): if !dbg_cap: return @@ -63,6 +29,8 @@ void dbg_log_char (unsigned ch): c.data[i] = 0 c.data[0] = ch dbg_cap->invoke (&c) + if dbg_cap->target->owner: + current = dbg_cap->target->owner void dbg_log (char const *str): while *str: @@ -71,37 +39,19 @@ void dbg_log (char const *str): void dbg_send (unsigned code, unsigned bits): if bits > 32: bits = 32 - #if 0 char const *encode = "0123456789abcdef" dbg_log_char ('[') dbg_log_char (encode[(bits >> 4) & 0xf]) dbg_log_char (encode[bits & 0xf]) dbg_log_char (':') for unsigned i = 0; i < 8; ++i: - dbg_log_char (encode[(code >> (7 - i)) & 0xf]) + dbg_log_char (encode[(code >> (4 * (7 - i))) & 0xf]) dbg_log_char (']') 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): + Thread *who = current // Stop all threads. - unschedule () while first_scheduled: first_scheduled->unrun () 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: dbg_cap->target->owner->run () // Use the (now running) log thread to display the message. + dbg_log ("Panic: ") + dbg_send (n) dbg_log (message) dbg_log_char ('\n') - else: - while true: - dbg_send (n) + // If no log capability is registered, the machine just hangs. diff --git a/schedule.ccp b/schedule.ccp index 8a62a9c..9c213f1 100644 --- a/schedule.ccp +++ b/schedule.ccp @@ -89,12 +89,6 @@ void schedule (): if !current: current = first_scheduled -void unschedule (): - Thread *old = current - schedule () - if old == current: - current = NULL - void timer_interrupt (): Receiver *recv, *next for recv = first_alarm; recv; recv = next: