#pypp 0 // Iris: micro-kernel for a capability-based operating system. // kernel.hhp: Header for all kernel sources. // 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 . #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