/* * \brief Fiasco.OC pager support * \author Christian Helmuth * \author Stefan Kalkowski * \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 /* Fiasco includes */ namespace Fiasco { #include } namespace Genode { class Mapping { private: addr_t _dst_addr; addr_t _src_addr; bool _write_combined; unsigned _log2size; bool _rw; bool _grant; public: /** * Constructor */ Mapping(addr_t dst_addr, addr_t src_addr, bool write_combined, unsigned l2size = L4_LOG2_PAGESIZE, bool rw = true, bool grant = false) : _dst_addr(dst_addr), _src_addr(src_addr), _write_combined(write_combined), _log2size(l2size), _rw(rw), _grant(grant) { } /** * Construct invalid flexpage */ Mapping() : _dst_addr(0), _src_addr(0), _write_combined(false), _log2size(0), _rw(false), _grant(false) { } Fiasco::l4_umword_t dst_addr() const { return _dst_addr; } bool grant() const { return _grant; } Fiasco::l4_fpage_t fpage() const { // TODO: write combined //if (write_combined) // _fpage.fp.cache = Fiasco::L4_FPAGE_BUFFERABLE; unsigned char rights = _rw ? Fiasco::L4_FPAGE_RW : Fiasco::L4_FPAGE_RO; return Fiasco::l4_fpage(_src_addr, _log2size, rights); } /** * Prepare map operation * * On Fiasco, we need to map a page locally to be able to map it to * another address space. */ void prepare_map_operation() { size_t mapping_size = 1 << _log2size; for (addr_t i = 0; i < mapping_size; i += L4_PAGESIZE) { if (_rw) touch_read_write((unsigned char volatile *)(_src_addr + i)); else touch_read((unsigned char const volatile *)(_src_addr + i)); } } }; /** * Special paging server class */ class Ipc_pager : public Native_capability { public: enum Msg_type { PAGEFAULT, WAKE_UP, PAUSE, EXCEPTION }; private: Native_thread _last; /* origin of last fault */ addr_t _pf_addr; /* page-fault address */ addr_t _pf_ip; /* ip of faulter */ Mapping _reply_mapping; /* page-fault answer */ unsigned long _badge; /* badge of faulting thread */ Fiasco::l4_msgtag_t _tag; /* receive message tag */ Fiasco::l4_exc_regs_t _regs; /* exception registers */ Msg_type _type; void _parse_msg_type(void); void _parse_exception(void); void _parse_pagefault(void); void _parse(unsigned long label); public: /** * Constructor */ Ipc_pager(); /** * Wait for a new page fault received as short message IPC */ void wait_for_fault(); /** * Reply current page-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 page 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) { _reply_mapping = m; } /** * Set destination for next reply */ void set_reply_dst(Native_capability pager_object) { _last = pager_object.dst(); } /** * 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 last() const { return _last; } /** * Return badge for faulting thread */ unsigned long badge() { return _badge; } bool is_write_fault() const { return (_pf_addr & 2); } /** * Return true if last fault was an exception */ bool is_exception() const { return _type == Ipc_pager::EXCEPTION; } /** * Return the type of ipc we received at last. */ Msg_type msg_type() { return _type; }; /** * Copy the exception registers from the last exception * to the given thread_state object. */ void copy_regs(Thread_state *state); }; } #endif /* _INCLUDE__BASE__IPC_PAGER_H_ */