mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 19:44:16 +02:00
360 lines
11 KiB
Plaintext
360 lines
11 KiB
Plaintext
#pypp 0
|
|
// Iris: micro-kernel for a capability-based operating system.
|
|
// kernel.hhp: Header for all kernel sources.
|
|
// 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/>.
|
|
|
|
#ifndef _KERNEL_HH
|
|
#define _KERNEL_HH
|
|
|
|
// Include definitions which are shared with user space.
|
|
#define __KERNEL__
|
|
|
|
// Normally define all variables in this file as extern.
|
|
// Exactly once (in data.ccp), EXTERN is predefined empty.
|
|
// That results in space being allocated in its object file.
|
|
#ifndef EXTERN
|
|
#define EXTERN extern
|
|
#endif
|
|
|
|
struct kPage
|
|
struct kThread
|
|
struct kMessage
|
|
struct kReceiver
|
|
struct kCapability
|
|
struct kCaps
|
|
struct kMemory
|
|
struct kList
|
|
struct kListitem
|
|
|
|
// Some functions which must be defined early.
|
|
#ifndef NDEBUG
|
|
void kdebug (unsigned ch)
|
|
void kdebug (char const *str)
|
|
void kdebug_num (unsigned num, unsigned digits = 8)
|
|
#else
|
|
#define kdebug(x) do {} while (0)
|
|
#define kdebug_num(n) do {} while (0)
|
|
#endif
|
|
|
|
#include "iris.hh"
|
|
|
|
typedef kPage *kPageP
|
|
typedef kThread *kThreadP
|
|
typedef kMessage *kMessageP
|
|
typedef kReceiver *kReceiverP
|
|
typedef kCapability *kCapabilityP
|
|
typedef kCaps *kCapsP
|
|
typedef kMemory *kMemoryP
|
|
typedef kList *kListP
|
|
typedef kListitem *kListitemP
|
|
typedef void *kPointer
|
|
|
|
struct kCapRef:
|
|
kCapsP caps
|
|
unsigned index
|
|
inline kCapability *deref ()
|
|
bool valid ():
|
|
return deref () != NULL
|
|
kCapability *operator-> ():
|
|
return deref ()
|
|
void reset ():
|
|
caps = NULL
|
|
kCapRef (kCapsP c, unsigned i) : caps (c), index (i):
|
|
kCapRef () : caps (NULL), index (~0):
|
|
inline void clone (kCapRef source, bool copy)
|
|
inline void set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
|
|
|
|
struct kObject:
|
|
kCapRef refs
|
|
kMemoryP address_space
|
|
// Next and previous object of the same type in any page.
|
|
kPointer prev, next
|
|
inline bool is_free ()
|
|
|
|
struct kFree : public kObject:
|
|
// This marker is ~0. No other kernel structure may allow this value
|
|
// at this point. It is used to recognize free chunks.
|
|
unsigned marker
|
|
|
|
bool kObject::is_free ():
|
|
return ((kFree *)this)->marker == ~0
|
|
|
|
// Include architecture-specific parts.
|
|
#include "arch.hh"
|
|
|
|
struct kCapability : public kObject:
|
|
struct Context:
|
|
Iris::Num data[2]
|
|
kCapRef reply
|
|
kCapRef arg
|
|
bool copy[2]
|
|
kReceiverP target
|
|
kCapRef parent
|
|
kCapRef children
|
|
kCapRef sibling_prev, sibling_next
|
|
Iris::Num protected_data
|
|
inline void invoke (kCapability::Context *c)
|
|
void invalidate ()
|
|
|
|
struct _slot_data:
|
|
kThreadP thread
|
|
unsigned index
|
|
|
|
// The order of the members is defined in arch.hh. It must be first an object which cannot be ~0, then
|
|
// pc, sp and arch. After that everything is allowed.
|
|
struct kThread : public kObject:
|
|
kReceiverP receivers
|
|
unsigned pc, sp
|
|
kThread_arch arch
|
|
unsigned flags
|
|
kThreadP schedule_prev, schedule_next
|
|
unsigned recv_reply, recv_arg
|
|
// slot[] is an array of slots pointers to kCapses.
|
|
unsigned slots
|
|
#ifndef NDEBUG
|
|
unsigned id
|
|
#endif
|
|
struct caps_store:
|
|
_slot_data prev, next
|
|
kCapsP caps
|
|
caps_store slot[1]
|
|
void unset_slot (unsigned s)
|
|
void raise (unsigned code, unsigned data)
|
|
void run ()
|
|
void unrun ()
|
|
void wait ()
|
|
void unwait ()
|
|
bool is_waiting ():
|
|
return flags & Iris::Thread::WAITING
|
|
kCapRef find_capability (unsigned code, bool *copy)
|
|
|
|
struct kReceiver : public kObject:
|
|
kThreadP owner
|
|
kReceiverP prev_owned, next_owned
|
|
kReceiverP prev_alarm, next_alarm
|
|
unsigned alarm_count
|
|
// random is used like the tlb random register to find invalid caps to store the message to.
|
|
unsigned random
|
|
kCapsP caps
|
|
// These are capabilities which call this receiver on invoke.
|
|
kCapRef capabilities
|
|
// The message queue. kMessages are added at the tail, and removed at the front.
|
|
kMessageP messages
|
|
kMessageP last_message
|
|
Iris::Num reply_protected_data
|
|
bool protected_only
|
|
// This limit is for messages stored in its address space. There is unlimited space if senders provide it.
|
|
unsigned queue_limit, queue_use
|
|
void own (kThreadP o)
|
|
void orphan ()
|
|
bool try_deliver ()
|
|
bool send_message (Iris::Num protected_data, kCapability::Context *c)
|
|
void check (unsigned line)
|
|
|
|
struct kPage : public kObject:
|
|
unsigned frame
|
|
unsigned flags
|
|
unsigned mapping
|
|
kPageP share_prev, share_next
|
|
kPage_arch arch
|
|
void forget ()
|
|
void check_payment ()
|
|
|
|
struct kCaps : public kObject:
|
|
_slot_data first_slot
|
|
unsigned size
|
|
kCapability caps[1]
|
|
inline kCapability *cap (unsigned idx)
|
|
void set (unsigned index, kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
|
|
void clone (unsigned index, kCapRef source, bool copy)
|
|
void init (unsigned size)
|
|
|
|
// The 8 comes from the size of the admin data in a free page. When changing that, this must be changed as well.
|
|
#define MAX_NUM_CAPS ((PAGE_SIZE - 8 - sizeof (kCaps)) / sizeof (kCapability) + 1)
|
|
|
|
struct kMessage : public kObject:
|
|
Iris::Num protected_data
|
|
Iris::Num data[2]
|
|
// This is a real Caps of two elements, not a link.
|
|
kCaps caps
|
|
|
|
struct kList : public kObject:
|
|
kListitemP first_listitem
|
|
// This is a real Caps of one element, not a link.
|
|
kCaps owner
|
|
|
|
struct kListitem : public kObject:
|
|
kListP list
|
|
kListitemP prev_item, next_item
|
|
Iris::Num info
|
|
// This is a real Caps of one element, not a link.
|
|
kCaps target
|
|
void add (kList *l)
|
|
|
|
struct kMemory : public kObject:
|
|
kFree *frees
|
|
kPageP pages
|
|
kThreadP threads
|
|
kReceiverP receivers
|
|
kCapsP capses
|
|
kListP lists
|
|
kListitemP listitems
|
|
kMemoryP memories
|
|
unsigned limit, used
|
|
kMemory_arch arch
|
|
|
|
inline bool map (kPage *page, unsigned address)
|
|
inline void unmap (kPage *page)
|
|
inline kPage *get_mapping (unsigned address)
|
|
|
|
// Allocation of pages.
|
|
bool use (unsigned num = 1)
|
|
void unuse (unsigned num = 1)
|
|
unsigned palloc ()
|
|
unsigned zalloc ()
|
|
void pfree (unsigned page)
|
|
void zfree (unsigned page)
|
|
|
|
// Allocation routines for kernel structures
|
|
void *search_free (unsigned size, void **first)
|
|
kPage *alloc_page ()
|
|
kThread *alloc_thread (unsigned size)
|
|
kMessage *alloc_message (kReceiver *target)
|
|
kReceiver *alloc_receiver ()
|
|
kCaps *alloc_caps (unsigned size)
|
|
kList *alloc_list ()
|
|
kListitem *alloc_listitem ()
|
|
kMemory *alloc_memory ()
|
|
|
|
void free_page (kPage *page)
|
|
void free_thread (kThread *thread)
|
|
void free_message (kReceiver *owner, kMessage *message)
|
|
void free_receiver (kReceiver *receiver)
|
|
void free_caps (kCaps *page)
|
|
void free_list (kList *list)
|
|
void free_listitem (kListitem *listitem)
|
|
void free_memory (kMemory *mem)
|
|
|
|
void free_obj (kObject *obj, void **first)
|
|
void check (unsigned line)
|
|
void print (unsigned line, unsigned indent)
|
|
|
|
// Functions which can be called from assembly must not be mangled.
|
|
extern "C":
|
|
// Panic. n is sent over caps led. message is sent to dbg_caps (when in use).
|
|
#define panic(n, m) panic_impl ((n), __stringify (__LINE__), __PRETTY_FUNCTION__, (m))
|
|
void panic_impl (unsigned n, char const *line, char const *name, char const *message = "")
|
|
#ifndef NDEBUG
|
|
EXTERN Iris::Num dbg_code
|
|
EXTERN unsigned dbg_buffer[32]
|
|
EXTERN unsigned dbg_buffer_head
|
|
static void dbg_push (unsigned n):
|
|
dbg_buffer[dbg_buffer_head++] = n
|
|
if dbg_buffer_head == 32:
|
|
dbg_buffer_head = 0
|
|
EXTERN kCapRef dbg_cap
|
|
void dbg_send (unsigned num, unsigned bits)
|
|
void check (unsigned num, char const *msg)
|
|
#define dbg_check() ::check (__LINE__, __FILE__)
|
|
void print_free ()
|
|
void check_impl (kObject *o, unsigned num, char const *msg)
|
|
bool check_free (kObject *o, unsigned size)
|
|
#define dpanic(n, msg) panic (n, msg)
|
|
#define dbg_print() top_memory.print (__LINE__, 0)
|
|
#else
|
|
#define dbg_send(n, m) do {} while (0)
|
|
#define check (n, x) do {} while (0)
|
|
#define dpanic(n, x) do {} while (0)
|
|
#endif
|
|
|
|
/// Defined in schedule.ccp
|
|
void schedule ()
|
|
void timer_interrupt ()
|
|
|
|
EXTERN kMemory top_memory
|
|
EXTERN kReceiverP first_alarm
|
|
EXTERN kThread idle
|
|
EXTERN kMemory idle_memory
|
|
EXTERN kPage idle_page
|
|
EXTERN kThreadP first_scheduled
|
|
EXTERN kThreadP current, old_current
|
|
EXTERN bool do_schedule, must_wait
|
|
// reply_caps is the source of a receiver-generated reply capability.
|
|
// replied_caps is the source of kernel-generated capabilities which are used as arguments in a reply.
|
|
// reply_target is the target receiver for kernel replies.
|
|
// reply_protected is the protected data for the kernel reply.
|
|
EXTERN kCaps reply_caps, replied_caps
|
|
EXTERN kReceiver *reply_target
|
|
EXTERN Iris::Num reply_protected
|
|
|
|
// Defined in memory.ccp
|
|
unsigned init_memory (unsigned mem)
|
|
unsigned raw_zalloc ()
|
|
void raw_pfree (unsigned page)
|
|
unsigned phys_alloc (unsigned num)
|
|
void phys_free (unsigned page, unsigned num)
|
|
|
|
// Defind in invoke.ccp
|
|
void invoke (kReceiverP target, Iris::Num protected_data, kCapability::Context *c)
|
|
|
|
// Defined by architecture-specific files.
|
|
void kThread_arch_init (kThread *thread)
|
|
void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data)
|
|
unsigned *kThread_arch_info (kThread *thread, unsigned num)
|
|
void kMemory_arch_init (kMemory *mem)
|
|
void kMemory_arch_free (kMemory *mem)
|
|
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address)
|
|
void kMemory_arch_unmap (kMemory *mem, kPage *page)
|
|
kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address)
|
|
void kPage_arch_init (kPage *page)
|
|
void kPage_arch_update_mapping (kPage *page)
|
|
void arch_register_interrupt (unsigned num, kReceiverP r)
|
|
void arch_reboot ()
|
|
void arch_poweroff ()
|
|
void arch_suspend ()
|
|
void arch_boot (unsigned address, unsigned arg)
|
|
void arch_uncache_page (unsigned page)
|
|
|
|
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
|
#define __stringify2(x) #x
|
|
#define __stringify(x) __stringify2 (x)
|
|
#define kdebug_line() do { kdebug (__FILE__ ":"); kdebug (__PRETTY_FUNCTION__); kdebug (":"); kdebug (__stringify (__LINE__)); kdebug ('\n'); } while (0)
|
|
|
|
bool kMemory::map (kPage *page, unsigned address):
|
|
return kMemory_arch_map (this, page, address)
|
|
void kMemory::unmap (kPage *page):
|
|
page->forget ()
|
|
kMemory_arch_unmap (this, page)
|
|
kPage *kMemory::get_mapping (unsigned address):
|
|
return kMemory_arch_get_mapping (this, address)
|
|
kCapability *kCapRef::deref ():
|
|
return caps ? caps->cap (index) : NULL
|
|
void kCapRef::clone (kCapRef source, bool copy):
|
|
caps->clone (index, source, copy)
|
|
void kCapRef::set (kReceiver *target, Iris::Num pdata, kCapRef parent, kCapRef *parent_ptr):
|
|
if valid ():
|
|
deref ()->invalidate ()
|
|
caps->set (index, target, pdata, parent, parent_ptr)
|
|
void kCapability::invoke (kCapability::Context *c):
|
|
::invoke (target, protected_data, c)
|
|
kCapability *kCaps::cap (unsigned idx):
|
|
if idx >= size:
|
|
dpanic (idx, "invalid capability requested")
|
|
return NULL
|
|
return &caps[idx]
|
|
|
|
#endif
|