#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" struct list: list *prev, *next static unsigned __slots, __caps static list *__slot_admin, *__cap_admin static list *__first_free_slot, *__first_free_cap namespace Iris: bool enable_debug Caps my_caps Receiver my_receiver Thread my_thread Memory my_memory Cap my_call Parent my_parent __recv_data_t recv void print_caps (): // __caps cannot be larger than 63. bool used[63] for unsigned i = 0; i < __caps; ++i: used[i] = true unsigned num = 0 for list *i = __first_free_cap; i; i = i->next: if used[i - __cap_admin] == false: panic (0, "inconsistent userspace cap db") used[i - __cap_admin] = false ++num kdebug_num (num, 2) kdebug (":") for unsigned i = 0; i < __caps; ++i: kdebug_char (used[i] ? '#' : '.') kdebug_char ('\n') void free_slot (unsigned slot): //kdebug ("free slot\n") for list *i = __first_free_slot; i; i = i->next: if slot == i - __slot_admin: panic (0, "double free of userspace slot") __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): if enable_debug: kdebug ("free cap ") kdebug_num (cap.idx (), 2) kdebug ("\n") for list *i = __first_free_cap; i; i = i->next: if cap.idx () == i - __cap_admin: panic (0, "double free of userspace cap") if cap.slot () != 0: kdebug ("trying to free capability from non-0 slot\n") Iris::panic (0) 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") Iris::panic (0) 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 (): if !__first_free_cap: // Out of caps... Probably best to raise an exception. For now, just return CAP_NONE kdebug ("out of capabilities!\n") Iris::panic (0) return Cap (0, CAP_NONE) list *ret = __first_free_cap __first_free_cap = ret->next if ret->next: ret->next->prev = NULL if enable_debug: kdebug ("alloc cap ") kdebug_num (ret - __cap_admin, 2) kdebug ("\n") return Cap (0, ret - __cap_admin) extern "C": void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin): Iris::enable_debug = false __slots = slots __caps = caps __slot_admin = slot_admin __cap_admin = cap_admin __first_free_slot = NULL for unsigned i = 1; i < __slots; ++i: Iris::free_slot (i) __first_free_cap = NULL for unsigned i = 6; i < __caps; ++i: Iris::free_cap (Iris::Cap (0, i)) Iris::my_caps = Iris::Cap (0, __caps_num) Iris::my_receiver = Iris::Cap (0, __receiver_num) Iris::my_thread = Iris::Cap (0, __thread_num) Iris::my_memory = Iris::Cap (0, __memory_num) Iris::my_call = Iris::Cap (0, __call_num) Iris::my_parent = Iris::Cap (0, __parent_num) Iris::recv.reply = Iris::alloc_cap () Iris::recv.arg = Iris::alloc_cap () Iris::Num ret = start () Iris::my_parent.exit (ret) Iris::my_memory.destroy (Iris::my_thread) // The program no longer exists. If it somehow does, die again. while true: Iris::panic (0, "this program should no longer exist.") *(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")