mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-04 22:54:03 +02:00
more
This commit is contained in:
parent
64b7976770
commit
616e81d7a8
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,3 +4,5 @@ all.raw.gz
|
||||
report
|
||||
uimage
|
||||
*.o
|
||||
*.cc
|
||||
*.hh
|
||||
|
6
Makefile
6
Makefile
@ -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 $@
|
||||
|
73
alloc.ccp
73
alloc.ccp
@ -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
148
entry.S
@ -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
100
init.ccp
@ -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 ()
|
||||
|
||||
|
@ -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.
|
||||
|
35
kernel.hhp
35
kernel.hhp
@ -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
2
memory.ccp
Normal file
@ -0,0 +1,2 @@
|
||||
#pypp 0
|
||||
#include "kernel.hh"
|
67
mips.hhp
67
mips.hhp
@ -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
|
||||
|
@ -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)
|
||||
|
10
test.ccp
10
test.ccp
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user