mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-08-21 23:56:48 +03:00
126 lines
3.8 KiB
COBOL
126 lines
3.8 KiB
COBOL
#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 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, *c0, *c1, *c2, *c3
|
|
target = current->address_space->find_capability (current->arch.v0)
|
|
if !target:
|
|
// TODO: there must be no action here. This is just because the rest doesn't work yet.
|
|
led (current->arch.a0, current->arch.a1, current->arch.a2)
|
|
dbg_sleep (1000)
|
|
schedule ()
|
|
return
|
|
c0 = current->address_space->find_capability (current->arch.a0)
|
|
c1 = current->address_space->find_capability (current->arch.a1)
|
|
c2 = current->address_space->find_capability (current->arch.a2)
|
|
c3 = current->address_space->find_capability (current->arch.a3)
|
|
target->invoke (current->arch.t0, current->arch.t1, current->arch.t2, current->arch.t3, c0, c1, c2, c3)
|
|
|
|
void arch_schedule (Thread *previous, Thread *target):
|
|
if (Memory *)asids[target->address_space->arch.asid] != target->address_space:
|
|
if asids[0]:
|
|
target->address_space->arch.asid = asids[0]
|
|
asids[0] = asids[asids[0]]
|
|
else:
|
|
static unsigned random = 1
|
|
target->address_space->arch.asid = random
|
|
// Overwrite used asid, so flush those values from tlb.
|
|
flush_tlb (random)
|
|
++random
|
|
if random >= 64:
|
|
random = 1
|
|
asids[target->address_space->arch.asid] = (unsigned)target
|
|
cp0_set (CP0_ENTRY_HI, target->address_space->arch.asid)
|