1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 02:45:27 +03:00
This commit is contained in:
Bas Wijnen 2009-05-18 23:18:23 +02:00
parent 64b7976770
commit 616e81d7a8
11 changed files with 302 additions and 155 deletions

2
.gitignore vendored
View File

@ -4,3 +4,5 @@ all.raw.gz
report
uimage
*.o
*.cc
*.hh

View File

@ -1,6 +1,6 @@
load = 0x80000000
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc -DNUM_THREADS=0
CPPFLAGS = -O5 -Wa,-mips32
CROSS = mipsel-linux-gnu-
CC = $(CROSS)gcc
@ -8,7 +8,7 @@ LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
kernel_sources = interrupts.cc panic.cc data.cc test.cc alloc.cc
kernel_sources = interrupts.cc panic.cc data.cc test.cc alloc.cc memory.cc
boot_sources = init.cc
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
@ -23,7 +23,7 @@ uimage: all.raw Makefile
mkimage -A MIPS -O Linux -C none -a $(load) -e 0x$(shell /bin/sh -c '$(OBJDUMP) -t all | grep __start$$ | cut -b-8') -n "Shevek's kernel" -d $< $@ | sed -e 's/:/;/g'
arch.hh: mips.hh
ln -s $< $@
ln -s $< $@ || true
%.o:%.cc Makefile kernel.hh arch.hh
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

View File

@ -1,7 +1,20 @@
#pypp 0
#include "kernel.hh"
bool Memory::use ():
if used >= limit:
return false
if !parent || parent->use ():
++used
return true
return false
void Memory::unuse ():
--used;
return parent->unuse ()
void *Memory::palloc ():
if use >= limit:
if !use ():
return NULL
FreePage *ret = junk_pages
if !ret:
@ -12,7 +25,7 @@ void *Memory::palloc ():
return ret
void *Memory::zalloc ():
if use >= limit:
if !use ():
return NULL
FreePage *ret = zero_pages
if !ret:
@ -35,12 +48,12 @@ void Memory::zfree (void *page):
p->next = zero_pages
zero_pages = p
void *Memory::search_free (unsigned size, void *&first):
void *Memory::search_free (unsigned size, void **first):
Free *f
unsigned s = 0
for f = frees; f; f = f->next:
if f->next_obj:
s = f->next_obj - f
s = (unsigned)f->next_obj - (unsigned)f
else:
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK)
if s >= size:
@ -63,7 +76,7 @@ void *Memory::search_free (unsigned size, void *&first):
// Create the new object at the end and keep the Free.
Free *obj = (Free *)((unsigned)f + s - size)
obj->next_obj = f->next_obj
if (obj->next_obj)
if obj->next_obj:
obj->next_obj->prev_obj = obj
obj->prev_obj = f
f->next_obj = obj
@ -75,11 +88,11 @@ void *Memory::search_free (unsigned size, void *&first):
frees = f->next
if f->next:
f->next->prev = f->prev
f->next = first
f->next = (Free *)*first
f->prev = NULL
if f->next:
f->next->prev = f
first = f
*first = f
return f
void Object_base::free_obj (Memory *parent):
@ -114,14 +127,14 @@ void Object_base::free_obj (Memory *parent):
parent->pfree (self)
Page *Memory::alloc_page ():
Page *ret = (Page *)search_free (sizeof (Page), pages)
Page *ret = (Page *)search_free (sizeof (Page), (void **)&pages)
ret->physical = zalloc ()
if !ret->physical:
ret->free (this, pages)
free_page (ret)
return ret
Thread *Memory::alloc_thread ():
Thread *ret = (Thread *)search_free (sizeof (Thread), threads)
Thread *ret = (Thread *)search_free (sizeof (Thread), (void **)&threads)
ret->address_space = this
ret->pc = 0
ret->sp = 0
@ -131,7 +144,8 @@ Thread *Memory::alloc_thread ():
return ret
Memory *Memory::alloc_memory ():
Memory *ret = (Memory *)search_free (sizeof (Memory), memories)
Memory *ret = (Memory *)search_free (sizeof (Memory), (void **)&memories)
ret->parent = this
ret->frees = NULL
ret->pages = NULL
ret->threads = NULL
@ -140,3 +154,40 @@ Memory *Memory::alloc_memory ():
ret->used = 0
Memory_arch_init (ret)
return ret
void Memory::free_page (Page *page):
if page->prev:
page->prev->next = page->next
else:
pages = page->next
if page->next:
page->next->prev = page->prev
unuse ()
pfree (page->physical)
free_obj (this)
void Memory::free_thread (Thread *thread):
if thread->prev:
thread->prev->next = thread->next
else:
threads = thread->next
if thread->next:
thread->next->prev = thread->prev
// TODO: unschedule
free_obj (this)
void Memory::free_memory (Memory *mem):
if mem->prev:
mem->prev->next = mem->next
else:
memories = mem->next
if mem->next:
mem->next->prev = mem->prev
while mem->pages:
free_page (mem->pages)
while mem->threads:
free_thread (mem->threads)
while mem->memories:
free_memory (mem->memories)
Memory_arch_free (mem)
free_obj (this)

