mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-10-04 05:27:36 +03:00
142 lines
4.1 KiB
COBOL
142 lines
4.1 KiB
COBOL
#pypp 0
|
|
// Also declare things which only work during kernel init.
|
|
#define INIT
|
|
#include "kernel.hh"
|
|
|
|
#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 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.prev_obj = NULL
|
|
idle.next_obj = NULL
|
|
idle.prev = NULL
|
|
idle.next = NULL
|
|
idle.schedule_prev = NULL
|
|
idle.schedule_next = NULL
|
|
idle.address_space = &idle_memory
|
|
// initialize idle_memory.
|
|
idle_memory.prev_obj = NULL
|
|
idle_memory.next_obj = NULL
|
|
idle_memory.prev = NULL
|
|
idle_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.arch.directory = (Page ***)0x80000000
|
|
idle_memory.arch.asid = 0
|
|
// initialize idle_page
|
|
idle_page.prev_obj = NULL
|
|
idle_page.next_obj = NULL
|
|
idle_page.prev = NULL
|
|
idle_page.next = NULL
|
|
idle_page.physical = (void *)0
|
|
|
|
static void init_cp0 ():
|
|
// Set timer to a defined value
|
|
cp0_set (CP0_COMPARE, 1000000)
|
|
// Reset timer
|
|
cp0_set0 (CP0_COUNT)
|
|
// Use the interrupt vector for interrupts
|
|
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 (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 (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 (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 (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 (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 (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 (CP0_STATUS, 0x1000ff13)
|
|
|
|
static void init_threads ():
|
|
for unsigned i = 0; i < NUM_THREADS; ++i:
|
|
Memory *mem = top_memory.alloc_memory ()
|
|
Thread *thread = mem->alloc_thread ()
|
|
// TODO
|
|
|
|
/// 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.prev_obj = NULL
|
|
top_memory.next_obj = NULL
|
|
top_memory.prev = NULL
|
|
top_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.arch.directory = NULL
|
|
top_memory.arch.asid = 0
|
|
|
|
init_threads ()
|
|
|
|
// Done; return to user space (the idle task).
|
|
__asm__ volatile ("eret")
|