mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-30 18:51:05 +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
|
report
|
||||||
uimage
|
uimage
|
||||||
*.o
|
*.o
|
||||||
|
*.cc
|
||||||
|
*.hh
|
||||||
|
6
Makefile
6
Makefile
@ -1,6 +1,6 @@
|
|||||||
load = 0x80000000
|
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
|
CPPFLAGS = -O5 -Wa,-mips32
|
||||||
CROSS = mipsel-linux-gnu-
|
CROSS = mipsel-linux-gnu-
|
||||||
CC = $(CROSS)gcc
|
CC = $(CROSS)gcc
|
||||||
@ -8,7 +8,7 @@ LD = $(CROSS)ld
|
|||||||
OBJCOPY = $(CROSS)objcopy
|
OBJCOPY = $(CROSS)objcopy
|
||||||
OBJDUMP = $(CROSS)objdump
|
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
|
boot_sources = init.cc
|
||||||
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
|
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'
|
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
|
arch.hh: mips.hh
|
||||||
ln -s $< $@
|
ln -s $< $@ || true
|
||||||
|
|
||||||
%.o:%.cc Makefile kernel.hh arch.hh
|
%.o:%.cc Makefile kernel.hh arch.hh
|
||||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||||
|
73
alloc.ccp
73
alloc.ccp
@ -1,7 +1,20 @@
|
|||||||
|
#pypp 0
|
||||||
#include "kernel.hh"
|
#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 ():
|
void *Memory::palloc ():
|
||||||
if use >= limit:
|
if !use ():
|
||||||
return NULL
|
return NULL
|
||||||
FreePage *ret = junk_pages
|
FreePage *ret = junk_pages
|
||||||
if !ret:
|
if !ret:
|
||||||
@ -12,7 +25,7 @@ void *Memory::palloc ():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
void *Memory::zalloc ():
|
void *Memory::zalloc ():
|
||||||
if use >= limit:
|
if !use ():
|
||||||
return NULL
|
return NULL
|
||||||
FreePage *ret = zero_pages
|
FreePage *ret = zero_pages
|
||||||
if !ret:
|
if !ret:
|
||||||
@ -35,12 +48,12 @@ void Memory::zfree (void *page):
|
|||||||
p->next = zero_pages
|
p->next = zero_pages
|
||||||
zero_pages = p
|
zero_pages = p
|
||||||
|
|
||||||
void *Memory::search_free (unsigned size, void *&first):
|
void *Memory::search_free (unsigned size, void **first):
|
||||||
Free *f
|
Free *f
|
||||||
unsigned s = 0
|
unsigned s = 0
|
||||||
for f = frees; f; f = f->next:
|
for f = frees; f; f = f->next:
|
||||||
if f->next_obj:
|
if f->next_obj:
|
||||||
s = f->next_obj - f
|
s = (unsigned)f->next_obj - (unsigned)f
|
||||||
else:
|
else:
|
||||||
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK)
|
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK)
|
||||||
if s >= size:
|
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.
|
// Create the new object at the end and keep the Free.
|
||||||
Free *obj = (Free *)((unsigned)f + s - size)
|
Free *obj = (Free *)((unsigned)f + s - size)
|
||||||
obj->next_obj = f->next_obj
|
obj->next_obj = f->next_obj
|
||||||
if (obj->next_obj)
|
if obj->next_obj:
|
||||||
obj->next_obj->prev_obj = obj
|
obj->next_obj->prev_obj = obj
|
||||||
obj->prev_obj = f
|
obj->prev_obj = f
|
||||||
f->next_obj = obj
|
f->next_obj = obj
|
||||||
@ -75,11 +88,11 @@ void *Memory::search_free (unsigned size, void *&first):
|
|||||||
frees = f->next
|
frees = f->next
|
||||||
if f->next:
|
if f->next:
|
||||||
f->next->prev = f->prev
|
f->next->prev = f->prev
|
||||||
f->next = first
|
f->next = (Free *)*first
|
||||||
f->prev = NULL
|
f->prev = NULL
|
||||||
if f->next:
|
if f->next:
|
||||||
f->next->prev = f
|
f->next->prev = f
|
||||||
first = f
|
*first = f
|
||||||
return f
|
return f
|
||||||
|
|
||||||
void Object_base::free_obj (Memory *parent):
|
void Object_base::free_obj (Memory *parent):
|
||||||
@ -114,14 +127,14 @@ void Object_base::free_obj (Memory *parent):
|
|||||||
parent->pfree (self)
|
parent->pfree (self)
|
||||||
|
|
||||||
Page *Memory::alloc_page ():
|
Page *Memory::alloc_page ():
|
||||||
Page *ret = (Page *)search_free (sizeof (Page), pages)
|
Page *ret = (Page *)search_free (sizeof (Page), (void **)&pages)
|
||||||
ret->physical = zalloc ()
|
ret->physical = zalloc ()
|
||||||
if !ret->physical:
|
if !ret->physical:
|
||||||
ret->free (this, pages)
|
free_page (ret)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Thread *Memory::alloc_thread ():
|
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->address_space = this
|
||||||
ret->pc = 0
|
ret->pc = 0
|
||||||
ret->sp = 0
|
ret->sp = 0
|
||||||
@ -131,7 +144,8 @@ Thread *Memory::alloc_thread ():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
Memory *Memory::alloc_memory ():
|
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->frees = NULL
|
||||||
ret->pages = NULL
|
ret->pages = NULL
|
||||||
ret->threads = NULL
|
ret->threads = NULL
|
||||||
@ -140,3 +154,40 @@ Memory *Memory::alloc_memory ():
|
|||||||
ret->used = 0
|
ret->used = 0
|
||||||
Memory_arch_init (ret)
|
Memory_arch_init (ret)
|
||||||
return 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
|
.globl run_idle
|
||||||
.set noat
|
.set noat
|
||||||
|
|
||||||
|
#define Index 0
|
||||||
|
#define Random 1
|
||||||
#define EntryLo0 2
|
#define EntryLo0 2
|
||||||
#define EntryLo1 3
|
#define EntryLo1 3
|
||||||
#define EntryHi 10
|
#define EntryHi 10
|
||||||
#define Random 1
|
|
||||||
#define Index 0
|
|
||||||
#define Status 12
|
#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:
|
addr_000:
|
||||||
// TLB refill
|
// TLB refill
|
||||||
@ -45,7 +74,7 @@ addr_180:
|
|||||||
// General exception
|
// General exception
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
//li $a0, 0xaaff0000
|
li $a0, 0xaaff0000
|
||||||
la $t9, panic
|
la $t9, panic
|
||||||
jr $t9
|
jr $t9
|
||||||
nop
|
nop
|
||||||
@ -90,73 +119,78 @@ start_idle: // 288
|
|||||||
b 1b
|
b 1b
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
// TODO: save only fragile registers now, the rest on task switch.
|
||||||
kernel_exit:
|
kernel_exit:
|
||||||
move $k0, $v0
|
lw $k0, SAVE_PC($v0)
|
||||||
lw $v0, 96($k0)
|
mtc0 $k0, $EPC
|
||||||
lw $v1, 100($k0)
|
lw $k0, SAVE_LO($v0)
|
||||||
mthi $v0
|
lw $k1, SAVE_HI($v0)
|
||||||
mtlo $v1
|
mtlo $k0
|
||||||
lw $v0, 16($k0)
|
mthi $k1
|
||||||
lw $v1, 20($k0)
|
lw $v1, SAVE_V1($v0)
|
||||||
lw $a0, 24($k0)
|
lw $a0, SAVE_A0($v0)
|
||||||
lw $a1, 28($k0)
|
lw $a1, SAVE_A1($v0)
|
||||||
lw $a2, 32($k0)
|
lw $a2, SAVE_A2($v0)
|
||||||
lw $a3, 36($k0)
|
lw $a3, SAVE_A3($v0)
|
||||||
lw $t0, 40($k0)
|
lw $t0, SAVE_T0($v0)
|
||||||
lw $t1, 44($k0)
|
lw $t1, SAVE_T1($v0)
|
||||||
lw $t2, 48($k0)
|
lw $t2, SAVE_T2($v0)
|
||||||
lw $t3, 52($k0)
|
lw $t3, SAVE_T3($v0)
|
||||||
lw $t4, 56($k0)
|
lw $t4, SAVE_T4($v0)
|
||||||
lw $t5, 60($k0)
|
lw $t5, SAVE_T5($v0)
|
||||||
lw $t6, 64($k0)
|
lw $t6, SAVE_T6($v0)
|
||||||
lw $t7, 68($k0)
|
lw $t7, SAVE_T7($v0)
|
||||||
lw $t8, 72($k0)
|
lw $t8, SAVE_T8($v0)
|
||||||
lw $t9, 76($k0)
|
lw $t9, SAVE_T9($v0)
|
||||||
lw $gp, 80($k0)
|
lw $gp, SAVE_GP($v0)
|
||||||
lw $sp, 84($k0)
|
lw $sp, SAVE_SP($v0)
|
||||||
lw $fp, 88($k0)
|
lw $fp, SAVE_FP($v0)
|
||||||
lw $ra, 92($k0)
|
lw $ra, SAVE_RA($v0)
|
||||||
lw $at, 12($k0)
|
lw $at, SAVE_AT($v0)
|
||||||
lw $k1, 104($k0) // Real $k0
|
lw $k0, SAVE_K0($v0)
|
||||||
|
lw $k1, SAVE_V0($v0)
|
||||||
sw $k1, -0x190($zero)
|
sw $k1, -0x190($zero)
|
||||||
lw $k1, 108($k0)
|
lw $k1, SAVE_K1($v0)
|
||||||
sw $k0, -0x18c($zero)
|
sw $v0, -0x18c($zero)
|
||||||
lw $k0, -0x190($zero)
|
lw $v0, -0x190($zero)
|
||||||
eret
|
eret
|
||||||
|
|
||||||
save_regs:
|
save_regs:
|
||||||
sw $k0, -0x190($zero)
|
sw $k0, -0x190($zero)
|
||||||
lw $k0, -0x18c($zero)
|
lw $k0, -0x18c($zero)
|
||||||
sw $at, 12($k0)
|
sw $at, SAVE_AT($k0)
|
||||||
sw $gp, 80($k0)
|
sw $gp, SAVE_GP($k0)
|
||||||
sw $sp, 84($k0)
|
sw $sp, SAVE_SP($k0)
|
||||||
sw $fp, 88($k0)
|
sw $fp, SAVE_FP($k0)
|
||||||
|
|
||||||
sw $k1, 108($k0)
|
sw $k1, SAVE_K1($k0)
|
||||||
lw $k1, -0x190($zero)
|
lw $k1, -0x190($zero)
|
||||||
sw $k1, 104($k0) // Real $k0
|
sw $k1, SAVE_K0($k0)
|
||||||
|
|
||||||
lw $k1, -0x188($zero)
|
lw $k1, -0x188($zero)
|
||||||
sw $k1, 92($k0) // Real $ra
|
sw $k1, SAVE_RA($k0)
|
||||||
sw $v0, 16($k0)
|
sw $v0, SAVE_V0($k0)
|
||||||
sw $v1, 20($k0)
|
sw $v1, SAVE_V1($k0)
|
||||||
sw $a0, 24($k0)
|
sw $a0, SAVE_A0($k0)
|
||||||
sw $a1, 28($k0)
|
sw $a1, SAVE_A1($k0)
|
||||||
sw $a2, 32($k0)
|
sw $a2, SAVE_A2($k0)
|
||||||
sw $a3, 36($k0)
|
sw $a3, SAVE_A3($k0)
|
||||||
sw $t1, 44($k0)
|
sw $t0, SAVE_T0($k0)
|
||||||
sw $t2, 48($k0)
|
sw $t1, SAVE_T1($k0)
|
||||||
sw $t3, 52($k0)
|
sw $t2, SAVE_T2($k0)
|
||||||
sw $t4, 56($k0)
|
sw $t3, SAVE_T3($k0)
|
||||||
sw $t5, 60($k0)
|
sw $t4, SAVE_T4($k0)
|
||||||
sw $t6, 64($k0)
|
sw $t5, SAVE_T5($k0)
|
||||||
sw $t7, 68($k0)
|
sw $t6, SAVE_T6($k0)
|
||||||
sw $t8, 72($k0)
|
sw $t7, SAVE_T7($k0)
|
||||||
sw $t9, 76($k0)
|
sw $t8, SAVE_T8($k0)
|
||||||
|
sw $t9, SAVE_T9($k0)
|
||||||
mfhi $v0
|
mfhi $v0
|
||||||
mflo $v1
|
mflo $v1
|
||||||
sw $v0, 96($k0)
|
sw $v0, SAVE_HI($k0)
|
||||||
sw $v1, 100($k0)
|
sw $v1, SAVE_LO($k0)
|
||||||
|
mfc0 $k1, $EPC
|
||||||
|
sw $k1, SAVE_PC($k0)
|
||||||
|
|
||||||
lw $gp, -0x184($zero)
|
lw $gp, -0x184($zero)
|
||||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||||
|
100
init.ccp
100
init.ccp
@ -3,102 +3,99 @@
|
|||||||
#define INIT
|
#define INIT
|
||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
#define cp0_get(reg, sel, target) do { __asm__ volatile ("mfc0 %0, $" #reg ", " #sel : "=r (target)); } while (0)
|
#define reg_hack(x) #x
|
||||||
#define cp0_set(reg, value) do { __asm__ volatile ("mtc0 %0, $" #reg :: "r (value)); } while (0)
|
#define cp0_get(reg, sel, target) do { __asm__ volatile ("mfc0 %0, $" reg_hack(reg) ", " #sel : "=r" (target)); } while (0)
|
||||||
#define cp0_set0(reg) do { __asm__ volatile ("mtc0 $zero, $" #reg); } 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.
|
// cp0 registers.
|
||||||
#define INDEX 0
|
#define CP0_INDEX 0
|
||||||
#define ENTRY_LO0 2
|
#define CP0_ENTRY_LO0 2
|
||||||
#define ENTRY_LO1 3
|
#define CP0_ENTRY_LO1 3
|
||||||
#define PAGE_MASK 5
|
#define CP0_PAGE_MASK 5
|
||||||
#define WIRED 6
|
#define CP0_WIRED 6
|
||||||
#define COUNT 9
|
#define CP0_COUNT 9
|
||||||
#define ENTRY_HI 10
|
#define CP0_ENTRY_HI 10
|
||||||
#define COMPARE 11
|
#define CP0_COMPARE 11
|
||||||
#define STATUS 12
|
#define CP0_STATUS 12
|
||||||
#define CAUSE 13
|
#define CP0_CAUSE 13
|
||||||
#define EPC 14
|
#define CP0_EPC 14
|
||||||
#define CONFIG 16
|
#define CP0_CONFIG 16
|
||||||
|
|
||||||
static void init_idle ():
|
static void init_idle ():
|
||||||
// initialize idle task as if it is currently running.
|
// 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.prev = NULL
|
||||||
idle.next = NULL
|
idle.next = NULL
|
||||||
idle.thread_prev = NULL
|
|
||||||
idle.thread_next = NULL
|
|
||||||
idle.schedule_prev = NULL
|
idle.schedule_prev = NULL
|
||||||
idle.schedule_next = NULL
|
idle.schedule_next = NULL
|
||||||
idle.address_space = &idle_memory
|
idle.address_space = &idle_memory
|
||||||
// initialize 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.prev = NULL
|
||||||
idle_memory.next = NULL
|
idle_memory.next = NULL
|
||||||
idle_memory.memory_prev = NULL
|
|
||||||
idle_memory.memory_next = NULL
|
|
||||||
idle_memory.pages = &idle_page
|
idle_memory.pages = &idle_page
|
||||||
idle_memory.threads = &idle
|
idle_memory.threads = &idle
|
||||||
idle_memory.memories = NULL
|
idle_memory.memories = NULL
|
||||||
idle_memory.limit = 0
|
idle_memory.limit = 0
|
||||||
idle_memory.used = 0
|
idle_memory.used = 0
|
||||||
idle_memory.cpu.directory = (Page ***)0x80000000
|
idle_memory.arch.directory = (Page ***)0x80000000
|
||||||
idle_memory.cpu.asid = 0
|
idle_memory.arch.asid = 0
|
||||||
// initialize idle_page
|
// initialize idle_page
|
||||||
idle_page.size = sizeof (Page)
|
idle_page.prev_obj = NULL
|
||||||
|
idle_page.next_obj = NULL
|
||||||
idle_page.prev = NULL
|
idle_page.prev = NULL
|
||||||
idle_page.next = NULL
|
idle_page.next = NULL
|
||||||
idle_page.page_prev = NULL
|
idle_page.physical = (void *)0
|
||||||
idle_page.page_next = NULL
|
|
||||||
// Not an error, this is really physical page 0.
|
|
||||||
idle_page.physical = 0
|
|
||||||
|
|
||||||
static void init_cp0 ():
|
static void init_cp0 ():
|
||||||
// Set timer to a defined value
|
// Set timer to a defined value
|
||||||
cp0_set (COMPARE, 1000000)
|
cp0_set (CP0_COMPARE, 1000000)
|
||||||
// Reset timer
|
// Reset timer
|
||||||
cp0_set0 (COUNT)
|
cp0_set0 (CP0_COUNT)
|
||||||
// Use the interrupt vector for interrupts
|
// 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
|
// clear the tlb, hardwire page 0 to 0xffffffff
|
||||||
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
|
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
|
||||||
// (for the idle task).
|
// (for the idle task).
|
||||||
|
|
||||||
cp0_set (WIRED, 1)
|
cp0_set (CP0_WIRED, 1)
|
||||||
cp0_set0 (PAGE_MASK)
|
cp0_set0 (CP0_PAGE_MASK)
|
||||||
cp0_set0 (ENTRY_LO0)
|
cp0_set0 (CP0_ENTRY_LO0)
|
||||||
cp0_set0 (ENTRY_LO1)
|
cp0_set0 (CP0_ENTRY_LO1)
|
||||||
// Get number of tlb entries (is 31).
|
// Get number of tlb entries (is 31).
|
||||||
unsigned num;
|
unsigned num;
|
||||||
cp0_get (CONFIG, 1, num)
|
cp0_get (CP0_CONFIG, 1, num)
|
||||||
num >>= 25
|
num >>= 25
|
||||||
num &= 0x3f
|
num &= 0x3f
|
||||||
// Clear the tlb.
|
// Clear the tlb.
|
||||||
#if 0
|
#if 0
|
||||||
for unsigned i = 1; i < num; ++i:
|
for unsigned i = 1; i < num; ++i:
|
||||||
// this address doesn't reach the tlb, so it can't trigger exceptions.
|
// this address doesn't reach the tlb, so it can't trigger exceptions.
|
||||||
cp0_set (ENTRY_HI, 0x70000000 + 0x1000 * i)
|
cp0_set (CP0_ENTRY_HI, 0x70000000 + 0x1000 * i)
|
||||||
cp0_set (INDEX, i)
|
cp0_set (CP0_INDEX, i)
|
||||||
// write the data.
|
// write the data.
|
||||||
__asm__ volatile ("tlbwi")
|
__asm__ volatile ("tlbwi")
|
||||||
#endif
|
#endif
|
||||||
// Fill the upper page in kseg3.
|
// Fill the upper page in kseg3.
|
||||||
cp0_set (ENTRY_HI, 0xfffff000)
|
cp0_set (CP0_ENTRY_HI, 0xfffff000)
|
||||||
cp0_set (ENTRY_LO0, 0x1d)
|
cp0_set (CP0_ENTRY_LO0, 0x1d)
|
||||||
cp0_set (ENTRY_LO1, 0x1f)
|
cp0_set (CP0_ENTRY_LO1, 0x1f)
|
||||||
cp0_set0 (INDEX)
|
cp0_set0 (CP0_INDEX)
|
||||||
__asm__ volatile ("tlbwi")
|
__asm__ volatile ("tlbwi")
|
||||||
// Fill the idle task's page in useg. Set it to non-cachable.
|
// Fill the idle task's page in useg. Set it to non-cachable.
|
||||||
cp0_set (ENTRY_HI, 0x284a0000)
|
cp0_set (CP0_ENTRY_HI, 0x284a0000)
|
||||||
cp0_set (ENTRY_LO0, 0x16)
|
cp0_set (CP0_ENTRY_LO0, 0x16)
|
||||||
cp0_set (ENTRY_LO1, 0x14)
|
cp0_set (CP0_ENTRY_LO1, 0x14)
|
||||||
__asm__ volatile ("tlbwr")
|
__asm__ volatile ("tlbwr")
|
||||||
// Allow eret to be used to jump to the idle task.
|
// 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.
|
// Enable all interrupts and say we're handling an exception.
|
||||||
// Since we're going to enter the idle task, allow access to cp0.
|
// 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 ():
|
static void init_threads ():
|
||||||
for unsigned i = 0; i < NUM_THREADS; ++i:
|
for unsigned i = 0; i < NUM_THREADS; ++i:
|
||||||
@ -126,18 +123,17 @@ void init ():
|
|||||||
// initialize everything about the idle task.
|
// initialize everything about the idle task.
|
||||||
init_idle ()
|
init_idle ()
|
||||||
// initialize top_memory.
|
// initialize top_memory.
|
||||||
top_memory.size = sizeof (Memory)
|
top_memory.prev_obj = NULL
|
||||||
|
top_memory.next_obj = NULL
|
||||||
top_memory.prev = NULL
|
top_memory.prev = NULL
|
||||||
top_memory.next = NULL
|
top_memory.next = NULL
|
||||||
top_memory.memory_prev = NULL
|
|
||||||
top_memory.memory_next = NULL
|
|
||||||
top_memory.pages = NULL
|
top_memory.pages = NULL
|
||||||
top_memory.threads = NULL
|
top_memory.threads = NULL
|
||||||
top_memory.memories = NULL
|
top_memory.memories = NULL
|
||||||
top_memory.limit = count
|
top_memory.limit = count
|
||||||
top_memory.used = 0
|
top_memory.used = 0
|
||||||
top_memory.cpu.directory = NULL
|
top_memory.arch.directory = NULL
|
||||||
top_memory.cpu.asid = 0
|
top_memory.arch.asid = 0
|
||||||
|
|
||||||
init_threads ()
|
init_threads ()
|
||||||
|
|
||||||
|
@ -2,13 +2,12 @@
|
|||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
// hi and lo cannot be saved in assemply due to space restrictions.
|
// 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.
|
/// A TLB miss has occurred. This should eventually move to entry.S.
|
||||||
Thread *tlb_refill (Thread *current, unsigned EntryHi):
|
Thread *tlb_refill (Thread *current, unsigned EntryHi):
|
||||||
save_hilo (current)
|
save_hilo (current)
|
||||||
led (false, false)
|
Page ***dir = current->address_space->arch.directory
|
||||||
Page ***dir = current->address_space->cpu.directory
|
|
||||||
if !dir:
|
if !dir:
|
||||||
panic (0x00000000, "no page directory for thread")
|
panic (0x00000000, "no page directory for thread")
|
||||||
EntryHi >>= 12
|
EntryHi >>= 12
|
||||||
@ -22,11 +21,11 @@ Thread *tlb_refill (Thread *current, unsigned EntryHi):
|
|||||||
panic (0x22222222, "no page mapped at requested address")
|
panic (0x22222222, "no page mapped at requested address")
|
||||||
unsigned low0, low1
|
unsigned low0, low1
|
||||||
if page0:
|
if page0:
|
||||||
low0 = page0->physical | 0x18 | 0x4 | 0x2
|
low0 = (unsigned)page0->physical | 0x18 | 0x4 | 0x2
|
||||||
else
|
else
|
||||||
low0 = 0
|
low0 = 0
|
||||||
if page1:
|
if page1:
|
||||||
low1 = page1->physical | 0x18 | 0x4 | 0x2
|
low1 = (unsigned)page1->physical | 0x18 | 0x4 | 0x2
|
||||||
else
|
else
|
||||||
low1 = 0
|
low1 = 0
|
||||||
__asm__ volatile ("mtc0 %0, $2; mtc0 %1, $3; tlbwr" :: "r"(low0), "r"(low1))
|
__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.
|
/// An interrupt which is not an exception has occurred.
|
||||||
Thread *interrupt (Thread *current):
|
Thread *interrupt (Thread *current):
|
||||||
save_hilo (current)
|
save_hilo (current)
|
||||||
led (false, false)
|
|
||||||
return current
|
return current
|
||||||
|
|
||||||
/// A general exception has occurred.
|
/// A general exception has occurred.
|
||||||
|
35
kernel.hhp
35
kernel.hhp
@ -9,7 +9,6 @@
|
|||||||
#define NULL 0
|
#define NULL 0
|
||||||
|
|
||||||
struct Object_base
|
struct Object_base
|
||||||
struct Object
|
|
||||||
struct Page
|
struct Page
|
||||||
struct Thread
|
struct Thread
|
||||||
struct Memory
|
struct Memory
|
||||||
@ -18,16 +17,16 @@ struct Memory
|
|||||||
|
|
||||||
struct Object_base:
|
struct Object_base:
|
||||||
// Next and previous object of any type in the same page.
|
// 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)
|
void free_obj (Memory *parent)
|
||||||
inline bool is_free ()
|
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.
|
// Next and previous object of the same type in any page.
|
||||||
_T *prev, *next
|
_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
|
// This marker is ~0. No other kernel structure may allow this value
|
||||||
// at this point. It is used to recognize free chunks.
|
// at this point. It is used to recognize free chunks.
|
||||||
unsigned marker
|
unsigned marker
|
||||||
@ -45,6 +44,7 @@ struct Thread : public Object <Thread>:
|
|||||||
Thread *schedule_prev, *schedule_next
|
Thread *schedule_prev, *schedule_next
|
||||||
|
|
||||||
struct Memory : public Object <Memory>:
|
struct Memory : public Object <Memory>:
|
||||||
|
Memory *parent
|
||||||
Free *frees
|
Free *frees
|
||||||
Page *pages
|
Page *pages
|
||||||
Thread *threads
|
Thread *threads
|
||||||
@ -52,24 +52,36 @@ struct Memory : public Object <Memory>:
|
|||||||
unsigned limit, used
|
unsigned limit, used
|
||||||
Memory_arch arch
|
Memory_arch arch
|
||||||
|
|
||||||
|
void unmap (Page *page, void *address):
|
||||||
|
Memory_arch_unmap (this, page, address)
|
||||||
|
|
||||||
// Allocation of pages.
|
// Allocation of pages.
|
||||||
|
bool use ()
|
||||||
|
void unuse ()
|
||||||
void *palloc ()
|
void *palloc ()
|
||||||
void *zalloc ()
|
void *zalloc ()
|
||||||
void pfree (void *page)
|
void pfree (void *page)
|
||||||
void zfree (void *page)
|
void zfree (void *page)
|
||||||
|
|
||||||
// Allocation routines for kernel structures
|
// Allocation routines for kernel structures
|
||||||
void *search_free (unsigned size, void *&first)
|
void *search_free (unsigned size, void **first)
|
||||||
Page *alloc_page ()
|
Page *alloc_page ()
|
||||||
Thread *alloc_thread ()
|
Thread *alloc_thread ()
|
||||||
Memory *alloc_memory ()
|
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.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
// Panic. n is sent over caps led. message is currently ignored.
|
// Panic. n is sent over caps led. message is currently ignored.
|
||||||
void panic (unsigned n, char const *message)
|
void panic (unsigned n, char const *message)
|
||||||
// Debug: switch caps led
|
// Debug: switch caps led
|
||||||
void led (bool on, bool tick)
|
void led (bool one, bool two, bool three)
|
||||||
|
|
||||||
struct FreePage:
|
struct FreePage:
|
||||||
FreePage *next
|
FreePage *next
|
||||||
@ -81,13 +93,4 @@ EXTERN Thread idle
|
|||||||
EXTERN Memory idle_memory
|
EXTERN Memory idle_memory
|
||||||
EXTERN Page idle_page
|
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
|
#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
|
#ifndef _ARCH_HH
|
||||||
#define _ARCH_HH
|
#define _ARCH_HH
|
||||||
|
|
||||||
|
#define PAGE_BITS (12)
|
||||||
|
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||||
|
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||||
|
|
||||||
struct Thread_arch:
|
struct Thread_arch:
|
||||||
unsigned at, v0, v1, a0, a1, a2, a3
|
unsigned at, v0, v1, a0, a1, a2, a3
|
||||||
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
|
unsigned t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
|
||||||
unsigned gp, fp, ra, hi, lo, k0, k1
|
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:
|
struct Memory_arch:
|
||||||
unsigned asid
|
unsigned asid
|
||||||
Page ***directory
|
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
|
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.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
@ -32,4 +91,4 @@ extern "C":
|
|||||||
void run_idle (Thread *self)
|
void run_idle (Thread *self)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // ARCH_PART2
|
||||||
|
@ -5,6 +5,6 @@ void panic (unsigned n, char const *message):
|
|||||||
while (1):
|
while (1):
|
||||||
for unsigned bit = 0x80000000; bit; bit >>= 1:
|
for unsigned bit = 0x80000000; bit; bit >>= 1:
|
||||||
for int i = 0; i < 600000; ++i:
|
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:
|
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 NETWORK_IO 9
|
||||||
#define LIGHT 105
|
#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 (CAPSLOCKLED_IO)
|
||||||
__gpio_as_output (NUMLOCKLED_IO)
|
__gpio_as_output (NUMLOCKLED_IO)
|
||||||
__gpio_as_output (NETWORK_IO)
|
__gpio_as_output (NETWORK_IO)
|
||||||
if on:
|
if one:
|
||||||
|
__gpio_clear_pin (NUMLOCKLED_IO)
|
||||||
|
else:
|
||||||
__gpio_set_pin (NUMLOCKLED_IO)
|
__gpio_set_pin (NUMLOCKLED_IO)
|
||||||
|
if two:
|
||||||
__gpio_clear_pin (CAPSLOCKLED_IO)
|
__gpio_clear_pin (CAPSLOCKLED_IO)
|
||||||
else:
|
else:
|
||||||
__gpio_set_pin (CAPSLOCKLED_IO)
|
__gpio_set_pin (CAPSLOCKLED_IO)
|
||||||
__gpio_clear_pin (NUMLOCKLED_IO)
|
if three:
|
||||||
if tick:
|
|
||||||
__gpio_clear_pin (NETWORK_IO)
|
__gpio_clear_pin (NETWORK_IO)
|
||||||
else:
|
else:
|
||||||
__gpio_set_pin (NETWORK_IO)
|
__gpio_set_pin (NETWORK_IO)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user