148
entry.S
View File

@ -4,12 +4,41 @@
.globl run_idle
.set noat
#define Index 0
#define Random 1
#define EntryLo0 2
#define EntryLo1 3
#define EntryHi 10
#define Random 1
#define Index 0
#define Status 12
#define EPC 14
// register save positions in Thread
#define SAVE_PC (5 * 4)
#define SAVE_SP (SAVE_PC + 4)
#define SAVE_AT (SAVE_SP + 4)
#define SAVE_V0 (SAVE_AT + 4)
#define SAVE_V1 (SAVE_V0 + 4)
#define SAVE_A0 (SAVE_V1 + 4)
#define SAVE_A1 (SAVE_A0 + 4)
#define SAVE_A2 (SAVE_A1 + 4)
#define SAVE_A3 (SAVE_A2 + 4)
#define SAVE_T0 (SAVE_A3 + 4)
#define SAVE_T1 (SAVE_T0 + 4)
#define SAVE_T2 (SAVE_T1 + 4)
#define SAVE_T3 (SAVE_T2 + 4)
#define SAVE_T4 (SAVE_T3 + 4)
#define SAVE_T5 (SAVE_T4 + 4)
#define SAVE_T6 (SAVE_T5 + 4)
#define SAVE_T7 (SAVE_T6 + 4)
#define SAVE_T8 (SAVE_T7 + 4)
#define SAVE_T9 (SAVE_T8 + 4)
#define SAVE_GP (SAVE_T9 + 4)
#define SAVE_FP (SAVE_GP + 4)
#define SAVE_RA (SAVE_FP + 4)
#define SAVE_HI (SAVE_RA + 4)
#define SAVE_LO (SAVE_HI + 4)
#define SAVE_K0 (SAVE_LO + 4)
#define SAVE_K1 (SAVE_K0 + 4)
addr_000:
// TLB refill
@ -45,7 +74,7 @@ addr_180:
// General exception
// TODO
//li $a0, 0xaaff0000
li $a0, 0xaaff0000
la $t9, panic
jr $t9
nop
@ -90,73 +119,78 @@ start_idle: // 288
b 1b
nop
// TODO: save only fragile registers now, the rest on task switch.
kernel_exit:
move $k0, $v0
lw $v0, 96($k0)
lw $v1, 100($k0)
mthi $v0
mtlo $v1
lw $v0, 16($k0)
lw $v1, 20($k0)
lw $a0, 24($k0)
lw $a1, 28($k0)
lw $a2, 32($k0)
lw $a3, 36($k0)
lw $t0, 40($k0)
lw $t1, 44($k0)
lw $t2, 48($k0)
lw $t3, 52($k0)
lw $t4, 56($k0)
lw $t5, 60($k0)
lw $t6, 64($k0)
lw $t7, 68($k0)
lw $t8, 72($k0)
lw $t9, 76($k0)
lw $gp, 80($k0)
lw $sp, 84($k0)
lw $fp, 88($k0)
lw $ra, 92($k0)
lw $at, 12($k0)
lw $k1, 104($k0) // Real $k0
lw $k0, SAVE_PC($v0)
mtc0 $k0, $EPC
lw $k0, SAVE_LO($v0)
lw $k1, SAVE_HI($v0)
mtlo $k0
mthi $k1
lw $v1, SAVE_V1($v0)
lw $a0, SAVE_A0($v0)
lw $a1, SAVE_A1($v0)
lw $a2, SAVE_A2($v0)
lw $a3, SAVE_A3($v0)
lw $t0, SAVE_T0($v0)
lw $t1, SAVE_T1($v0)
lw $t2, SAVE_T2($v0)
lw $t3, SAVE_T3($v0)
lw $t4, SAVE_T4($v0)
lw $t5, SAVE_T5($v0)
lw $t6, SAVE_T6($v0)
lw $t7, SAVE_T7($v0)
lw $t8, SAVE_T8($v0)
lw $t9, SAVE_T9($v0)
lw $gp, SAVE_GP($v0)
lw $sp, SAVE_SP($v0)
lw $fp, SAVE_FP($v0)
lw $ra, SAVE_RA($v0)
lw $at, SAVE_AT($v0)
lw $k0, SAVE_K0($v0)
lw $k1, SAVE_V0($v0)
sw $k1, -0x190($zero)
lw $k1, 108($k0)
sw $k0, -0x18c($zero)
lw $k0, -0x190($zero)
lw $k1, SAVE_K1($v0)
sw $v0, -0x18c($zero)
lw $v0, -0x190($zero)
eret
save_regs:
sw $k0, -0x190($zero)
lw $k0, -0x18c($zero)
sw $at, 12($k0)
sw $gp, 80($k0)
sw $sp, 84($k0)
sw $fp, 88($k0)
sw $at, SAVE_AT($k0)
sw $gp, SAVE_GP($k0)
sw $sp, SAVE_SP($k0)
sw $fp, SAVE_FP($k0)
sw $k1, 108($k0)
sw $k1, SAVE_K1($k0)
lw $k1, -0x190($zero)
sw $k1, 104($k0) // Real $k0
sw $k1, SAVE_K0($k0)
lw $k1, -0x188($zero)
sw $k1, 92($k0) // Real $ra
sw $v0, 16($k0)
sw $v1, 20($k0)
sw $a0, 24($k0)
sw $a1, 28($k0)
sw $a2, 32($k0)
sw $a3, 36($k0)
sw $t1, 44($k0)
sw $t2, 48($k0)
sw $t3, 52($k0)
sw $t4, 56($k0)
sw $t5, 60($k0)
sw $t6, 64($k0)
sw $t7, 68($k0)
sw $t8, 72($k0)
sw $t9, 76($k0)
sw $k1, SAVE_RA($k0)
sw $v0, SAVE_V0($k0)
sw $v1, SAVE_V1($k0)
sw $a0, SAVE_A0($k0)
sw $a1, SAVE_A1($k0)
sw $a2, SAVE_A2($k0)
sw $a3, SAVE_A3($k0)
sw $t0, SAVE_T0($k0)
sw $t1, SAVE_T1($k0)
sw $t2, SAVE_T2($k0)
sw $t3, SAVE_T3($k0)
sw $t4, SAVE_T4($k0)
sw $t5, SAVE_T5($k0)
sw $t6, SAVE_T6($k0)
sw $t7, SAVE_T7($k0)
sw $t8, SAVE_T8($k0)
sw $t9, SAVE_T9($k0)
mfhi $v0
mflo $v1
sw $v0, 96($k0)
sw $v1, 100($k0)
sw $v0, SAVE_HI($k0)
sw $v1, SAVE_LO($k0)
mfc0 $k1, $EPC
sw $k1, SAVE_PC($k0)
lw $gp, -0x184($zero)
la $sp, kernel_stack + KERNEL_STACK_SIZE

