mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-17 01:06:15 +02:00
idle
This commit is contained in:
parent
aee799648f
commit
5d9d12b860
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
all
|
all
|
||||||
|
all.raw
|
||||||
all.raw.gz
|
all.raw.gz
|
||||||
report
|
report
|
||||||
uimage
|
uimage
|
||||||
|
14
Makefile
14
Makefile
@ -1,4 +1,4 @@
|
|||||||
load = 0xa0000000
|
load = 0x80000000
|
||||||
|
|
||||||
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc
|
CXXFLAGS = -Wno-unused-parameter -fno-strict-aliasing -fno-builtin -nostdinc
|
||||||
CPPFLAGS = -O5 -Wa,-mips32
|
CPPFLAGS = -O5 -Wa,-mips32
|
||||||
@ -8,7 +8,9 @@ LD = $(CROSS)ld
|
|||||||
OBJCOPY = $(CROSS)objcopy
|
OBJCOPY = $(CROSS)objcopy
|
||||||
OBJDUMP = $(CROSS)objdump
|
OBJDUMP = $(CROSS)objdump
|
||||||
|
|
||||||
BUILT_SOURCES = interrupts.cc panic.cc data.cc test.cc
|
kernel_sources = interrupts.cc panic.cc data.cc test.cc
|
||||||
|
boot_sources = init.cc
|
||||||
|
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
|
||||||
|
|
||||||
PYPP = /usr/bin/pypp
|
PYPP = /usr/bin/pypp
|
||||||
%.cc: %.ccp kernel.hh
|
%.cc: %.ccp kernel.hh
|
||||||
@ -17,8 +19,8 @@ PYPP = /usr/bin/pypp
|
|||||||
$(PYPP) --name $< < $< > $@
|
$(PYPP) --name $< < $< > $@
|
||||||
|
|
||||||
# Transform ':' into ';' so vim doesn't think there are errors.
|
# Transform ':' into ';' so vim doesn't think there are errors.
|
||||||
uimage: all.raw.gz Makefile
|
uimage: all.raw Makefile
|
||||||
mkimage -A MIPS -O Linux -C gzip -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'
|
||||||
|
|
||||||
%.o:%.cc Makefile kernel.hh
|
%.o:%.cc Makefile kernel.hh
|
||||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||||
@ -26,8 +28,8 @@ uimage: all.raw.gz Makefile
|
|||||||
%.o:%.S Makefile
|
%.o:%.S Makefile
|
||||||
$(CC) $(CPPFLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
$(CC) $(CPPFLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
||||||
|
|
||||||
# entry.o must be the first file. For the rest, the order doesn't matter.
|
# entry.o must be the first file. boot.o must be the first of the init objects (which can be dumped after loading).
|
||||||
all: entry.o $(subst .cc,.o,$(BUILT_SOURCES))
|
all: entry.o $(subst .cc,.o,$(kernel_sources)) boot.o $(subst .cc,.o,$(boot_sources))
|
||||||
$(LD) --omagic -Ttext $(load) $^ -o $@
|
$(LD) --omagic -Ttext $(load) $^ -o $@
|
||||||
|
|
||||||
junk = mdebug.abi32 reginfo comment pdr
|
junk = mdebug.abi32 reginfo comment pdr
|
||||||
|
45
boot.S
Normal file
45
boot.S
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// The kernel stack.
|
||||||
|
.lcomm kernel_stack, KERNEL_STACK_SIZE
|
||||||
|
|
||||||
|
.globl __start
|
||||||
|
.set noreorder
|
||||||
|
|
||||||
|
#define Status 12
|
||||||
|
#define Config 16
|
||||||
|
|
||||||
|
__start:
|
||||||
|
bal 1f
|
||||||
|
nop
|
||||||
|
.word _gp
|
||||||
|
// For some reason the disassembler considers everything
|
||||||
|
// after __start non-code until the next label. So I add a label.
|
||||||
|
start_hack_for_disassembler:
|
||||||
|
1: lw $gp, 0($ra)
|
||||||
|
|
||||||
|
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||||
|
|
||||||
|
// Disable interrupts during bootstrap.
|
||||||
|
mtc0 $zero, $Status
|
||||||
|
|
||||||
|
// TODO: flush cache and optionally refill it.
|
||||||
|
|
||||||
|
// Set kseg0 cachable.
|
||||||
|
li $k0, 0x3
|
||||||
|
mtc0 $k0, $Config, 0
|
||||||
|
|
||||||
|
// Jump into cached code.
|
||||||
|
la $t9, 1f
|
||||||
|
jr $t9
|
||||||
|
nop
|
||||||
|
1:
|
||||||
|
|
||||||
|
// Clear .bss
|
||||||
|
la $a0, _edata
|
||||||
|
la $a1, _end
|
||||||
|
1: sw $zero, 0($a0)
|
||||||
|
bne $a1, $a0, 1b
|
||||||
|
addu $a0, 4
|
||||||
|
|
||||||
|
la $t9, init
|
||||||
|
jr $t9
|
||||||
|
nop
|
234
entry.S
234
entry.S
@ -1,73 +1,15 @@
|
|||||||
// The kernel stack.
|
// The kernel stack.
|
||||||
.lcomm kernel_stack, KERNEL_STACK_SIZE
|
.lcomm kernel_stack, KERNEL_STACK_SIZE
|
||||||
|
|
||||||
.globl __start
|
|
||||||
.globl run_idle
|
.globl run_idle
|
||||||
.set noat
|
.set noat
|
||||||
.set noreorder
|
|
||||||
|
|
||||||
#define EntryLo0 2
|
#define EntryLo0 2
|
||||||
#define EntryLo1 3
|
#define EntryLo1 3
|
||||||
#define EntryHi 10
|
#define EntryHi 10
|
||||||
#define Random 1
|
#define Random 1
|
||||||
#define Index 0
|
#define Index 0
|
||||||
#define PageMask 5
|
|
||||||
#define Wired 6
|
|
||||||
#define Config 16
|
|
||||||
#define Status 12
|
#define Status 12
|
||||||
#define Cause 13
|
|
||||||
#define Compare 11
|
|
||||||
|
|
||||||
#define save_regs \
|
|
||||||
sw $k0, -0x180($zero) ;\
|
|
||||||
lw $k0, -0x184($zero) ;\
|
|
||||||
sw $at, 12($k0) ;\
|
|
||||||
sw $k1, 108($k0) ;\
|
|
||||||
lw $k1, -0x180($zero) ;\
|
|
||||||
sw $k1, 104($k0) ;\
|
|
||||||
sw $v0, 16($k0) ;\
|
|
||||||
sw $v1, 20($k0) ;\
|
|
||||||
sw $t0, 40($k0) ;\
|
|
||||||
sw $sp, 84($k0) ;\
|
|
||||||
sw $fp, 88($k0) ;\
|
|
||||||
sw $ra, 92($k0) ;\
|
|
||||||
lw $gp, -12($zero) ;\
|
|
||||||
la $sp, kernel_stack + KERNEL_STACK_SIZE ;\
|
|
||||||
move $a0, $k0 ;\
|
|
||||||
la $ra, kernel_exit ;\
|
|
||||||
bal save_args
|
|
||||||
|
|
||||||
#define restore_regs \
|
|
||||||
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) ;\
|
|
||||||
sw $k1, -0x180($zero) ;\
|
|
||||||
lw $k1, 108($k0) ;\
|
|
||||||
sw $k0, -0x184($zero) ;\
|
|
||||||
lw $k0, -0x180($zero)
|
|
||||||
|
|
||||||
addr_000:
|
addr_000:
|
||||||
// TLB refill
|
// TLB refill
|
||||||
@ -76,9 +18,10 @@ addr_000:
|
|||||||
li $a0, 0xffff0000
|
li $a0, 0xffff0000
|
||||||
la $t9, panic
|
la $t9, panic
|
||||||
jr $t9
|
jr $t9
|
||||||
|
nop
|
||||||
|
|
||||||
save_regs
|
sw $ra, -0x188($zero)
|
||||||
mfc0 $a1, $EntryHi
|
bal save_regs
|
||||||
la $t9, tlb_refill
|
la $t9, tlb_refill
|
||||||
jr $t9
|
jr $t9
|
||||||
nop
|
nop
|
||||||
@ -90,8 +33,10 @@ addr_100:
|
|||||||
li $a0, 0xaaaa0000
|
li $a0, 0xaaaa0000
|
||||||
la $t9, panic
|
la $t9, panic
|
||||||
jr $t9
|
jr $t9
|
||||||
|
nop
|
||||||
|
|
||||||
save_regs
|
sw $ra, -0x188($zero)
|
||||||
|
bal save_regs
|
||||||
la $t9, cache_error
|
la $t9, cache_error
|
||||||
jr $t9
|
jr $t9
|
||||||
nop
|
nop
|
||||||
@ -100,11 +45,13 @@ 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
|
||||||
|
|
||||||
save_regs
|
sw $ra, -0x188($zero)
|
||||||
|
bal save_regs
|
||||||
la $t9, exception
|
la $t9, exception
|
||||||
jr $t9
|
jr $t9
|
||||||
nop
|
nop
|
||||||
@ -116,85 +63,83 @@ addr_200:
|
|||||||
li $a0, 0x0a0f0000
|
li $a0, 0x0a0f0000
|
||||||
la $t9, panic
|
la $t9, panic
|
||||||
jr $t9
|
jr $t9
|
||||||
|
nop
|
||||||
|
|
||||||
save_regs
|
sw $ra, -0x188($zero)
|
||||||
|
bal save_regs
|
||||||
la $t9, interrupt
|
la $t9, interrupt
|
||||||
jr $t9
|
jr $t9
|
||||||
nop
|
nop
|
||||||
.fill 0x280 - (. - addr_000)
|
.fill 0x280 - (. - addr_000) - 16
|
||||||
|
|
||||||
// space for save_regs.
|
// space for save_regs: k0; current Thread; ra; gp
|
||||||
|
.word 0
|
||||||
.word 0
|
.word 0
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
start_idle:
|
|
||||||
b .
|
|
||||||
nop
|
|
||||||
.word idle_page
|
|
||||||
.word 0x80000000 // A pointer to the current page.
|
|
||||||
|
|
||||||
__start:
|
|
||||||
bal 1f
|
|
||||||
nop
|
|
||||||
.word _gp
|
.word _gp
|
||||||
// For some reason the disassembler considers everything
|
|
||||||
// after __start non-code until the next label. So I add a label.
|
|
||||||
start_hack:
|
|
||||||
1: lw $gp, 0($ra)
|
|
||||||
|
|
||||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
.word idle_page // 280
|
||||||
|
.word 0x80000000 // 284 A pointer to the current page.
|
||||||
// Disable interrupts during bootstrap.
|
start_idle: // 288
|
||||||
mtc0 $zero, $Status
|
// Wait for the next interrupt, then the first thread will be scheduled.
|
||||||
|
// It is impractical to try to call schedule, because for that the
|
||||||
// TODO: flush cache
|
// idle task would need to own capabilities.
|
||||||
|
mfc0 $a0, $9
|
||||||
// Set kseg0 cachable.
|
syscall
|
||||||
li $k0, 0x3
|
1: wait
|
||||||
mtc0 $k0, $Config, 0
|
b 1b
|
||||||
|
|
||||||
// Clear .bss
|
|
||||||
la $a0, _edata
|
|
||||||
la $a1, _end
|
|
||||||
1: sw $zero, 0($a0)
|
|
||||||
bne $a1, $a0, 1b
|
|
||||||
addu $a0, 4
|
|
||||||
|
|
||||||
// Set timer to a defined value
|
|
||||||
mtc0 $zero, $Compare, 0
|
|
||||||
|
|
||||||
// Use the interrupt vector for interrupts
|
|
||||||
li $k0, 1 << 23
|
|
||||||
mtc0 $k0, $Cause
|
|
||||||
|
|
||||||
li $a0, 0xff0a0000
|
|
||||||
la $t9, panic
|
|
||||||
jr $t9
|
|
||||||
|
|
||||||
// clear the tlb, hardwire page 0 to 0xffffffff
|
|
||||||
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
|
|
||||||
// (for the idle task).
|
|
||||||
|
|
||||||
// this address doesn't reach the tlb, so it can't trigger exceptions.
|
|
||||||
mtc0 $zero, $PageMask
|
|
||||||
mtc0 $zero, $EntryLo0
|
|
||||||
mtc0 $zero, $EntryLo1
|
|
||||||
li $t0, 0x80000000
|
|
||||||
// There are 32 tlb entries.
|
|
||||||
addi $a0, $zero, 31
|
|
||||||
1: mtc0 $t0, $EntryHi
|
|
||||||
mtc0 $a0, $Index
|
|
||||||
tlbwi
|
|
||||||
addiu $t0, $t0, 1 << 13
|
|
||||||
bgtz $a0, 1b
|
|
||||||
addiu $a0, $a0, -1
|
|
||||||
|
|
||||||
la $t9, init
|
|
||||||
jalr $t9
|
|
||||||
nop
|
nop
|
||||||
sw $gp, -12($zero)
|
|
||||||
|
|
||||||
save_args:
|
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
|
||||||
|
sw $k1, -0x190($zero)
|
||||||
|
lw $k1, 108($k0)
|
||||||
|
sw $k0, -0x18c($zero)
|
||||||
|
lw $k0, -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 $k1, 108($k0)
|
||||||
|
lw $k1, -0x190($zero)
|
||||||
|
sw $k1, 104($k0) // Real $k0
|
||||||
|
|
||||||
|
lw $k1, -0x188($zero)
|
||||||
|
sw $k1, 92($k0) // Real $ra
|
||||||
|
sw $v0, 16($k0)
|
||||||
|
sw $v1, 20($k0)
|
||||||
sw $a0, 24($k0)
|
sw $a0, 24($k0)
|
||||||
sw $a1, 28($k0)
|
sw $a1, 28($k0)
|
||||||
sw $a2, 32($k0)
|
sw $a2, 32($k0)
|
||||||
@ -208,23 +153,14 @@ save_args:
|
|||||||
sw $t7, 68($k0)
|
sw $t7, 68($k0)
|
||||||
sw $t8, 72($k0)
|
sw $t8, 72($k0)
|
||||||
sw $t9, 76($k0)
|
sw $t9, 76($k0)
|
||||||
sw $gp, 80($k0)
|
mfhi $v0
|
||||||
j $ra
|
mflo $v1
|
||||||
|
sw $v0, 96($k0)
|
||||||
|
sw $v1, 100($k0)
|
||||||
|
|
||||||
run_idle:
|
lw $gp, -0x184($zero)
|
||||||
move $k0, $a0
|
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||||
move $k1, $gp
|
move $t9, $ra
|
||||||
// Prepare enabling interrupts and switching to user mode.
|
la $ra, kernel_exit
|
||||||
// The command is executed in the delay slot of the jump.
|
|
||||||
li $t0, 0xff11
|
|
||||||
// Now it's acceptable to receive an exception. Jump to kuseg,
|
|
||||||
// thereby generating a tlb_refill exception (which is handled).
|
|
||||||
// The address is the virtual address where the idle task is.
|
|
||||||
la $t9, ((0x294 << 20) + (0x290 << 10) + 0x288)
|
|
||||||
jr $t9
|
jr $t9
|
||||||
mtc0 $t0, $Status
|
move $a0, $k0
|
||||||
|
|
||||||
kernel_exit:
|
|
||||||
move $k0, $v0
|
|
||||||
restore_regs
|
|
||||||
eret
|
|
||||||
|
125
init.ccp
Normal file
125
init.ccp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#pypp 0
|
||||||
|
#include "kernel.hh"
|
||||||
|
|
||||||
|
static void init_idle ():
|
||||||
|
// initialize idle task as if it is currently running.
|
||||||
|
idle.size = sizeof (Thread)
|
||||||
|
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 = 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
|
||||||
|
// initialize idle_page
|
||||||
|
idle_page.size = sizeof (Page)
|
||||||
|
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
|
||||||
|
|
||||||
|
static void init_cp0 ():
|
||||||
|
// Set timer to a defined value (11 is Compare)
|
||||||
|
__asm__ volatile ("mtc0 %0, $11, 0" :: "r"(1000000))
|
||||||
|
// Reset timer (9 is Count)
|
||||||
|
__asm__ volatile ("mtc0 $zero, $9, 0")
|
||||||
|
// Use the interrupt vector for interrupts (13 is Cause)
|
||||||
|
__asm__ volatile ("mtc0 %0, $13" :: "r"(1 << 23))
|
||||||
|
|
||||||
|
// clear the tlb, hardwire page 0 to 0xffffffff
|
||||||
|
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
|
||||||
|
// (for the idle task).
|
||||||
|
|
||||||
|
// 6 is Wired.
|
||||||
|
__asm__ volatile ("mtc0 %0, $6" :: "r"(1))
|
||||||
|
// 5 is PageMask.
|
||||||
|
__asm__ volatile ("mtc0 $zero, $5")
|
||||||
|
// 2 is EntryLo0.
|
||||||
|
__asm__ volatile ("mtc0 $zero, $2")
|
||||||
|
// 3 is EntryLo1.
|
||||||
|
__asm__ volatile ("mtc0 $zero, $3")
|
||||||
|
// Get number of tlb entries (is 31).
|
||||||
|
unsigned num;
|
||||||
|
__asm__ volatile ("mfc0 %0, $16, 1" : "=r"(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.
|
||||||
|
// 10 is EntryHi
|
||||||
|
__asm__ volatile ("mtc0 %0, $10" :: "r"(0x70000000 + 0x1000 * i))
|
||||||
|
// 0 is Index.
|
||||||
|
__asm__ volatile ("mtc0 %0, $0" :: "r"(i))
|
||||||
|
// write the data.
|
||||||
|
__asm__ volatile ("tlbwi")
|
||||||
|
#endif
|
||||||
|
// Fill the upper page in kseg3.
|
||||||
|
__asm__ volatile ("mtc0 %0, $10" :: "r"(0xfffff000))
|
||||||
|
__asm__ volatile ("mtc0 %0, $2" :: "r"(0x0000001d))
|
||||||
|
__asm__ volatile ("mtc0 %0, $3" :: "r"(0x0000001f))
|
||||||
|
__asm__ volatile ("mtc0 %0, $0" :: "r"(0))
|
||||||
|
__asm__ volatile ("tlbwi")
|
||||||
|
// Fill the idle task's page in useg. Set it to non-cachable.
|
||||||
|
__asm__ volatile ("mtc0 %0, $10" :: "r"(0x284a0000))
|
||||||
|
__asm__ volatile ("mtc0 %0, $2" :: "r"(0x00000016))
|
||||||
|
__asm__ volatile ("mtc0 %0, $3" :: "r"(0x00000014))
|
||||||
|
__asm__ volatile ("tlbwr")
|
||||||
|
// Allow eret to be used to jump to the idle task.
|
||||||
|
// 14 is EPC.
|
||||||
|
__asm__ volatile ("mtc0 %0, $14" :: "r"(0x284a0288))
|
||||||
|
// Enable all interrupts and say we're handling an exception.
|
||||||
|
// 12 is Status.
|
||||||
|
__asm__ volatile ("mtc0 %0, $12" :: "r"(0x1000ff13))
|
||||||
|
|
||||||
|
/// Initialize the kernel, finish by falling into the idle task.
|
||||||
|
extern unsigned _end
|
||||||
|
void init ():
|
||||||
|
// Initialize kernel variables to empty.
|
||||||
|
sleepers = NULL
|
||||||
|
runners = NULL
|
||||||
|
zero_pages = NULL
|
||||||
|
// Fill junk pages with all memory not currently used.
|
||||||
|
junk_pages = (FreePage *)(((unsigned)&_end + (1 << 12) - 1) & ~((1 << 12) - 1))
|
||||||
|
FreePage *p, *next
|
||||||
|
unsigned count = 1
|
||||||
|
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < (1 << 27); p = next, next = (FreePage *)((unsigned)p + (1 << 12)):
|
||||||
|
p->next = next
|
||||||
|
++count
|
||||||
|
p->next = NULL
|
||||||
|
// initialize system control coprocessor.
|
||||||
|
init_cp0 ()
|
||||||
|
// initialize everything about the idle task.
|
||||||
|
init_idle ()
|
||||||
|
// initialize top_memory.
|
||||||
|
top_memory.size = sizeof (Memory)
|
||||||
|
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
|
||||||
|
// TOOO: set up initial threads.
|
||||||
|
|
||||||
|
// Done; return to user space (the idle task).
|
||||||
|
__asm__ volatile ("eret")
|
@ -2,7 +2,7 @@
|
|||||||
#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__ ("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)->cpu.hi), "=r"((x)->cpu.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):
|
||||||
@ -29,7 +29,7 @@ Thread *tlb_refill (Thread *current, unsigned EntryHi):
|
|||||||
low1 = page1->physical | 0x18 | 0x4 | 0x2
|
low1 = page1->physical | 0x18 | 0x4 | 0x2
|
||||||
else
|
else
|
||||||
low1 = 0
|
low1 = 0
|
||||||
__asm__ ("mtc0 %0, $2; mtc0 %1, $3; tlbwr" :: "r"(low0), "r"(low1))
|
__asm__ volatile ("mtc0 %0, $2; mtc0 %1, $3; tlbwr" :: "r"(low0), "r"(low1))
|
||||||
return current
|
return current
|
||||||
|
|
||||||
/// An interrupt which is not an exception has occurred.
|
/// An interrupt which is not an exception has occurred.
|
||||||
@ -49,67 +49,3 @@ Thread *cache_error (Thread *current):
|
|||||||
save_hilo (current)
|
save_hilo (current)
|
||||||
panic (0x33333333, "cache error")
|
panic (0x33333333, "cache error")
|
||||||
return current
|
return current
|
||||||
|
|
||||||
static void init_idle ():
|
|
||||||
// initialize idle task as if it is currently running.
|
|
||||||
idle.size = sizeof (Thread)
|
|
||||||
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 = 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
|
|
||||||
// initialize idle_page
|
|
||||||
idle_page.size = sizeof (Page)
|
|
||||||
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
|
|
||||||
|
|
||||||
/// Initialize the kernel, finish by falling into the idle task.
|
|
||||||
extern unsigned _end
|
|
||||||
void init ():
|
|
||||||
// Initialize kernel variables to empty.
|
|
||||||
sleepers = NULL
|
|
||||||
runners = NULL
|
|
||||||
zero_pages = NULL
|
|
||||||
// Fill junk pages with all memory not currently used.
|
|
||||||
junk_pages = (FreePage *)(((unsigned)&_end + (1 << 12) - 1) & ~((1 << 12) - 1))
|
|
||||||
FreePage *p, *next
|
|
||||||
unsigned count = 1
|
|
||||||
for p = junk_pages; (unsigned)next - 0x80000000 < (1 << 27); p = next, next = (FreePage *)((unsigned)p + 1 << 12):
|
|
||||||
p->next = next
|
|
||||||
++count
|
|
||||||
p->next = NULL
|
|
||||||
// initialize everything about the idle task.
|
|
||||||
init_idle ()
|
|
||||||
// initialize top_memory.
|
|
||||||
top_memory.size = sizeof (Memory)
|
|
||||||
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
|
|
||||||
// TOOO: set up initial threads.
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
void panic (unsigned n, char const *message):
|
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 < 60000; ++i:
|
for int i = 0; i < 600000; ++i:
|
||||||
led (n & bit, i > 20000 && i < 40000)
|
led (n & bit, i > 200000 && i < 400000)
|
||||||
for int i = 0; i < 100000; ++i:
|
for int i = 0; i < 1000000; ++i:
|
||||||
led (false, false)
|
led (false, false)
|
||||||
|
24
start.S
24
start.S
@ -1,24 +0,0 @@
|
|||||||
.set noreorder
|
|
||||||
.globl __start
|
|
||||||
.globl kernel_stack
|
|
||||||
__start:
|
|
||||||
bal 1f
|
|
||||||
nop
|
|
||||||
.word _gp
|
|
||||||
1: lw $gp, 0($ra)
|
|
||||||
nop
|
|
||||||
|
|
||||||
la $a0, _edata
|
|
||||||
la $a1, _end
|
|
||||||
1: sw $zero, 0($a0)
|
|
||||||
bne $a1, $a0, 1b
|
|
||||||
addu $a0, 4
|
|
||||||
|
|
||||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
|
||||||
|
|
||||||
bal kernel_entry
|
|
||||||
nop
|
|
||||||
b .
|
|
||||||
nop
|
|
||||||
|
|
||||||
.lcomm kernel_stack, KERNEL_STACK_SIZE
|
|
Loading…
Reference in New Issue
Block a user