1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-07 17:56:43 +03:00
iris/mips.ccp

150 lines
4.4 KiB
Plaintext
Raw Normal View History

2009-05-20 23:07:56 +03:00
#pypp 0
2009-05-22 23:48:49 +03:00
#define ARCH
2009-05-20 23:07:56 +03:00
#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
2009-05-25 01:31:35 +03:00
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
2009-05-20 23:07:56 +03:00
void Memory_arch_init (Memory *mem):
2009-05-24 13:22:22 +03:00
mem->arch.asid = 1
2009-05-20 23:07:56 +03:00
mem->arch.directory = NULL
2009-05-24 13:22:22 +03:00
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")
2009-05-20 23:07:56 +03:00
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 ()
2009-05-22 23:48:49 +03:00
mem->zfree ((unsigned)table)
2009-05-20 23:07:56 +03:00
mem->arch.directory[i] = NULL
2009-05-24 13:22:22 +03:00
if (Memory *)asids[mem->arch.asid] == mem:
flush_tlb (mem->arch.asid)
asids[mem->arch.asid] = asids[0]
asids[0] = mem->arch.asid
2009-05-20 23:07:56 +03:00
mem->unuse ()
2009-05-22 23:48:49 +03:00
mem->zfree ((unsigned)mem->arch.directory)
2009-05-20 23:07:56 +03:00
bool Memory_arch_map (Memory *mem, Page *page, unsigned address, bool write):
2009-05-23 21:55:31 +03:00
if !mem->arch.directory:
mem->arch.directory = (unsigned **)mem->zalloc ()
if !mem->arch.directory:
return false
2009-05-24 13:22:22 +03:00
unsigned *table = mem->arch.directory[address >> 22]
2009-05-20 23:07:56 +03:00
if !table:
table = (unsigned *)mem->zalloc ()
if !table:
return false
2009-05-24 13:22:22 +03:00
mem->arch.directory[address >> 22] = table
unsigned idx = (address >> 12) & ((1 << 10) - 1)
2009-05-20 23:07:56 +03:00
if table[idx]:
mem->unmap ((Page *)(table[idx] & ~3), address)
table[idx] = write ? (unsigned)page : (unsigned)page + 1
2009-05-23 21:55:31 +03:00
return true
2009-05-20 23:07:56 +03:00
void Memory_arch_unmap (Memory *mem, Page *page, unsigned address):
2009-05-24 13:22:22 +03:00
unsigned *table = mem->arch.directory[address >> 22]
table[(address >> 12) & ((1 << 10) - 1)] = 0
2009-05-20 23:07:56 +03:00
2009-05-24 13:22:22 +03:00
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)
2009-05-23 21:55:31 +03:00
return (Page *)(v & ~1)
2009-05-20 23:07:56 +03:00
2009-05-23 21:55:31 +03:00
void arch_invoke ():
2009-05-25 01:31:35 +03:00
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 ()
2009-05-20 23:07:56 +03:00
if !target:
// TODO: there must be no action here. This is just because the rest doesn't work yet.
2009-05-25 01:31:35 +03:00
dbg_led (caller->arch.a0, caller->arch.a1, caller->arch.a2)
2009-05-23 21:55:31 +03:00
dbg_sleep (1000)
2009-05-20 23:07:56 +03:00
schedule ()
2009-05-25 01:31:35 +03:00
// Calling an invalid capability always fails.
caller->arch.v0 = 0
2009-05-20 23:07:56 +03:00
return
2009-05-25 01:31:35 +03:00
c[0] = caller->address_space->find_capability (caller->arch.a0, &copy[0])
c[1] = caller->address_space->find_capability (caller->arch.a1, &copy[1])
c[2] = caller->address_space->find_capability (caller->arch.a2, &copy[2])
c[3] = caller->address_space->find_capability (caller->arch.a3, &copy[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)