100
init.ccp
View File

@ -3,102 +3,99 @@
#define INIT
#include "kernel.hh"
#define cp0_get(reg, sel, target) do { __asm__ volatile ("mfc0 %0, $" #reg ", " #sel : "=r (target)); } while (0)
#define cp0_set(reg, value) do { __asm__ volatile ("mtc0 %0, $" #reg :: "r (value)); } while (0)
#define cp0_set0(reg) do { __asm__ volatile ("mtc0 $zero, $" #reg); } while (0)
#define reg_hack(x) #x
#define cp0_get(reg, sel, target) do { __asm__ volatile ("mfc0 %0, $" reg_hack(reg) ", " #sel : "=r" (target)); } while (0)
#define cp0_set(reg, value) do { __asm__ volatile ("mtc0 %0, $" reg_hack(reg) :: "r" (value)); } while (0)
#define cp0_set0(reg) do { __asm__ volatile ("mtc0 $zero, $" reg_hack(reg)); } while (0)
// cp0 registers.
#define INDEX 0
#define ENTRY_LO0 2
#define ENTRY_LO1 3
#define PAGE_MASK 5
#define WIRED 6
#define COUNT 9
#define ENTRY_HI 10
#define COMPARE 11
#define STATUS 12
#define CAUSE 13
#define EPC 14
#define CONFIG 16
#define CP0_INDEX 0
#define CP0_ENTRY_LO0 2
#define CP0_ENTRY_LO1 3
#define CP0_PAGE_MASK 5
#define CP0_WIRED 6
#define CP0_COUNT 9
#define CP0_ENTRY_HI 10
#define CP0_COMPARE 11
#define CP0_STATUS 12
#define CP0_CAUSE 13
#define CP0_EPC 14
#define CP0_CONFIG 16
static void init_idle ():
// initialize idle task as if it is currently running.
idle.size = sizeof (Thread)
idle.prev_obj = NULL
idle.next_obj = NULL
idle.prev = NULL
idle.next = NULL
idle.thread_prev = NULL
idle.thread_next = NULL
idle.schedule_prev = NULL
idle.schedule_next = NULL
idle.address_space = &idle_memory
// initialize idle_memory.
idle_memory.size = sizeof (Memory)
idle_memory.prev_obj = NULL
idle_memory.next_obj = NULL
idle_memory.prev = NULL
idle_memory.next = NULL
idle_memory.memory_prev = NULL
idle_memory.memory_next = NULL
idle_memory.pages = &idle_page
idle_memory.threads = &idle
idle_memory.memories = NULL
idle_memory.limit = 0
idle_memory.used = 0
idle_memory.cpu.directory = (Page ***)0x80000000
idle_memory.cpu.asid = 0
idle_memory.arch.directory = (Page ***)0x80000000
idle_memory.arch.asid = 0
// initialize idle_page
idle_page.size = sizeof (Page)
idle_page.prev_obj = NULL
idle_page.next_obj = NULL
idle_page.prev = NULL
idle_page.next = NULL
idle_page.page_prev = NULL
idle_page.page_next = NULL
// Not an error, this is really physical page 0.
idle_page.physical = 0
idle_page.physical = (void *)0
static void init_cp0 ():
// Set timer to a defined value
cp0_set (COMPARE, 1000000)
cp0_set (CP0_COMPARE, 1000000)
// Reset timer
cp0_set0 (COUNT)
cp0_set0 (CP0_COUNT)
// Use the interrupt vector for interrupts
cp0_set (CAUSE, 1 << 23)
cp0_set (CP0_CAUSE, 1 << 23)
// clear the tlb, hardwire page 0 to 0xffffffff
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
// (for the idle task).
cp0_set (WIRED, 1)
cp0_set0 (PAGE_MASK)
cp0_set0 (ENTRY_LO0)
cp0_set0 (ENTRY_LO1)
cp0_set (CP0_WIRED, 1)
cp0_set0 (CP0_PAGE_MASK)
cp0_set0 (CP0_ENTRY_LO0)
cp0_set0 (CP0_ENTRY_LO1)
// Get number of tlb entries (is 31).
unsigned num;
cp0_get (CONFIG, 1, num)
cp0_get (CP0_CONFIG, 1, num)
num >>= 25
num &= 0x3f
// Clear the tlb.
#if 0
for unsigned i = 1; i < num; ++i:
// this address doesn't reach the tlb, so it can't trigger exceptions.
cp0_set (ENTRY_HI, 0x70000000 + 0x1000 * i)
cp0_set (INDEX, i)
cp0_set (CP0_ENTRY_HI, 0x70000000 + 0x1000 * i)
cp0_set (CP0_INDEX, i)
// write the data.
__asm__ volatile ("tlbwi")
#endif
// Fill the upper page in kseg3.
cp0_set (ENTRY_HI, 0xfffff000)
cp0_set (ENTRY_LO0, 0x1d)
cp0_set (ENTRY_LO1, 0x1f)
cp0_set0 (INDEX)
cp0_set (CP0_ENTRY_HI, 0xfffff000)
cp0_set (CP0_ENTRY_LO0, 0x1d)
cp0_set (CP0_ENTRY_LO1, 0x1f)
cp0_set0 (CP0_INDEX)
__asm__ volatile ("tlbwi")
// Fill the idle task's page in useg. Set it to non-cachable.
cp0_set (ENTRY_HI, 0x284a0000)
cp0_set (ENTRY_LO0, 0x16)
cp0_set (ENTRY_LO1, 0x14)
cp0_set (CP0_ENTRY_HI, 0x284a0000)
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 (EPC, 0x284a0288)
cp0_set (CP0_EPC, 0x284a0288)
// Enable all interrupts and say we're handling an exception.
// Since we're going to enter the idle task, allow access to cp0.
cp0_set (STATUS, 0x1000ff13)
cp0_set (CP0_STATUS, 0x1000ff13)
static void init_threads ():
for unsigned i = 0; i < NUM_THREADS; ++i:
@ -126,18 +123,17 @@ void init ():
// initialize everything about the idle task.
init_idle ()
// initialize top_memory.
top_memory.size = sizeof (Memory)
top_memory.prev_obj = NULL
top_memory.next_obj = NULL
top_memory.prev = NULL
top_memory.next = NULL
top_memory.memory_prev = NULL
top_memory.memory_next = NULL
top_memory.pages = NULL
top_memory.threads = NULL
top_memory.memories = NULL
top_memory.limit = count
top_memory.used = 0
top_memory.cpu.directory = NULL
top_memory.cpu.asid = 0
top_memory.arch.directory = NULL
top_memory.arch.asid = 0
init_threads ()

