From 35fb72c239992d37059deb34c2a1eb45ce93ffe2 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Wed, 27 May 2009 14:38:52 +0200 Subject: [PATCH] working again with new paging layout --- boot-programs/sos.h | 6 ++++- entry.S | 18 ++++++++++---- init.ccp | 10 ++++++-- interrupts.ccp | 5 ++-- invoke.ccp | 60 +++++++++++++++++++++++++++++++++++++++------ mips.ccp | 37 ++++++++++++++++++---------- test.ccp | 5 ++-- 7 files changed, 108 insertions(+), 33 deletions(-) diff --git a/boot-programs/sos.h b/boot-programs/sos.h index 1fc24a2..6b582e0 100644 --- a/boot-programs/sos.h +++ b/boot-programs/sos.h @@ -28,7 +28,9 @@ extern "C" { #define CAP_RECEIVER_CREATE_CAPABILITY 2 #define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3 /* Not an operation; a capability with this bit set is a call capability. */ -#define CAP_RECEIVER_CALL 4 +#define CAP_RECEIVER_CALL 8 +/* Same thing for reply capability. */ +#define CAP_RECEIVER_REPLY 9 #define CAP_MEMORY_CREATE 1 #define CAP_MEMORY_DESTROY 2 @@ -44,6 +46,8 @@ extern "C" { /* Flag values for processor state */ #define THREAD_FLAG_WAITING 0x80000000 #define THREAD_FLAG_RUNNING 0x40000000 +#define THREAD_FLAG_PRIV 0x20000000 +#define THREAD_FLAG_USER 0x1fffffff #define CAP_PAGE_MAP 1 #define CAP_PAGE_SHARE 2 diff --git a/entry.S b/entry.S index 3eb6c41..b58e9e6 100644 --- a/entry.S +++ b/entry.S @@ -11,6 +11,7 @@ #include "arch.hh" addr_000: +#if 0 // TLB refill bne $zero, $k0, slow_refill nop @@ -40,8 +41,10 @@ addr_000: slow_refill0: move $k1, $zero slow_refill: +#endif sw $ra, -0xd88($zero) bal save_regs + nop la $t9, tlb_refill jr $t9 nop @@ -50,26 +53,33 @@ addr_100: // Cache error sw $ra, -0xd88($zero) bal save_regs + nop la $t9, cache_error jr $t9 nop .fill 0x180 - (. - addr_000) addr_180: // General exception + // Allow new exceptions to update EPC and friends. + mtc0 $zero, $CP0_STATUS sw $ra, -0xd88($zero) bal save_regs + nop la $t9, exception jr $t9 nop - .fill 0x200 - (. - addr_000) + .fill 0x200 - (. - addr_000) - 8 + .word 0x0000001e // 1f8 EntryLo data for idle page. + .word 0x80000000 // 1fc A pointer to the current page. addr_200: // Interrupt sw $ra, -0xd88($zero) bal save_regs + nop la $t9, interrupt jr $t9 nop - .fill 0x280 - (. - addr_000) - 16 + .fill 0x280 - (. - addr_000) - 20 directory: .word 0 // -d94 == directory @@ -79,9 +89,7 @@ directory: .word 0 // -d88 == ra .word _gp // -d84 == gp - .word idle_page // 280 - .word 0x80000000 // 284 A pointer to the current page. -start_idle: // 288 +start_idle: // 280 // Wait for the next interrupt, then the first thread will be scheduled. // It is impractical to try to call schedule, because for that the // idle task would need to own capabilities. diff --git a/init.ccp b/init.ccp index c1facda..3bfc500 100644 --- a/init.ccp +++ b/init.ccp @@ -24,6 +24,8 @@ static void init_idle (): idle_memory.limit = 0 idle_memory.used = 0 idle_memory.arch.directory = (unsigned **)0x80000000 + // Shadow is never used for the idle task. + idle_memory.arch.shadow = NULL idle_memory.arch.asid = 0 // initialize idle_page idle_page.prev = NULL @@ -69,12 +71,16 @@ static void init_cp0 (): cp0_set0 (CP0_INDEX) __asm__ volatile ("tlbwi") // Fill the idle task's page in useg. Set it to non-cachable. - cp0_set (CP0_ENTRY_HI, 0x284a0000) + // its directory entry is at 1fc, so it's number 7f (0fe00000). + // its table entry is at 1f8, so it's number 7e (0007e000). + // its address is 280 (00000280), used below for EPC. + unsigned const idle_entry_hi = 0x0fe7e000 + cp0_set (CP0_ENTRY_HI, idle_entry_hi) cp0_set (CP0_ENTRY_LO0, 0x16) cp0_set (CP0_ENTRY_LO1, 0x14) __asm__ volatile ("tlbwr") // Allow eret to be used to jump to the idle task. - cp0_set (CP0_EPC, 0x284a0288) + cp0_set (CP0_EPC, (idle_entry_hi & PAGE_MASK) | 0x280) // Wait with initializing the status register until the last moment, so that // exceptions in the bootup code will fill EPC and friends. diff --git a/interrupts.ccp b/interrupts.ccp index 2be25ae..e4aea00 100644 --- a/interrupts.ccp +++ b/interrupts.ccp @@ -41,6 +41,7 @@ Thread *interrupt (): Thread *exception (): unsigned cause cp0_get (CP0_CAUSE, cause) + //dbg_send (cause >> 2, 5) switch (cause >> 2) & 0x1f: case 0: // Interrupt. This shouldn't happen, since CAUSE[IV] == 1. @@ -68,10 +69,8 @@ Thread *exception (): panic (0x81223344, "Bus error load or store.") case 8: // Syscall. - // DEBUG: allow new exceptions. - //cp0_set0 (CP0_STATUS) arch_invoke () - return current + break case 9: // Breakpoint. panic (0x91223344, "Breakpoint.") diff --git a/invoke.ccp b/invoke.ccp index d3f1dd3..dfd88a4 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -20,6 +20,7 @@ Capability *Memory::find_capability (unsigned code, bool *copy): return NULL static Capability *reply +static Receiver *reply_receiver static void reply_cap (unsigned target, unsigned protected_data): Capability r @@ -33,19 +34,28 @@ static void reply_cap (unsigned target, unsigned protected_data): unsigned d[4] = { 0, 0, 0, 0 } Capability *caps[4] = { &r, NULL, NULL, NULL } bool cops[4] = { true, false, false, false } - reply->invoke (d, caps, cops) + if reply: + reply->invoke (d, caps, cops) + else: + // TODO: send message to reply_receiver static void reply_cap (Capability *cap, bool copy): unsigned d[4] = { 0, 0, 0, 0 } Capability *caps[4] = { cap, NULL, NULL, NULL } bool cops[4] = { copy, false, false, false } - reply->invoke (d, caps, cops) + if reply: + reply->invoke (d, caps, cops) + else: + // TODO: send message to reply_receiver static void reply_num (unsigned num): unsigned d[4] = { num, 0, 0, 0 } Capability *caps[4] = { NULL, NULL, NULL, NULL } bool cops[4] = { false, false, false, false } - reply->invoke (d, caps, cops) + if reply: + reply->invoke (d, caps, cops) + else: + // TODO: send message to reply_receiver static void admin_invoke (unsigned target, Capability *cap, unsigned request, unsigned data): switch request: @@ -117,7 +127,32 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability return break case CAP_MEMORY_DESTROY: - // TODO + if !cap || cap->address_space != mem || (unsigned)cap->target & ~KERNEL_MASK: + return + switch (unsigned)cap->target & CAPTYPE_MASK: + case CAPTYPE_ADMIN: + // Admin capabilities don't take space, so they cannot be destroyed. + return + case CAPTYPE_RECEIVER: + mem->free_receiver ((Receiver *)cap->protected_data) + return + case CAPTYPE_MEMORY: + mem->free_memory ((Memory *)cap->protected_data) + return + case CAPTYPE_THREAD: + mem->free_thread ((Thread *)cap->protected_data) + return + case CAPTYPE_PAGE: + mem->free_page ((Page *)cap->protected_data) + return + case CAPTYPE_CAPABILITY: + mem->free_capability ((Capability *)cap->protected_data) + return + case CAPTYPE_CAPPAGE: + mem->free_cappage ((Cappage *)cap->protected_data) + return + default: + panic (0x55228930, "invalid case") break case CAP_MEMORY_LIST: // TODO @@ -205,7 +240,7 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[ // other parameters' meanings depend on the operation. if !((1 << d[0]) & target & ~REQUEST_MASK): // You are not allowed to perform this operation. - return false + return true reply = c[0] if d[0] == CAP_DEGRADE: reply_cap (target & d[1], protected_data) @@ -215,10 +250,21 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, unsigned d[ admin_invoke (target, c[1], d[0], d[1]) break case CAPTYPE_RECEIVER: - if target & CAP_RECEIVER_CALL: + if target & (1 << CAP_RECEIVER_CALL): // This is a call capability. + protected_data = c[0]->protected_data + target = (unsigned)c[0]->target + if ~(unsigned)c[0]->target & ~KERNEL_MASK: + // TODO: create reply capability. + else: + // Kernel call: don't create actual capablities. + reply = NULL + reply_receiver = (Receiver *)protected_data + return kernel_invoke (target, protected_data, d, c, copy) + if target & (1 << CAP_RECEIVER_REPLY): + // This is a reply capability. // TODO - return false + return true receiver_invoke (target, protected_data, c[1], d[0], d[1]) break case CAPTYPE_MEMORY: diff --git a/mips.ccp b/mips.ccp index f14d1a2..e0ae5ec 100644 --- a/mips.ccp +++ b/mips.ccp @@ -139,6 +139,8 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write): if !mem->arch.first_page_table: mem->zfree ((unsigned)mem->arch.directory) mem->zfree ((unsigned)mem->arch.shadow) + mem->arch.directory = NULL + mem->arch.shadow = NULL return false t = alloc_page_table (mem) if !t: @@ -146,8 +148,11 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write): if !mem->arch.first_page_table: mem->zfree ((unsigned)mem->arch.directory) mem->zfree ((unsigned)mem->arch.shadow) + mem->arch.directory = NULL + mem->arch.shadow = NULL return false mem->arch.directory[address >> 21] = table + mem->arch.shadow[address >> 21] = t arch_page *p = alloc_page (mem, t) if !p: if !t->first_page: @@ -157,7 +162,7 @@ bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write): unsigned idx = (address >> 12) & ((1 << 9) - 1) if table[idx]: mem->unmap ((Page *)table[idx + 0x200], address) - table[idx] = page->physical ? (page->physical >> 6) | 0x18 | (write ? 0x4 : 0) | 0x2 : 0 + table[idx] = page->physical ? ((page->physical & ~0x80000000) >> 6) | 0x18 | (write ? 0x4 : 0) | 0x2 : 0 table[idx + 0x200] = (unsigned)p p->mapping = address p->page = page @@ -199,17 +204,17 @@ void arch_invoke (): schedule () // Calling an invalid capability always fails. caller->arch.v0 = 0 - return - c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0]) - c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1]) - c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2]) - c[3] = caller->address_space->find_capability (caller->arch.a3, ©[3]) - unsigned d[4] - d[0] = caller->arch.t0 - d[1] = caller->arch.t1 - d[2] = caller->arch.t2 - d[3] = caller->arch.t3 - caller->arch.v0 = target->invoke (d, c, copy) ? 1 : 0 + else: + c[0] = caller->address_space->find_capability (caller->arch.a0, ©[0]) + c[1] = caller->address_space->find_capability (caller->arch.a1, ©[1]) + c[2] = caller->address_space->find_capability (caller->arch.a2, ©[2]) + c[3] = caller->address_space->find_capability (caller->arch.a3, ©[3]) + unsigned d[4] + d[0] = caller->arch.t0 + d[1] = caller->arch.t1 + d[2] = caller->arch.t2 + d[3] = caller->arch.t3 + caller->arch.v0 = target->invoke (d, c, copy) ? 1 : 0 if caller != current: if (Memory *)asids[current->address_space->arch.asid] != current->address_space: if asids[0]: @@ -223,6 +228,12 @@ void arch_invoke (): ++random if random >= 64: random = 1 - asids[current->address_space->arch.asid] = (unsigned)current + asids[current->address_space->arch.asid] = (unsigned)current->address_space cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid) directory = current->address_space->arch.directory + unsigned status + cp0_get (CP0_STATUS, status) + status &= 0x0fffffff + if current->flags & THREAD_FLAG_PRIV: + status |= 0x10000000 + cp0_set (CP0_STATUS, status | 0x13) diff --git a/test.ccp b/test.ccp index 6465ef9..6473161 100644 --- a/test.ccp +++ b/test.ccp @@ -80,7 +80,7 @@ void dbg_sleep (unsigned ms): __gpio_as_output (CAPSLOCKLED_IO) void dbg_send (unsigned code, unsigned bits): - for int i = bits; i >= 0; --i: + for int i = bits - 1; i >= 0; --i: bool on = code & (1 << i) dbg_led (false, false, false) dbg_sleep (200) @@ -92,5 +92,6 @@ void dbg_send (unsigned code, unsigned bits): dbg_led (false, false, false) dbg_sleep (200) dbg_led (true, true, false) - dbg_sleep (200) + dbg_sleep (500) dbg_led (false, false, false) + dbg_sleep (500)