1  /*
   2   * \brief  Region manager session interface
   3   * \author Norman Feske
   4   * \date   2006-05-15
   5   */

   6  
   7  /*
   8   * Copyright (C) 2006-2013 Genode Labs GmbH
   9   *
  10   * This file is part of the Genode OS framework, which is distributed
  11   * under the terms of the GNU General Public License version 2.
  12   */

  13  
  14  #ifndef _INCLUDE__RM_SESSION__RM_SESSION_H_
  15  #define _INCLUDE__RM_SESSION__RM_SESSION_H_
  16  
  17  #include <base/exception.h>
  18  #include <base/stdint.h>
  19  #include <base/signal.h>
  20  #include <dataspace/capability.h>
  21  #include <thread/capability.h>
  22  #include <pager/capability.h>
  23  #include <session/session.h>
  24  
  25  namespace Genode { struct Rm_session; }
  26  
  27  
  28  struct Genode::Rm_session : Session
  29  {
  30     enum Fault_type {
  31        READY = 0, READ_FAULT = 1, WRITE_FAULT = 2, EXEC_FAULT = 3 }
;

  32  
  33     /**
  34      * State of region-manager session
  35      *
  36      * If a client accesses a location outside the regions attached to
  37      * the region-manager session, a fault occurs and gets signalled to
  38      * the registered fault handler. The fault handler, in turn needs
  39      * the information about the fault address and fault type to
  40      * resolve the fault. This information is represented by this
  41      * structure.
  42      */

  43     struct State
  44     {
  45        /**
  46         * Type of occurred fault
  47         */

  48        Fault_type type;
  49  
  50        /**
  51         * Fault address
  52         */

  53        addr_t addr;
  54  
  55        /**
  56         * Default constructor
  57         */

  58        State() : type(READY), addr(0) { }

  59  
  60        /**
  61         * Constructor
  62         */

  63        State(Fault_type fault_type, addr_t fault_addr) :
  64           type(fault_type), addr(fault_addr)
 { }

  65     }
;

  66  
  67  
  68     /**
  69      * Helper for tranferring the bit representation of a pointer as RPC
  70      * argument.
  71      */

  72     class Local_addr
  73     {
  74        private:
  75  
  76           void *_ptr;

  77  
  78        public:
  79  
  80           template <typename T>
  81           Local_addr(ptr) : _ptr((void *)ptr) { }

  82  
  83           Local_addr() : _ptr(0) { }
  84  
  85           template <typename T>
  86           operator T () { return (T)_ptr; }

  87     }
;

  88  
  89  
  90     static const char *service_name() { return "RM"; }
  91  
  92  
  93     /*********************
  94      ** Exception types **
  95      *********************/

  96  
  97     class Attach_failed     : public Exception     { };
  98     class Invalid_args      : public Attach_failed { };
  99     class Invalid_dataspace : public Attach_failed { };
 100     class Region_conflict   : public Attach_failed { };
 101     class Out_of_metadata   : public Attach_failed { };
 102  
 103     class Invalid_thread    : public Exception { };
 104     class Unbound_thread    : public Exception { };
 105  
 106     /**
 107      * Destructor
 108      */

 109     virtual ~Rm_session() { }

 110  
 111     /**
 112      * Map dataspace into local address space
 113      *
 114      * \param ds               capability of dataspace to map
 115      * \param size             size of the locally mapped region
 116      *                         default (0) is the whole dataspace
 117      * \param offset           start at offset in dataspace (page-aligned)
 118      * \param use_local_addr   if set to true, attach the dataspace at
 119      *                         the specified `local_addr`
 120      * \param local_addr       local destination address
 121      * \param executable       if the mapping should be executable
 122      *
 123      * \throw Attach_failed    if dataspace or offset is invalid,
 124      *                         or on region conflict
 125      * \throw Out_of_metadata  if meta-data backing store is exhausted
 126      *
 127      * \return                 local address of mapped dataspace
 128      *
 129      */

 130     virtual Local_addr attach(Dataspace_capability ds,
 131                               size_t size = 0, off_t offset = 0,
 132                               bool use_local_addr = false,
 133                               Local_addr local_addr = (void *)0,
 134                               bool executable = false)
 = 0;

 135  
 136     /**
 137      * Shortcut for attaching a dataspace at a predefined local address
 138      */

 139     Local_addr attach_at(Dataspace_capability ds, addr_t local_addr,
 140                          size_t size = 0, off_t offset = 0)
 {
 141        return attach(ds, size, offset, true, local_addr); }

 142  
 143     /**
 144      * Shortcut for attaching a dataspace executable at a predefined local address
 145      */

 146     Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr,
 147                                  size_t size = 0, off_t offset = 0)
 {
 148        return attach(ds, size, offset, true, local_addr, true); }

 149  
 150     /**
 151      * Remove region from local address space
 152      */

 153     virtual void detach(Local_addr local_addr) = 0;

 154  
 155     /**
 156      * Add client to pager
 157      *
 158      * \param thread  thread that will be paged
 159      * \throw         Invalid_thread
 160      * \throw         Out_of_metadata
 161      * \throw         Unbound_thread
 162      * \return        capability to be used for handling page faults
 163      *
 164      * This method must be called at least once to establish a valid
 165      * communication channel between the pager part of the region manager
 166      * and the client thread.
 167      */

 168     virtual Pager_capability add_client(Thread_capability thread) = 0;

 169  
 170     /**
 171      * Remove client from pager
 172      *
 173      * \param pager  pager capability of client to be removed
 174      */

 175     virtual void remove_client(Pager_capability) = 0;

 176  
 177     /**
 178      * Register signal handler for region-manager faults
 179      *
 180      * On Linux, this signal is never delivered because page-fault handling
 181      * is performed by the Linux kernel. On microkernel platforms,
 182      * unresolvable page faults (traditionally called segmentation fault)
 183      * will result in the delivery of the signal.
 184      */

 185     virtual void fault_handler(Signal_context_capability handler) = 0;

 186  
 187     /**
 188      * Request current state of RM session
 189      */

 190     virtual State state() = 0;

 191  
 192     /**
 193      * Return dataspace representation of region-manager session
 194      */

 195     virtual Dataspace_capability dataspace() = 0;

 196  
 197  
 198     /*********************
 199      ** RPC declaration **
 200      *********************/

 201  
 202     GENODE_RPC_THROW(Rpc_attach, Local_addr, attach,
 203                      GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict,
 204                                       Out_of_metadata, Invalid_args)
,
 205                      Dataspace_capability, size_t, off_t, bool, Local_addr, bool)
;
 206     GENODE_RPC(Rpc_detach, void, detach, Local_addr);
 207     GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client,
 208                      GENODE_TYPE_LIST(Unbound_thread, Invalid_thread, Out_of_metadata),
 209                      Thread_capability)
;
 210     GENODE_RPC(Rpc_remove_client, void, remove_client, Pager_capability);
 211     GENODE_RPC(Rpc_fault_handler, void, fault_handler, Signal_context_capability);
 212     GENODE_RPC(Rpc_state, State, state);
 213     GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace);
 214  
 215     GENODE_RPC_INTERFACE(Rpc_attach, Rpc_detach, Rpc_add_client,
 216                          Rpc_remove_client, Rpc_fault_handler, Rpc_state,
 217                          Rpc_dataspace)
;
 218  }
;

 219  
 220  #endif /* _INCLUDE__RM_SESSION__RM_SESSION_H_ */