View File

@ -2,13 +2,12 @@
#include "kernel.hh"
// hi and lo cannot be saved in assemply due to space restrictions.
#define save_hilo(x) do { __asm__ volatile ("mfhi %0 ; mflo %1" : "=r"((x)->cpu.hi), "=r"((x)->cpu.lo)); } while (0)
#define save_hilo(x) do { __asm__ volatile ("mfhi %0 ; mflo %1" : "=r"((x)->arch.hi), "=r"((x)->arch.lo)); } while (0)
/// A TLB miss has occurred. This should eventually move to entry.S.
Thread *tlb_refill (Thread *current, unsigned EntryHi):
save_hilo (current)
led (false, false)
Page ***dir = current->address_space->cpu.directory
Page ***dir = current->address_space->arch.directory
if !dir:
panic (0x00000000, "no page directory for thread")
EntryHi >>= 12
@ -22,11 +21,11 @@ Thread *tlb_refill (Thread *current, unsigned EntryHi):
panic (0x22222222, "no page mapped at requested address")
unsigned low0, low1
if page0:
low0 = page0->physical | 0x18 | 0x4 | 0x2
low0 = (unsigned)page0->physical | 0x18 | 0x4 | 0x2
else
low0 = 0
if page1:
low1 = page1->physical | 0x18 | 0x4 | 0x2
low1 = (unsigned)page1->physical | 0x18 | 0x4 | 0x2
else
low1 = 0
__asm__ volatile ("mtc0 %0, $2; mtc0 %1, $3; tlbwr" :: "r"(low0), "r"(low1))
@ -35,7 +34,6 @@ Thread *tlb_refill (Thread *current, unsigned EntryHi):
/// An interrupt which is not an exception has occurred.
Thread *interrupt (Thread *current):
save_hilo (current)
led (false, false)
return current
/// A general exception has occurred.

