#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")