/* * \brief Pistachio pager support for Genode * \author Christian Helmuth * \date 2006-06-14 */ /* * Copyright (C) 2006-2012 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #ifndef _INCLUDE__BASE__IPC_PAGER_H_ #define _INCLUDE__BASE__IPC_PAGER_H_ /* Genode includes */ #include #include #include #include #include /* Pistachio includes */ namespace Pistachio { #include } namespace Genode { class Mapping { private: union { Pistachio::L4_MapItem_t _map_item; Pistachio::L4_GrantItem_t _grant_item; }; /* * On Pistachio, the write-combining attribute is not part of a mapping * but it can be applied to a flexpage via the memory-control system * call. Therefore, we need to keep the flag in an extra member variable. */ bool _write_combined; /* enable write-combined access to I/O memory */ public: /** * Constructor */ Mapping(addr_t dst_addr, addr_t src_addr, bool write_combined, bool io_mem, unsigned l2size = Pistachio::get_page_size_log2(), bool rw = true, bool grant = false); /** * Construct invalid mapping */ Mapping(); addr_t _dst_addr() const { return Pistachio::L4_SndBase(_map_item); } Pistachio::L4_Fpage_t fpage() const { return Pistachio::L4_MapItemSndFpage(_map_item); } Pistachio::L4_MapItem_t map_item() const { return _map_item; }; /** * Prepare map operation * * On Pistachio, we need to map a page locally to be able to map it * to another address space. */ void prepare_map_operation() { using namespace Pistachio; unsigned char volatile *core_local_addr = (unsigned char volatile *)L4_Address(_map_item.X.snd_fpage); if (L4_Rights(_map_item.X.snd_fpage) & L4_Writable) touch_read_write(core_local_addr); else touch_read(core_local_addr); } }; /** * Special paging server class */ class Ipc_pager : public Native_capability { private: Pistachio::L4_ThreadId_t _last; /* origin of last fault message */ Pistachio::L4_Word_t _flags; /* page-fault attributes */ addr_t _pf_addr; /* page-fault address */ addr_t _pf_ip; /* instruction pointer of faulter */ Pistachio::L4_MapItem_t _map_item; /* page-fault answer */ protected: /** * Wait for short-message (register) IPC -- pagefault */ void _wait(); /** * Send short flex page and * wait for next short-message (register) IPC -- pagefault */ void _reply_and_wait(); public: /** * Constructor */ Ipc_pager(); /** * Wait for a new fault received as short message IPC */ void wait_for_fault(); /** * Reply current fault and wait for a new one * * Send short flex page and wait for next short-message (register) * IPC -- pagefault */ void reply_and_wait_for_fault(); /** * Request instruction pointer of current fault */ addr_t fault_ip() { return _pf_ip; } /** * Request fault address of current page fault */ addr_t fault_addr() { return _pf_addr & ~3; } /** * Set parameters for next reply */ void set_reply_mapping(Mapping m) { _map_item = m.map_item(); } /** * Set destination for next reply */ void set_reply_dst(Native_capability pager_object) { _last.raw = pager_object.local_name(); } /** * Answer call without sending a flex-page mapping * * This function is used to acknowledge local calls from one of * core's region-manager sessions. */ void acknowledge_wakeup(); /** * Return thread ID of last faulter */ Native_thread_id last() const { return _last; } /** * Return badge for faulting thread * * As L4v4 has no server-defined badges for fault messages, * we interpret the sender ID as badge. */ unsigned long badge() const { return _last.raw; } /** * Return true if last fault was a write fault */ bool is_write_fault() const { return (_flags & 2); } /** * Return true if last fault was an exception */ bool is_exception() const { /* * Reflection of exceptions is not supported on this platform. */ return false; } }; } #endif /* _INCLUDE__BASE__IPC_PAGER_H_ */