2010-01-14 19:14:37 +02:00
|
|
|
#pypp 0
|
|
|
|
// Iris: micro-kernel for a capability-based operating system.
|
|
|
|
// boot-programs/init.S: Startup code for initial Threads.
|
|
|
|
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
|
|
|
//
|
|
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#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 ():
|
2010-01-16 17:13:54 +02:00
|
|
|
// Assume __caps to be 32.
|
|
|
|
bool used[32]
|
|
|
|
for unsigned i = 0; i < 32; ++i:
|
2010-01-14 19:14:37 +02:00
|
|
|
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 (":")
|
2010-01-16 17:13:54 +02:00
|
|
|
for unsigned i = 0; i < 32; ++i:
|
2010-01-14 19:14:37 +02:00
|
|
|
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.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")
|