#pypp 0 #define ARCH #include "kernel.hh" void Thread_arch_init (Thread *thread): thread->arch.at = 0 thread->arch.v0 = 0 thread->arch.v1 = 0 thread->arch.a0 = 0 thread->arch.a1 = 0 thread->arch.a2 = 0 thread->arch.a3 = 0 thread->arch.t0 = 0 thread->arch.t1 = 0 thread->arch.t2 = 0 thread->arch.t3 = 0 thread->arch.t4 = 0 thread->arch.t5 = 0 thread->arch.t6 = 0 thread->arch.t7 = 0 thread->arch.t8 = 0 thread->arch.t9 = 0 thread->arch.gp = 0 thread->arch.fp = 0 thread->arch.ra = 0 thread->arch.hi = 0 thread->arch.lo = 0 thread->arch.k0 = 0 thread->arch.k1 = 0 void Thread_arch_receive (Thread *thread, unsigned d[4], Capability *c[4]): thread->arch.a0 = (unsigned)c[0] thread->arch.a1 = (unsigned)c[1] thread->arch.a2 = (unsigned)c[2] thread->arch.a3 = (unsigned)c[3] thread->arch.t0 = d[0] thread->arch.t1 = d[1] thread->arch.t2 = d[2] thread->arch.t3 = d[3] thread->arch.v0 = 1 void Thread_arch_receive_fail (Thread *thread): thread->arch.v0 = 0 void Memory_arch_init (Memory *mem): mem->arch.asid = 1 mem->arch.directory = NULL static void flush_tlb (unsigned asid): for unsigned tlb = 1; tlb < 32; ++tlb: cp0_set (CP0_INDEX, tlb) __asm__ volatile ("tlbr") unsigned hi cp0_get (CP0_ENTRY_HI, hi) if (hi & 0x1f) == asid: // Set asid to 0, which is only used by the idle task. cp0_set (CP0_ENTRY_HI, 0x2000 * tlb) __asm__ volatile ("tlbwi") void Memory_arch_free (Memory *mem): if !mem->arch.directory: return for unsigned i = 0; i < PAGE_SIZE; ++i: unsigned *table = mem->arch.directory[i] if !table: continue for unsigned j = 0; j < PAGE_SIZE; ++j: Page *page = (Page *)(table[j] & ~3) if !page: continue mem->unmap (page, i * 0x1000 * 0x400 + j * 0x1000) mem->unuse () mem->zfree ((unsigned)table) mem->arch.directory[i] = NULL if (Memory *)asids[mem->arch.asid] == mem: flush_tlb (mem->arch.asid) asids[mem->arch.asid] = asids[0] asids[0] = mem->arch.asid mem->unuse () mem->zfree ((unsigned)mem->arch.directory) bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write): if !mem->arch.directory: mem->arch.directory = (unsigned **)mem->zalloc () if !mem->arch.directory: return false unsigned *table = mem->arch.directory[address >> 22] if !table: table = (unsigned *)mem->zalloc () if !table: return false mem->arch.directory[address >> 22] = table unsigned idx = (address >> 12) & ((1 << 10) - 1) if table[idx]: mem->unmap ((Page *)(table[idx] & ~3), address) table[idx] = write ? (unsigned)page : (unsigned)page + 1 return true void Memory_arch_unmap (Memory *mem, Page *page, unsigned address): unsigned *table = mem->arch.directory[address >> 22] table[(address >> 12) & ((1 << 10) - 1)] = 0 Page *Memory_arch_get_mapping (Memory *mem, unsigned address, bool *writable): unsigned *table = mem->arch.directory[address >> 22] unsigned v = table[(address >> 12) & ((1 << 10) - 1)] if writable: *writable = !(v & 1) return (Page *)(v & ~1) void arch_invoke (): Capability *target, *c[4] bool wait, copy[4] Thread *caller = current target = caller->address_space->find_capability (current->arch.v0, &wait) if wait: caller->wait () if !target: // TODO: there must be no action here. This is just because the rest doesn't work yet. dbg_led (caller->arch.a0, caller->arch.a1, caller->arch.a2) dbg_sleep (1000) 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 if caller != current: if (Memory *)asids[current->address_space->arch.asid] != current->address_space: if asids[0]: current->address_space->arch.asid = asids[0] asids[0] = asids[asids[0]] else: static unsigned random = 1 current->address_space->arch.asid = random // Overwrite used asid, so flush those values from tlb. flush_tlb (random) ++random if random >= 64: random = 1 asids[current->address_space->arch.asid] = (unsigned)current cp0_set (CP0_ENTRY_HI, current->address_space->arch.asid)