/* * \brief Component-local region-map implementation based on mmap * \author Norman Feske * \author Christian Helmuth * \date 2006-07-28 */ /* * Copyright (C) 2006-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _INCLUDE__BASE__INTERNAL__REGION_MAP_MMAP_H_ #define _INCLUDE__BASE__INTERNAL__REGION_MAP_MMAP_H_ /* Genode includes */ #include #include #include #include /* base-internal includes */ #include #include namespace Genode { class Region_map_mmap; } /** * On Linux, we use a locally implemented region map that attaches dataspaces * via mmap to the local address space. */ class Genode::Region_map_mmap : public Region_map, public Dataspace { private: Region_registry _rmap { }; bool const _sub_rm; /* false if region map is root */ size_t const _size; /** * Base offset of the RM session * * For a normal RM session (the one that comes with the 'env()', this * value is zero. If the RM session is used as nested dataspace, * '_base' contains the address where the managed dataspace is attached * in the root RM session. * * Note that a managed dataspace cannot be attached more than once. * Furthermore, managed dataspace cannot be attached to another managed * dataspace. The nested dataspace emulation is solely implemented to * support the common use case of managed dataspaces as mechanism to * reserve parts of the local address space from being populated by the * 'env()->rm_session()'. (i.e., for the stack area, or for the * placement of consecutive shared-library segments) */ addr_t _base; bool _is_attached() const { return _base > 0; } void _add_to_rmap(Region const &); /** * Reserve VM region for sub-rm dataspace */ addr_t _reserve_local(bool use_local_addr, addr_t local_addr, size_t size); /** * Map dataspace into local address space */ void *_map_local(Dataspace_capability ds, size_t size, addr_t offset, bool use_local_addr, addr_t local_addr, bool executable, bool overmap, bool writeable); /** * Determine size of dataspace * * For core, this function performs a local lookup of the * 'Dataspace_component' object. For non-core programs, the dataspace * size is determined via an RPC to core (calling 'Dataspace::size()'). */ size_t _dataspace_size(Capability); /** * Determine file descriptor of dataspace */ int _dataspace_fd(Capability); /** * Determine whether dataspace is writable */ bool _dataspace_writable(Capability); public: Region_map_mmap(bool sub_rm, size_t size = ~0) : _sub_rm(sub_rm), _size(size), _base(0) { } ~Region_map_mmap() { /* detach sub RM session when destructed */ if (_sub_rm && _is_attached()) env_deprecated()->rm_session()->detach((void *)_base); } /************************** ** Region map interface ** **************************/ Local_addr attach(Dataspace_capability, size_t size, off_t, bool, Local_addr, bool, bool) override; void detach(Local_addr) override; void fault_handler(Signal_context_capability) override { } State state() override { return State(); } /************************* ** Dataspace interface ** *************************/ size_t size() override { return _size; } addr_t phys_addr() override { return 0; } bool writable() override { return true; } /** * Return pseudo dataspace capability of the RM session * * The capability returned by this function is only usable * as argument to 'Region_map_mmap::attach'. It is not a * real capability. */ Dataspace_capability dataspace() override { return Local_capability::local_cap(this); } }; #endif /* _INCLUDE__BASE__INTERNAL__REGION_MAP_MMAP_H_ */