1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2025-01-31 01:21:05 +02: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 report
uimage uimage
*.o *.o
*.cc
*.hh

View File

@ -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 $@

View File

@ -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
View File

@ -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
View File

@ -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 ()

View File

@ -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.

View File

@ -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
View File

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

View File

@ -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

View File

@ -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)

View File

@ -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)