#pypp 0 // Iris: micro-kernel for a capability-based operating system. // boot-programs/init.S: Startup code for initial Threads. // Copyright 2009 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "iris.hh" #include "devices.hh" // For some unknown reason, gcc needs this to be defined. unsigned __gxx_personality_v0 struct list: list *prev, *next static unsigned __slots, __caps static list *__slot_admin, *__cap_admin static list *__first_free_slot, *__first_free_cap namespace Kernel: Receiver my_receiver Thread my_thread Memory my_memory Cap my_call Parent my_parent __recv_data_t recv void print_caps (): // Assume __caps to be 32. bool used[32] for unsigned i = 0; i < 32; ++i: used[i] = true unsigned num = 0 for list *i = __first_free_cap; i; i = i->next: used[i - __cap_admin] = false ++num kdebug_num (num, 1) kdebug (":") for unsigned i = 0; i < 32; ++i: kdebug_char (used[i] ? '#' : '.') kdebug_char ('\n') void free_slot (unsigned slot): //kdebug ("free slot\n") __slot_admin[slot].prev = NULL __slot_admin[slot].next = __first_free_slot if __slot_admin[slot].next: __slot_admin[slot].next->prev = &__slot_admin[slot] __first_free_slot = &__slot_admin[slot] void free_cap (Cap cap): //kdebug ("free cap\n") if cap.slot () != 0: kdebug ("trying to free capability from non-0 slot\n") return list *l = &__cap_admin[cap.idx ()] l->prev = NULL l->next = __first_free_cap if l->next: l->next->prev = l __first_free_cap = l unsigned alloc_slot (): //kdebug ("alloc slot\n") if !__first_free_slot: // Out of slots... Probably best to raise an exception. For now, just return NO_SLOT. kdebug ("out of slots!\n") return ~0 list *ret = __first_free_slot __first_free_slot = ret->next if ret->next: ret->next->prev = NULL return ret - __slot_admin Cap alloc_cap (): //kdebug ("alloc cap\n") if !__first_free_cap: // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE kdebug ("out of capabilities!\n") return Cap (0, CAP_NONE) list *ret = __first_free_cap __first_free_cap = ret->next if ret->next: ret->next->prev = NULL return Cap (0, ret - __cap_admin) extern "C": void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin): __slots = slots __caps = caps __slot_admin = slot_admin __cap_admin = cap_admin __first_free_slot = NULL for unsigned i = 2; i < __slots; ++i: Kernel::free_slot (i) __first_free_cap = NULL for unsigned i = 7; i < __caps; ++i: Kernel::free_cap (Kernel::Cap (0, i)) Kernel::my_receiver = Kernel::Cap (0, __receiver_num) Kernel::my_thread = Kernel::Cap (0, __thread_num) Kernel::my_memory = Kernel::Cap (0, __memory_num) Kernel::my_call = Kernel::Cap (0, __call_num) Kernel::my_parent = Kernel::Cap (0, __parent_num) Kernel::recv.reply = Kernel::alloc_cap () Kernel::recv.arg = Kernel::alloc_cap () Kernel::Num ret = start () Kernel::my_parent.invoke (~0, ret) Kernel::my_memory.destroy (Kernel::my_thread) // The program no longer exists. If it somehow does, generate an address fault. while true: *(volatile unsigned *)~0 __asm__ volatile ("\t.text\n" "\t.globl __start\n" "\t.set noreorder\n" "__start:\n" "\tbal 1f\n" "__hack_label:\n" "\tnop\n" "\t.word _gp\n" "1:\n" "\tlw $gp, 0($ra)\n" "\tsll $v0, $a0, 3\n" "\tsll $v1, $a1, 3\n" "\tsubu $sp, $sp, $v0\n" "\tmove $a2, $sp\n" "\tsubu $sp, $sp, $v1\n" "\tmove $a3, $sp\n" "\tla $t9, run__main\n" "\tjr $t9\n" "\tnop\n" "\t.set reorder")