View File

@ -9,7 +9,6 @@
#define NULL 0
struct Object_base
struct Object
struct Page
struct Thread
struct Memory
@ -18,16 +17,16 @@ struct Memory
struct Object_base:
// Next and previous object of any type in the same page.
Object *prev_obj, *next_obj
Object_base *prev_obj, *next_obj
void free_obj (Memory *parent)
inline bool is_free ()
template <typename _T> struct Object : public Object_base:
template <typename _T> //
struct Object : public Object_base:
// Next and previous object of the same type in any page.
_T *prev, *next
void free (Memory *parent, _T *&first)
struct Free : public Object <Free>
struct Free : public Object <Free>:
// This marker is ~0. No other kernel structure may allow this value
// at this point. It is used to recognize free chunks.
unsigned marker
@ -45,6 +44,7 @@ struct Thread : public Object <Thread>:
Thread *schedule_prev, *schedule_next
struct Memory : public Object <Memory>:
Memory *parent
Free *frees
Page *pages
Thread *threads
@ -52,24 +52,36 @@ struct Memory : public Object <Memory>:
unsigned limit, used
Memory_arch arch
void unmap (Page *page, void *address):
Memory_arch_unmap (this, page, address)
// Allocation of pages.
bool use ()
void unuse ()
void *palloc ()
void *zalloc ()
void pfree (void *page)
void zfree (void *page)
// Allocation routines for kernel structures
void *search_free (unsigned size, void *&first)
void *search_free (unsigned size, void **first)
Page *alloc_page ()
Thread *alloc_thread ()
Memory *alloc_memory ()
void free_page (Page *page)
void free_thread (Thread *thread)
void free_memory (Memory *mem)
#define ARCH_PART2
#include "arch.hh"
// Functions which can be called from assembly must not be mangled.
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 led (bool on, bool tick)
void led (bool one, bool two, bool three)
struct FreePage:
FreePage *next
@ -81,13 +93,4 @@ EXTERN Thread idle
EXTERN Memory idle_memory
EXTERN Page idle_page
template <typename _T> void Object <_T>::free (Memory *parent, _T *&first):
if prev:
prev->next = next
else:
first = next
if next:
next->prev = prev
free_obj (parent)
#endif

2
memory.ccp Normal file
View File

@ -0,0 +1,2 @@
#pypp 0
#include "kernel.hh"

View File

@ -2,20 +2,79 @@
#ifndef _ARCH_HH
#define _ARCH_HH
#define PAGE_BITS (12)
#define PAGE_SIZE (1 << PAGE_BITS)
#define PAGE_MASK (~(PAGE_SIZE - 1))
struct Thread_arch:
unsigned at, v0, v1, a0, a1, a2, a3
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
unsigned gp, fp, ra, hi, lo, k0, k1
#define Thread_arch_init(thread) do { thread->at = 0; thread->v0 = 0; thread->v1 = 0; thread->a0 = 0; thread->a1 = 0; thread->a2 = 0; thread->a3 = 0; thread->t0 = 0; thread->t1 = 0; thread->t2 = 0; thread->t3 = 0; thread->t4 = 0; thread->t5 = 0; thread->t6 = 0; thread->t7 = 0; thread->t8 = 0; thread->t9 = 0; thread->gp = 0; thread->fp = 0; thread->ra = 0; thread->hi = 0; thread->lo = 0; thread->k0 = 0; thread->k1 = 0; } while (0)
struct Memory_arch:
unsigned asid
Page ***directory
static void Memory_arch_unmap (Memory *mem, Page *page, void *address)
#endif // _ARCH_HH
#ifdef ARCH_PART2
static 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
EXTERN unsigned g_asid
#define Memory_arch_init(mem) do { mem->asid = g_asid++; g_asid &= 0x3f; mem->directory = NULL; } while (0)
static void Memory_arch_init (Memory *mem):
++g_asid
g_asid &= 0x3f
if !g_asid:
++g_asid
mem->arch.asid = g_asid
mem->arch.directory = NULL
static void Memory_arch_free (Memory *mem):
if !mem->arch.directory:
return
for unsigned i = 0; i < PAGE_SIZE; ++i:
Page **table = mem->arch.directory[i]
if !table:
continue
for unsigned j = 0; j < PAGE_SIZE; ++j:
Page *page = table[j]
if !page:
continue
mem->unmap (page, (void *)(i * 0x1000 * 0x400 + j * 0x1000))
mem->unuse ()
mem->zfree (table)
mem->arch.directory[i] = NULL
mem->unuse ()
mem->zfree (mem->arch.directory)
static void Memory_arch_unmap (Memory *mem, Page *page, void *address):
// Functions which can be called from assembly must not be mangled.
extern "C":
@ -32,4 +91,4 @@ extern "C":
void run_idle (Thread *self)
#endif
#endif
#endif // ARCH_PART2

View File

@ -5,6 +5,6 @@ void panic (unsigned n, char const *message):
while (1):
for unsigned bit = 0x80000000; bit; bit >>= 1:
for int i = 0; i < 600000; ++i:
led (n & bit, i > 200000 && i < 400000)
led (n & bit, i > 200000 && i < 400000, false)
for int i = 0; i < 1000000; ++i:
led (false, false)
led (false, false, true)

View File

@ -58,17 +58,19 @@ static void __gpio_clear_pin (unsigned n):
#define NETWORK_IO 9
#define LIGHT 105
void led (bool on, bool tick):
void led (bool one, bool two, bool three):
__gpio_as_output (CAPSLOCKLED_IO)
__gpio_as_output (NUMLOCKLED_IO)
__gpio_as_output (NETWORK_IO)
if on:
if one:
__gpio_clear_pin (NUMLOCKLED_IO)
else:
__gpio_set_pin (NUMLOCKLED_IO)
if two:
__gpio_clear_pin (CAPSLOCKLED_IO)
else:
__gpio_set_pin (CAPSLOCKLED_IO)
__gpio_clear_pin (NUMLOCKLED_IO)
if tick:
if three:
__gpio_clear_pin (NETWORK_IO)
else:
__gpio_set_pin (NETWORK_IO)