L4Re/departure

Changeset

515:bae2ddb47ecd
2023-03-15 Paul Boddie raw files shortlog changelog graph Introduced support for reserve_area in the internal pager along with different kinds of memory area. This permits the execution of threaded programs.
libexec/include/exec/internal_pager.h (file) libexec/include/exec/mapped_region.h (file) libexec/include/exec/memory_area.h (file) libexec/include/exec/pager.h (file) libexec/lib/src/Makefile (file) libexec/lib/src/external_pager.cc (file) libexec/lib/src/internal_pager.cc (file) libexec/lib/src/memory_area.cc (file) libexec/lib/src/pager.cc (file) libexec/lib/src/segment.cc (file) libexec/rm/region_mapper.cc (file)
     1.1 --- a/libexec/include/exec/internal_pager.h	Tue Mar 14 23:51:57 2023 +0100
     1.2 +++ b/libexec/include/exec/internal_pager.h	Wed Mar 15 00:33:40 2023 +0100
     1.3 @@ -58,6 +58,9 @@
     1.4  
     1.5    virtual long attach(address_t *start, address_t size, map_flags_t flags,
     1.6                        l4_cap_idx_t ds, address_t offset, unsigned char align);
     1.7 +
     1.8 +  virtual long reserve_area(address_t *start, address_t size, map_flags_t flags,
     1.9 +                            unsigned char align);
    1.10  };
    1.11  
    1.12  /* vim: tabstop=2 expandtab shiftwidth=2
     2.1 --- a/libexec/include/exec/mapped_region.h	Tue Mar 14 23:51:57 2023 +0100
     2.2 +++ b/libexec/include/exec/mapped_region.h	Wed Mar 15 00:33:40 2023 +0100
     2.3 @@ -1,7 +1,7 @@
     2.4  /*
     2.5   * Mapped memory region support.
     2.6   *
     2.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
     2.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
     2.9   *
    2.10   * This program is free software; you can redistribute it and/or
    2.11   * modify it under the terms of the GNU General Public License as
    2.12 @@ -23,32 +23,51 @@
    2.13  
    2.14  #include <l4/sys/types.h>
    2.15  
    2.16 +#include <exec/memory_area.h>
    2.17  #include <systypes/base.h>
    2.18  
    2.19  
    2.20  
    2.21  /* A mapped region abstraction. */
    2.22  
    2.23 -class MappedRegion
    2.24 +class MappedRegion : public MemoryArea
    2.25  {
    2.26 +protected:
    2.27 +  l4_umword_t _flags;
    2.28 +  l4_cap_idx_t _ds;
    2.29 +  address_t _ds_start;
    2.30 +
    2.31  public:
    2.32 -  l4_addr_t start;
    2.33 -  offset_t size;
    2.34 -  l4_umword_t flags;
    2.35 -  l4_cap_idx_t ds;
    2.36 -  l4_addr_t ds_start;
    2.37 -
    2.38    explicit MappedRegion()
    2.39 -  : start(0), size(0), flags(0), ds(L4_INVALID_CAP), ds_start(0)
    2.40 +  : MemoryArea(), _flags(0), _ds(L4_INVALID_CAP), _ds_start(0)
    2.41    {
    2.42    }
    2.43  
    2.44 -  explicit MappedRegion(l4_addr_t start, l4_addr_t size,
    2.45 +  explicit MappedRegion(address_t start, address_t end,
    2.46                          l4_umword_t flags, l4_cap_idx_t ds = L4_INVALID_CAP,
    2.47 -                        l4_addr_t ds_start = 0)
    2.48 -  : start(start), size(size), flags(flags), ds(ds), ds_start(ds_start)
    2.49 +                        address_t ds_start = 0)
    2.50 +  : MemoryArea(start, end), _flags(flags), _ds(ds), _ds_start(ds_start)
    2.51    {
    2.52    }
    2.53 +
    2.54 +  virtual MemoryArea *copy()
    2.55 +  { return new MappedRegion(_start, _end, _flags, _ds, _ds_start); }
    2.56 +
    2.57 +  /* Access to area properties. */
    2.58 +
    2.59 +  virtual l4_umword_t flags()
    2.60 +  { return _flags; }
    2.61 +
    2.62 +  virtual l4_cap_idx_t dataspace()
    2.63 +  { return _ds; }
    2.64 +
    2.65 +  virtual address_t dataspace_start()
    2.66 +  { return _ds_start; }
    2.67 +
    2.68 +  /* Return whether the area provides a mapped region. */
    2.69 +
    2.70 +  virtual bool is_mapped()
    2.71 +  { return true; }
    2.72  };
    2.73  
    2.74  /* vim: tabstop=2 expandtab shiftwidth=2
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/libexec/include/exec/memory_area.h	Wed Mar 15 00:33:40 2023 +0100
     3.3 @@ -0,0 +1,218 @@
     3.4 +/*
     3.5 + * Memory area support.
     3.6 + *
     3.7 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
     3.8 + *
     3.9 + * This program is free software; you can redistribute it and/or
    3.10 + * modify it under the terms of the GNU General Public License as
    3.11 + * published by the Free Software Foundation; either version 2 of
    3.12 + * the License, or (at your option) any later version.
    3.13 + *
    3.14 + * This program is distributed in the hope that it will be useful,
    3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 + * GNU General Public License for more details.
    3.18 + *
    3.19 + * You should have received a copy of the GNU General Public License
    3.20 + * along with this program; if not, write to the Free Software
    3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
    3.22 + * Boston, MA  02110-1301, USA
    3.23 + */
    3.24 +
    3.25 +#pragma once
    3.26 +
    3.27 +#include <map>
    3.28 +#include <set>
    3.29 +#include <stack>
    3.30 +
    3.31 +#include <l4/sys/types.h>
    3.32 +
    3.33 +#include <systypes/base.h>
    3.34 +
    3.35 +
    3.36 +
    3.37 +/* A memory area abstraction. */
    3.38 +
    3.39 +class MemoryArea
    3.40 +{
    3.41 +protected:
    3.42 +  address_t _start, _end;
    3.43 +
    3.44 +public:
    3.45 +  explicit MemoryArea()
    3.46 +  : _start(0), _end(0)
    3.47 +  {
    3.48 +  }
    3.49 +
    3.50 +  explicit MemoryArea(address_t start, address_t end)
    3.51 +  : _start(start), _end(end)
    3.52 +  {
    3.53 +  }
    3.54 +
    3.55 +  virtual ~MemoryArea()
    3.56 +  {
    3.57 +  }
    3.58 +
    3.59 +  virtual MemoryArea *copy();
    3.60 +
    3.61 +  /* Access to area properties. */
    3.62 +
    3.63 +  virtual address_t area_start()
    3.64 +  { return _start; }
    3.65 +
    3.66 +  virtual address_t area_end()
    3.67 +  { return _end; }
    3.68 +
    3.69 +  virtual l4_umword_t flags()
    3.70 +  { return 0; }
    3.71 +
    3.72 +  virtual l4_cap_idx_t dataspace()
    3.73 +  { return L4_INVALID_CAP; }
    3.74 +
    3.75 +  virtual address_t dataspace_start()
    3.76 +  { return 0; }
    3.77 +
    3.78 +  /* Return whether the area supports the given address. */
    3.79 +
    3.80 +  virtual bool supports(address_t addr)
    3.81 +  { return (_start <= addr) && (addr < _end); }
    3.82 +
    3.83 +  /* Return whether an area is reserved and therefore cannot be mapped. */
    3.84 +
    3.85 +  virtual bool is_reserved()
    3.86 +  { return false; }
    3.87 +
    3.88 +  /* Return whether the area provides a mapped region. */
    3.89 +
    3.90 +  virtual bool is_mapped()
    3.91 +  { return false; }
    3.92 +
    3.93 +  /* Support for populating areas. */
    3.94 +
    3.95 +  virtual long add(MemoryArea &area);
    3.96 +
    3.97 +  virtual long remove(MemoryArea &area);
    3.98 +
    3.99 +  /* Support for finding regions. */
   3.100 +
   3.101 +  virtual long find(address_t addr, MemoryArea **area);
   3.102 +
   3.103 +  /* Support for finding areas. */
   3.104 +
   3.105 +  virtual long find(address_t *start, address_t *size, map_flags_t flags,
   3.106 +                    unsigned char align, MemoryArea **area);
   3.107 +};
   3.108 +
   3.109 +
   3.110 +
   3.111 +/* A reserved area abstraction. */
   3.112 +
   3.113 +class ReservedMemoryArea : public MemoryArea
   3.114 +{
   3.115 +public:
   3.116 +  explicit ReservedMemoryArea(address_t start, address_t end)
   3.117 +  : MemoryArea(start, end)
   3.118 +  {
   3.119 +  }
   3.120 +
   3.121 +  virtual MemoryArea *copy();
   3.122 +
   3.123 +  /* Return whether an area is reserved and therefore cannot be mapped. */
   3.124 +
   3.125 +  virtual bool is_reserved()
   3.126 +  { return true; }
   3.127 +
   3.128 +  /* Support for finding areas. */
   3.129 +
   3.130 +  virtual long find(address_t addr, MemoryArea **area);
   3.131 +};
   3.132 +
   3.133 +
   3.134 +
   3.135 +/* Collection types. */
   3.136 +
   3.137 +typedef std::map<address_t, MemoryArea *> MemoryAreaMap;
   3.138 +typedef std::set<MemoryArea *> MemoryAreas;
   3.139 +
   3.140 +
   3.141 +
   3.142 +/* A memory area containing other areas. */
   3.143 +
   3.144 +class AvailableMemoryArea : public MemoryArea
   3.145 +{
   3.146 +protected:
   3.147 +  MemoryAreaMap _areas;
   3.148 +  MemoryAreas _allocated;
   3.149 +
   3.150 +public:
   3.151 +  explicit AvailableMemoryArea(address_t start, address_t end)
   3.152 +  : MemoryArea(start, end)
   3.153 +  {
   3.154 +  }
   3.155 +
   3.156 +  virtual ~AvailableMemoryArea();
   3.157 +
   3.158 +  virtual MemoryArea *copy();
   3.159 +
   3.160 +  /* Support for populating areas. */
   3.161 +
   3.162 +  virtual long add(MemoryArea &area);
   3.163 +
   3.164 +  virtual long remove(MemoryArea &area);
   3.165 +
   3.166 +  /* Support for finding areas. */
   3.167 +
   3.168 +  virtual long find(address_t addr, MemoryArea **area);
   3.169 +
   3.170 +  virtual long find(address_t *start, address_t *size, map_flags_t flags,
   3.171 +                    unsigned char align, MemoryArea **area);
   3.172 +
   3.173 +  /* A recursive iterator over a memory area. */
   3.174 +
   3.175 +  class iterator
   3.176 +  {
   3.177 +  protected:
   3.178 +    std::stack<MemoryAreaMap::iterator> _iterators, _ends;
   3.179 +
   3.180 +    void ascend();
   3.181 +
   3.182 +    void descend();
   3.183 +
   3.184 +    void descend_all();
   3.185 +
   3.186 +  public:
   3.187 +    explicit iterator();
   3.188 +
   3.189 +    explicit iterator(MemoryAreaMap::iterator it,
   3.190 +                      MemoryAreaMap::iterator end);
   3.191 +
   3.192 +    MemoryArea *operator *();
   3.193 +
   3.194 +    iterator &operator ++();
   3.195 +
   3.196 +    iterator &operator ++(int);
   3.197 +
   3.198 +    bool operator ==(iterator other);
   3.199 +
   3.200 +    bool operator !=(iterator other);
   3.201 +
   3.202 +    /* Access to the underlying iterators. */
   3.203 +
   3.204 +    MemoryAreaMap::iterator &area_iterator();
   3.205 +
   3.206 +    MemoryAreaMap::iterator &area_end();
   3.207 +  };
   3.208 +
   3.209 +  /* Iteration methods. */
   3.210 +
   3.211 +  virtual iterator begin();
   3.212 +
   3.213 +  virtual iterator end();
   3.214 +
   3.215 +  virtual MemoryAreaMap::iterator areas_begin();
   3.216 +
   3.217 +  virtual MemoryAreaMap::iterator areas_end();
   3.218 +};
   3.219 +
   3.220 +/* vim: tabstop=2 expandtab shiftwidth=2
   3.221 +*/
     4.1 --- a/libexec/include/exec/pager.h	Tue Mar 14 23:51:57 2023 +0100
     4.2 +++ b/libexec/include/exec/pager.h	Wed Mar 15 00:33:40 2023 +0100
     4.3 @@ -21,15 +21,15 @@
     4.4  
     4.5  #pragma once
     4.6  
     4.7 -#include <map>
     4.8 +#include <set>
     4.9  
    4.10 -#include <exec/mapped_region.h>
    4.11 +#include <exec/memory_area.h>
    4.12  
    4.13  
    4.14  
    4.15 -/* Collection types. */
    4.16 +/* Collection definitions. */
    4.17  
    4.18 -typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
    4.19 +typedef std::set<l4_cap_idx_t> Capabilities;
    4.20  
    4.21  
    4.22  
    4.23 @@ -38,14 +38,19 @@
    4.24  class ExecPager
    4.25  {
    4.26  protected:
    4.27 -  address_t _start, _end;
    4.28 +
    4.29 +  /* Top-level area containing other areas and regions. */
    4.30 +
    4.31 +  AvailableMemoryArea _area;
    4.32 +
    4.33 +  /* Dataspace capabilities associated with regions. */
    4.34 +
    4.35 +  Capabilities _dataspaces;
    4.36  
    4.37    /* Region manager/mapper functionality. */
    4.38  
    4.39 -  MappedRegions _regions;
    4.40 -
    4.41    virtual long find(address_t *start, address_t *size, map_flags_t flags,
    4.42 -                    address_t offset, unsigned char align);
    4.43 +                    unsigned char align, MemoryArea **area);
    4.44  
    4.45  public:
    4.46    explicit ExecPager(address_t start = 0, address_t end = 0);
    4.47 @@ -54,9 +59,9 @@
    4.48  
    4.49    /* Region management methods. */
    4.50  
    4.51 -  virtual void add(MappedRegion &region);
    4.52 +  virtual void add(MemoryArea &area);
    4.53  
    4.54 -  virtual void remove(MappedRegion &region);
    4.55 +  virtual void remove(MemoryArea &area);
    4.56  
    4.57    /* Notification methods. */
    4.58  
     5.1 --- a/libexec/lib/src/Makefile	Tue Mar 14 23:51:57 2023 +0100
     5.2 +++ b/libexec/lib/src/Makefile	Wed Mar 15 00:33:40 2023 +0100
     5.3 @@ -28,8 +28,11 @@
     5.4  # Normal source files.
     5.5  
     5.6  PLAIN_SRC_CC			= \
     5.7 -				common.cc elf.cc external_pager.cc \
     5.8 -				internal_pager.cc memory.cc pager.cc \
     5.9 +				common.cc elf.cc \
    5.10 +				external_pager.cc \
    5.11 +				internal_pager.cc \
    5.12 +				memory.cc memory_area.cc \
    5.13 +				pager.cc \
    5.14  				process.cc process_creating.cc \
    5.15  				process_creator_context_resource.cc \
    5.16  				process_creator_resource.cc \
     6.1 --- a/libexec/lib/src/external_pager.cc	Tue Mar 14 23:51:57 2023 +0100
     6.2 +++ b/libexec/lib/src/external_pager.cc	Wed Mar 15 00:33:40 2023 +0100
     6.3 @@ -58,7 +58,7 @@
     6.4  
     6.5  void ExternalPager::close()
     6.6  {
     6.7 -  printf("Pager closing...\n");
     6.8 +  printf("External pager closing...\n");
     6.9  
    6.10    /* Remove pager regions to avoid unmapping them twice. */
    6.11  
    6.12 @@ -77,15 +77,22 @@
    6.13  
    6.14    /* Unmap all remaining regions. */
    6.15  
    6.16 -  MappedRegions::iterator it;
    6.17 +  AvailableMemoryArea::iterator it;
    6.18  
    6.19 -  for (it = _regions.begin(); it != _regions.end(); it++)
    6.20 +  for (it = _area.begin(); it != _area.end(); it++)
    6.21    {
    6.22 -    MappedRegion &r = it->second;
    6.23 +    MemoryArea *r = *it;
    6.24 +
    6.25 +    if (r->is_mapped())
    6.26 +      ipc_detach_dataspace((void *) r->dataspace_start());
    6.27 +  }
    6.28  
    6.29 -    ipc_detach_dataspace((void *) r.ds_start);
    6.30 -    ipc_cap_free_um(r.ds);
    6.31 -  }
    6.32 +  /* Free all capabilities. */
    6.33 +
    6.34 +  Capabilities::iterator itc;
    6.35 +
    6.36 +  for (itc = _dataspaces.begin(); itc != _dataspaces.end(); itc++)
    6.37 +    ipc_cap_free_um(*itc);
    6.38  
    6.39    /* Remove the created task. */
    6.40  
    6.41 @@ -172,61 +179,47 @@
    6.42    printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
    6.43  #endif
    6.44  
    6.45 -  /* Find the first region whose start address is beyond the fault address,
    6.46 -     testing if any immediately preceding region contains the fault address. */
    6.47 -
    6.48 -  MappedRegions::iterator it = _regions.upper_bound(addr);
    6.49 +  /* Obtain a region supporting the fault address. */
    6.50  
    6.51 -  if (it != _regions.begin())
    6.52 -    it--;
    6.53 -  else
    6.54 -  {
    6.55 -    printf("not mapped at %lx for pc %lx\n", addr, pc);
    6.56 -    return -L4_ENOMEM;
    6.57 -  }
    6.58 +  MemoryArea *r;
    6.59 +  long err = _area.find(addr, &r);
    6.60  
    6.61 -  /* Obtain the region and test if it contains the fault address. */
    6.62 -
    6.63 -  MappedRegion &r = it->second;
    6.64 -
    6.65 -  if ((addr >= r.start) && (addr < r.start + r.size))
    6.66 +  if (!err)
    6.67    {
    6.68      l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
    6.69      map_flags_t map_flags = map_flags_for_fault(flags);
    6.70  
    6.71 -    region->fpage = l4_fpage(r.ds_start + (page_addr - r.start), L4_PAGESHIFT, map_flags & r.flags);
    6.72 +    region->fpage = l4_fpage(r->dataspace_start() + (page_addr - r->area_start()), L4_PAGESHIFT, map_flags & r->flags());
    6.73      region->snd_base = page_addr;
    6.74  
    6.75  #if DEBUG
    6.76      printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x ds %lx\n",
    6.77 -           r.start, region->snd_base,
    6.78 -           r.ds_start, l4_fpage_memaddr(region->fpage),
    6.79 -           addr - r.start,
    6.80 +           r->area_start(), region->snd_base,
    6.81 +           r->dataspace_start(), l4_fpage_memaddr(region->fpage),
    6.82 +           addr - r->area_start(),
    6.83             l4_fpage_size(region->fpage),
    6.84             l4_fpage_rights(region->fpage),
    6.85 -           r.ds);
    6.86 +           r->dataspace());
    6.87  
    6.88      printf("%lx -> ", addr);
    6.89  
    6.90      for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
    6.91 -      printf("%02x", *((unsigned char *)(r.ds_start + (addr - r.start) + i)));
    6.92 +      printf("%02x", *((unsigned char *)(r->dataspace_start() + (addr - r->area_start()) + i)));
    6.93  
    6.94      printf("\n");
    6.95  #endif
    6.96  
    6.97 -    if (r.flags & L4RE_RM_F_W)
    6.98 -      l4_touch_rw((const void *) (r.ds_start + (page_addr - r.start)), L4_PAGESIZE);
    6.99 +    if (r->flags() & L4RE_RM_F_W)
   6.100 +      l4_touch_rw((const void *) (r->dataspace_start() + (page_addr - r->area_start())), L4_PAGESIZE);
   6.101      else
   6.102 -      l4_touch_ro((const void *) (r.ds_start + (page_addr - r.start)), L4_PAGESIZE);
   6.103 +      l4_touch_ro((const void *) (r->dataspace_start() + (page_addr - r->area_start())), L4_PAGESIZE);
   6.104  
   6.105      return L4_EOK;
   6.106    }
   6.107  
   6.108 -#if DEBUG
   6.109 -  printf("not mapped!\n");
   6.110 -#endif
   6.111 +  printf("not mapped at %lx for pc %lx\n", addr, pc);
   6.112  
   6.113 -  return -L4_ENOMEM;
   6.114 +  return err;
   6.115  }
   6.116  
   6.117  /* Attach a region for provision when page faults occur. This is required in
   6.118 @@ -237,7 +230,12 @@
   6.119                             l4_cap_idx_t ds, address_t offset,
   6.120                             unsigned char align)
   6.121  {
   6.122 -  long err = ExecPager::find(start, &size, flags, offset, align);
   6.123 +  // NOTE: Determine the purpose of offset.
   6.124 +
   6.125 +  (void) offset;
   6.126 +
   6.127 +  MemoryArea *area;
   6.128 +  long err = ExecPager::find(start, &size, flags, align, &area);
   6.129  
   6.130    /* Without an error, attach the dataspace. */
   6.131  
   6.132 @@ -257,8 +255,12 @@
   6.133  
   6.134      l4_touch_rw((const void *) ds_start, size);
   6.135  
   6.136 -    MappedRegion r(*start, size, flags & L4RE_DS_F_RIGHTS_MASK, ds, ds_start);
   6.137 -    add(r);
   6.138 +    MappedRegion r(*start, *start + size, flags & L4RE_DS_F_RIGHTS_MASK, ds, ds_start);
   6.139 +    area->add(r);
   6.140 +
   6.141 +    /* Record dataspaces separately. */
   6.142 +
   6.143 +    _dataspaces.insert(ds);
   6.144    }
   6.145  
   6.146    /* Discard the imported dataspace if its region cannot be accommodated. */
   6.147 @@ -281,6 +283,8 @@
   6.148  
   6.149    if (sig == 0)
   6.150    {
   6.151 +    printf("Signal from task.\n");
   6.152 +
   6.153      /* Once the program exits, the IPC gate connecting the program with its
   6.154         internal pager can be released. */
   6.155  
     7.1 --- a/libexec/lib/src/internal_pager.cc	Tue Mar 14 23:51:57 2023 +0100
     7.2 +++ b/libexec/lib/src/internal_pager.cc	Wed Mar 15 00:33:40 2023 +0100
     7.3 @@ -21,6 +21,7 @@
     7.4  
     7.5  #include <l4/re/env.h>
     7.6  #include <l4/re/c/dataspace.h>
     7.7 +#include <l4/re/c/rm.h>
     7.8  #include <l4/util/util.h>
     7.9  
    7.10  #include <ipc/cap_alloc.h>
    7.11 @@ -31,6 +32,7 @@
    7.12  
    7.13  #include "dataspace_client.h"
    7.14  #include "internal_pager.h"
    7.15 +#include "mapped_region.h"
    7.16  #include "pager_object_server.h"
    7.17  
    7.18  
    7.19 @@ -61,14 +63,10 @@
    7.20  
    7.21    /* Unmap all regions. */
    7.22  
    7.23 -  MappedRegions::iterator it;
    7.24 +  Capabilities::iterator itc;
    7.25  
    7.26 -  for (it = _regions.begin(); it != _regions.end(); it++)
    7.27 -  {
    7.28 -    MappedRegion &r = it->second;
    7.29 -
    7.30 -    ipc_cap_free_um(r.ds);
    7.31 -  }
    7.32 +  for (itc = _dataspaces.begin(); itc != _dataspaces.end(); itc++)
    7.33 +    ipc_cap_free_um(*itc);
    7.34  }
    7.35  
    7.36  
    7.37 @@ -101,43 +99,33 @@
    7.38    printf("regs = %p\n; regs->user[0] = %lx\n", regs, regs->user[0]);
    7.39  #endif
    7.40  
    7.41 -  /* Find the first region whose start address is beyond the fault address,
    7.42 -     testing if any immediately preceding region contains the fault address. */
    7.43 -
    7.44 -  MappedRegions::iterator it = _regions.upper_bound(addr);
    7.45 +  /* Obtain a region supporting the fault address. */
    7.46  
    7.47 -  if (it != _regions.begin())
    7.48 -    it--;
    7.49 -  else
    7.50 -  {
    7.51 -    printf("not mapped at %lx for pc %lx\n", addr, pc);
    7.52 -    return -L4_ENOMEM;
    7.53 -  }
    7.54 +  MemoryArea *r;
    7.55 +  long err = _area.find(addr, &r);
    7.56  
    7.57 -  MappedRegion &r = it->second;
    7.58 -
    7.59 -  if ((addr >= r.start) && (addr < r.start + r.size))
    7.60 +  if (!err)
    7.61    {
    7.62      address_t window_size = L4_PAGESIZE;
    7.63      address_t window_base = trunc(addr, window_size);
    7.64 -    address_t offset = addr - r.start;
    7.65 +    address_t offset = addr - r->area_start();
    7.66      address_t page_addr = trunc(addr, L4_PAGESIZE);
    7.67      address_t hot_spot = page_addr - window_base;
    7.68  
    7.69      /* Interact with the region's dataspace, specifying a receive window for a
    7.70         map operation. Here, a single page is specified. */
    7.71  
    7.72 -    client_Dataspace dataspace(r.ds);
    7.73 +    client_Dataspace dataspace(r->dataspace());
    7.74      l4_snd_fpage_t rw_region = {0, l4_fpage(window_base, L4_PAGESHIFT, 0)};
    7.75      map_flags_t map_flags = map_flags_for_fault(flags);
    7.76  
    7.77  #if DEBUG
    7.78      printf("window_base = %lx; window_size = %lx\n", window_base, window_size);
    7.79      printf("region = {%lx, {%lx, %d}}\n", rw_region.snd_base, l4_fpage_memaddr(rw_region.fpage), l4_fpage_size(rw_region.fpage));
    7.80 -    printf("map(%lx, %lx, %lx) -> %lx\n", offset, hot_spot, map_flags, r.ds);
    7.81 +    printf("map(%lx, %lx, %lx) -> %lx\n", offset, hot_spot, map_flags, r->dataspace());
    7.82  #endif
    7.83  
    7.84 -    long err = dataspace.map(offset, hot_spot, map_flags & r.flags, &rw_region);
    7.85 +    err = dataspace.map(offset, hot_spot, map_flags & r->flags(), &rw_region);
    7.86  
    7.87      /* Indicate an unspecified result, since the mapping should have taken
    7.88         place. */
    7.89 @@ -147,11 +135,9 @@
    7.90      return err;
    7.91    }
    7.92  
    7.93 -#if DEBUG
    7.94 -  printf("not mapped!\n");
    7.95 -#endif
    7.96 +  printf("not mapped at %lx for pc %lx\n", addr, pc);
    7.97  
    7.98 -  return -L4_ENOMEM;
    7.99 +  return err;
   7.100  }
   7.101  
   7.102  /* Attach a region for provision when page faults occur. This is required in
   7.103 @@ -162,12 +148,21 @@
   7.104                             l4_cap_idx_t ds, address_t offset,
   7.105                             unsigned char align)
   7.106  {
   7.107 -  long err = ExecPager::find(start, &size, flags, offset, align);
   7.108 +  // NOTE: Determine the purpose of offset.
   7.109 +
   7.110 +  (void) offset;
   7.111 +
   7.112 +  MemoryArea *area;
   7.113 +  long err = ExecPager::find(start, &size, flags, align, &area);
   7.114  
   7.115    if (!err)
   7.116    {
   7.117 -    MappedRegion r(*start, size, flags & L4RE_DS_F_RIGHTS_MASK, ds);
   7.118 -    add(r);
   7.119 +    MappedRegion r(*start, *start + size, flags & L4RE_DS_F_RIGHTS_MASK, ds);
   7.120 +    area->add(r);
   7.121 +
   7.122 +    /* Record dataspaces separately. */
   7.123 +
   7.124 +    _dataspaces.insert(ds);
   7.125    }
   7.126    else
   7.127      ipc_cap_free_um(ds);
   7.128 @@ -175,5 +170,34 @@
   7.129    return err;
   7.130  }
   7.131  
   7.132 +long InternalPager::reserve_area(address_t *start, address_t size,
   7.133 +                                 map_flags_t flags, unsigned char align)
   7.134 +{
   7.135 +  MemoryArea *area;
   7.136 +  long err = ExecPager::find(start, &size, flags, align, &area);
   7.137 +
   7.138 +  if (!err)
   7.139 +  {
   7.140 +    /* Add an object acting like a region but without any associated
   7.141 +       dataspace. */
   7.142 +
   7.143 +    if (flags & L4RE_RM_F_RESERVED)
   7.144 +    {
   7.145 +      ReservedMemoryArea r(*start, *start + size);
   7.146 +      area->add(r);
   7.147 +    }
   7.148 +
   7.149 +    /* Add an object permitting regions to be added within it. */
   7.150 +
   7.151 +    else
   7.152 +    {
   7.153 +      AvailableMemoryArea r(*start, *start + size);
   7.154 +      area->add(r);
   7.155 +    }
   7.156 +  }
   7.157 +
   7.158 +  return err;
   7.159 +}
   7.160 +
   7.161  /* vim: tabstop=2 expandtab shiftwidth=2
   7.162  */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/libexec/lib/src/memory_area.cc	Wed Mar 15 00:33:40 2023 +0100
     8.3 @@ -0,0 +1,434 @@
     8.4 +/*
     8.5 + * Memory area functionality.
     8.6 + *
     8.7 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
     8.8 + *
     8.9 + * This program is free software; you can redistribute it and/or
    8.10 + * modify it under the terms of the GNU General Public License as
    8.11 + * published by the Free Software Foundation; either version 2 of
    8.12 + * the License, or (at your option) any later version.
    8.13 + *
    8.14 + * This program is distributed in the hope that it will be useful,
    8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.17 + * GNU General Public License for more details.
    8.18 + *
    8.19 + * You should have received a copy of the GNU General Public License
    8.20 + * along with this program; if not, write to the Free Software
    8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
    8.22 + * Boston, MA  02110-1301, USA
    8.23 + */
    8.24 +
    8.25 +#include <l4/re/c/rm.h>
    8.26 +
    8.27 +#include <mem/memory_utils.h>
    8.28 +
    8.29 +#include "mapped_region.h"
    8.30 +
    8.31 +
    8.32 +
    8.33 +/* Copy an area. */
    8.34 +
    8.35 +MemoryArea *MemoryArea::copy()
    8.36 +{
    8.37 +  return new MemoryArea(_start, _end);
    8.38 +}
    8.39 +
    8.40 +/* In general, a region cannot support other regions. */
    8.41 +
    8.42 +long MemoryArea::add(MemoryArea &area)
    8.43 +{
    8.44 +  (void) area;
    8.45 +  return -L4_EPERM;
    8.46 +}
    8.47 +
    8.48 +long MemoryArea::remove(MemoryArea &area)
    8.49 +{
    8.50 +  (void) area;
    8.51 +  return -L4_EPERM;
    8.52 +}
    8.53 +
    8.54 +/* In general, a region supports a memory access within its bounds. */
    8.55 +
    8.56 +long MemoryArea::find(address_t addr, MemoryArea **area)
    8.57 +{
    8.58 +  if ((addr >= _start) && (addr < _end))
    8.59 +  {
    8.60 +    *area = this;
    8.61 +    return L4_EOK;
    8.62 +  }
    8.63 +  else
    8.64 +    return -L4_ENOMEM;
    8.65 +}
    8.66 +
    8.67 +/* In general, a region does not support the identification of a location for
    8.68 +   region insertion. */
    8.69 +
    8.70 +long MemoryArea::find(address_t *start, address_t *size, map_flags_t flags,
    8.71 +                      unsigned char align, MemoryArea **area)
    8.72 +{
    8.73 +  (void) start; (void) size; (void) flags; (void) align; (void) area;
    8.74 +  return -L4_ENOMEM;
    8.75 +}
    8.76 +
    8.77 +
    8.78 +
    8.79 +/* Copy a reserved area. */
    8.80 +
    8.81 +MemoryArea *ReservedMemoryArea::copy()
    8.82 +{
    8.83 +  return new ReservedMemoryArea(_start, _end);
    8.84 +}
    8.85 +
    8.86 +/* A reserved area does not support any memory access. */
    8.87 +
    8.88 +long ReservedMemoryArea::find(address_t addr, MemoryArea **area)
    8.89 +{
    8.90 +  (void) addr; (void) area;
    8.91 +  return -L4_ENOMEM;
    8.92 +}
    8.93 +
    8.94 +
    8.95 +
    8.96 +/* Discard all allocated areas. */
    8.97 +
    8.98 +AvailableMemoryArea::~AvailableMemoryArea()
    8.99 +{
   8.100 +  MemoryAreas::iterator it;
   8.101 +
   8.102 +  for (it = _allocated.begin(); it != _allocated.end(); it++)
   8.103 +    delete *it;
   8.104 +
   8.105 +  _allocated.clear();
   8.106 +}
   8.107 +
   8.108 +/* Copy an unused available memory area. */
   8.109 +
   8.110 +MemoryArea *AvailableMemoryArea::copy()
   8.111 +{
   8.112 +  return new AvailableMemoryArea(_start, _end);
   8.113 +}
   8.114 +
   8.115 +/* Add an area. */
   8.116 +
   8.117 +long AvailableMemoryArea::add(MemoryArea &area)
   8.118 +{
   8.119 +  MemoryArea *a = area.copy();
   8.120 +
   8.121 +  _areas[area.area_start()] = a;
   8.122 +  _allocated.insert(a);
   8.123 +
   8.124 +  return L4_EOK;
   8.125 +}
   8.126 +
   8.127 +/* Remove an area. */
   8.128 +
   8.129 +long AvailableMemoryArea::remove(MemoryArea &area)
   8.130 +{
   8.131 +  MemoryAreaMap::iterator it = _areas.find(area.area_start());
   8.132 +
   8.133 +  if (it != _areas.end())
   8.134 +  {
   8.135 +    _areas.erase(it);
   8.136 +
   8.137 +    MemoryAreas::iterator ita = _allocated.find(it->second);
   8.138 +
   8.139 +    if (ita != _allocated.end())
   8.140 +    {
   8.141 +      delete *ita;
   8.142 +      _allocated.erase(ita);
   8.143 +    }
   8.144 +  }
   8.145 +
   8.146 +  return L4_EOK;
   8.147 +}
   8.148 +
   8.149 +/* Find an region able to support a memory access. */
   8.150 +
   8.151 +long AvailableMemoryArea::find(address_t addr, MemoryArea **area)
   8.152 +{
   8.153 +  MemoryAreaMap::iterator it = _areas.upper_bound(addr);
   8.154 +
   8.155 +  /* Consider any area preceding or encompassing the desired address. */
   8.156 +
   8.157 +  if (it != _areas.begin())
   8.158 +  {
   8.159 +    it--;
   8.160 +
   8.161 +    /* Test whether the desired region start is encompassed by the preceding
   8.162 +       area. */
   8.163 +
   8.164 +    MemoryArea *r = it->second;
   8.165 +
   8.166 +    if (r->supports(addr))
   8.167 +      return r->find(addr, area);
   8.168 +  }
   8.169 +
   8.170 +  /* Otherwise, no area within this area supports the address. */
   8.171 +
   8.172 +  return -L4_ENOMEM;
   8.173 +}
   8.174 +
   8.175 +/* Find an area suitable for attaching a memory region. */
   8.176 +
   8.177 +long AvailableMemoryArea::find(address_t *start, address_t *size,
   8.178 +                               map_flags_t flags, unsigned char align,
   8.179 +                               MemoryArea **area)
   8.180 +{
   8.181 +  /* Obtain the alignment increment and a properly aligned size. */
   8.182 +
   8.183 +  address_t increment = 1UL << align;
   8.184 +  address_t region_size = round(*size, increment);
   8.185 +
   8.186 +  /* Align any desired location. */
   8.187 +
   8.188 +  address_t region_start = trunc(*start, increment);
   8.189 +
   8.190 +  /* Enforce a minimum address. */
   8.191 +
   8.192 +  if (region_start < _start)
   8.193 +    region_start = round(_start, increment);
   8.194 +
   8.195 +  /* Search for existing regions after the desired, conformant start address. */
   8.196 +
   8.197 +  MemoryAreaMap::iterator it = _areas.upper_bound(region_start);
   8.198 +
   8.199 +  /* Consider any area preceding or encompassing the desired address. */
   8.200 +
   8.201 +  if (it != _areas.begin())
   8.202 +  {
   8.203 +    MemoryAreaMap::iterator next = it;
   8.204 +
   8.205 +    /* Step back to the preceding area to get its details. */
   8.206 +
   8.207 +    it--;
   8.208 +    MemoryArea *pr = it->second;
   8.209 +    it = next;
   8.210 +
   8.211 +    /* Test whether the desired region start is encompassed by the preceding
   8.212 +       area. */
   8.213 +
   8.214 +    if (region_start < pr->area_end())
   8.215 +    {
   8.216 +      /* Where the preceding area is mapped or a reserved area, adjust the start
   8.217 +         of any search range. If an exact request is made for a region, deny the
   8.218 +         request. */
   8.219 +
   8.220 +      if (pr->is_mapped() || pr->is_reserved())
   8.221 +      {
   8.222 +        if (!(flags & L4RE_RM_F_SEARCH_ADDR))
   8.223 +          return -L4_ENOMEM;
   8.224 +
   8.225 +        region_start = round(pr->area_end(), increment);
   8.226 +      }
   8.227 +
   8.228 +      /* Where the preceding area is an area within which regions might be
   8.229 +         established, search within that area. */
   8.230 +
   8.231 +      else
   8.232 +        return pr->find(start, size, flags, align, area);
   8.233 +    }
   8.234 +  }
   8.235 +
   8.236 +  /* Consider the regions following the current region start candidate. */
   8.237 +
   8.238 +  MemoryArea *r;
   8.239 +
   8.240 +  while ((it != _areas.end()) && !(_end && ((region_start + region_size) > _end)))
   8.241 +  {
   8.242 +    r = it->second;
   8.243 +
   8.244 +    /* Obtain the limit of available space being considered. */
   8.245 +
   8.246 +    address_t end_limit = r->area_start();
   8.247 +
   8.248 +    /* Test if not enough space exists between the preceding region (or start of
   8.249 +       memory) and the current region. */
   8.250 +
   8.251 +    if ((region_start + region_size) > end_limit)
   8.252 +    {
   8.253 +      /* If an exact request is made for a region, deny the request. */
   8.254 +
   8.255 +      if (!(flags & L4RE_RM_F_SEARCH_ADDR))
   8.256 +        return -L4_ENOMEM;
   8.257 +
   8.258 +      /* Otherwise, investigate subsequent regions if not enough space exists
   8.259 +         between the preceding region (or start of memory) and the current
   8.260 +         region. */
   8.261 +
   8.262 +      region_start = round(r->area_end(), increment);
   8.263 +      it++;
   8.264 +    }
   8.265 +
   8.266 +    /* Otherwise, the region can be positioned. */
   8.267 +
   8.268 +    else
   8.269 +      break;
   8.270 +  }
   8.271 +
   8.272 +  /* Test for enough memory constrained by any predefined limit. */
   8.273 +
   8.274 +  if (_end && ((region_start + region_size) > _end))
   8.275 +    return -L4_ENOMEM;
   8.276 +
   8.277 +  /* Return the configured start and size. */
   8.278 +
   8.279 +  *start = region_start;
   8.280 +  *size = region_size;
   8.281 +
   8.282 +  /* Return the area within which any region will be added. */
   8.283 +
   8.284 +  *area = this;
   8.285 +
   8.286 +  return L4_EOK;
   8.287 +}
   8.288 +
   8.289 +/* Obtain a recursive iterator over a memory area. */
   8.290 +
   8.291 +AvailableMemoryArea::iterator AvailableMemoryArea::begin()
   8.292 +{
   8.293 +  return AvailableMemoryArea::iterator(_areas.begin(), _areas.end());
   8.294 +}
   8.295 +
   8.296 +AvailableMemoryArea::iterator AvailableMemoryArea::end()
   8.297 +{
   8.298 +  return AvailableMemoryArea::iterator(_areas.end(), _areas.end());
   8.299 +}
   8.300 +
   8.301 +MemoryAreaMap::iterator AvailableMemoryArea::areas_begin()
   8.302 +{
   8.303 +  return _areas.begin();
   8.304 +}
   8.305 +
   8.306 +MemoryAreaMap::iterator AvailableMemoryArea::areas_end()
   8.307 +{
   8.308 +  return _areas.end();
   8.309 +}
   8.310 +
   8.311 +
   8.312 +
   8.313 +/* Initialise a recursive iterator over a memory area. */
   8.314 +
   8.315 +AvailableMemoryArea::iterator::iterator(MemoryAreaMap::iterator it,
   8.316 +                                        MemoryAreaMap::iterator end)
   8.317 +{
   8.318 +  _iterators.push(it);
   8.319 +  _ends.push(end);
   8.320 +
   8.321 +  /* Descend to the first non-container area. */
   8.322 +
   8.323 +  descend_all();
   8.324 +}
   8.325 +
   8.326 +AvailableMemoryArea::iterator::iterator()
   8.327 +{
   8.328 +}
   8.329 +
   8.330 +/* Return the current underlying iterator. */
   8.331 +
   8.332 +MemoryAreaMap::iterator &AvailableMemoryArea::iterator::area_iterator()
   8.333 +{
   8.334 +  return _iterators.top();
   8.335 +}
   8.336 +
   8.337 +/* Return the end point of the current underlying iterator. */
   8.338 +
   8.339 +MemoryAreaMap::iterator &AvailableMemoryArea::iterator::area_end()
   8.340 +{
   8.341 +  return _ends.top();
   8.342 +}
   8.343 +
   8.344 +/* Return the current area. */
   8.345 +
   8.346 +MemoryArea *AvailableMemoryArea::iterator::operator *()
   8.347 +{
   8.348 +  return area_iterator()->second;
   8.349 +}
   8.350 +
   8.351 +/* Return whether this iterator references the same area as the other
   8.352 +   iterator. */
   8.353 +
   8.354 +bool AvailableMemoryArea::iterator::operator ==(AvailableMemoryArea::iterator other)
   8.355 +{
   8.356 +  return area_iterator() == other.area_iterator();
   8.357 +}
   8.358 +
   8.359 +/* Return whether this iterator references a different area to the other
   8.360 +   iterator. */
   8.361 +
   8.362 +bool AvailableMemoryArea::iterator::operator !=(AvailableMemoryArea::iterator other)
   8.363 +{
   8.364 +  return area_iterator() != other.area_iterator();
   8.365 +}
   8.366 +
   8.367 +/* Advance this iterator to the next area. */
   8.368 +
   8.369 +AvailableMemoryArea::iterator &AvailableMemoryArea::iterator::operator ++()
   8.370 +{
   8.371 +  /* Advance the area iterator. */
   8.372 +
   8.373 +  area_iterator()++;
   8.374 +
   8.375 +  /* Descend to the next non-container area. */
   8.376 +
   8.377 +  descend_all();
   8.378 +
   8.379 +  return *this;
   8.380 +}
   8.381 +
   8.382 +AvailableMemoryArea::iterator &AvailableMemoryArea::iterator::operator ++(int)
   8.383 +{
   8.384 +  return ++(*this);
   8.385 +}
   8.386 +
   8.387 +/* Advance this iterator to the next area not containing other areas. */
   8.388 +
   8.389 +void AvailableMemoryArea::iterator::descend_all()
   8.390 +{
   8.391 +  while ((area_iterator() != area_end()) || (_iterators.size() > 1))
   8.392 +  {
   8.393 +    /* Handle empty areas by ascending to refer to the area. */
   8.394 +
   8.395 +    if (area_iterator() == area_end())
   8.396 +    {
   8.397 +      ascend();
   8.398 +      break;
   8.399 +    }
   8.400 +
   8.401 +    MemoryArea *r = area_iterator()->second;
   8.402 +
   8.403 +    /* Handle areas by descending into them. */
   8.404 +
   8.405 +    if (!r->is_reserved() && !r->is_mapped())
   8.406 +      descend();
   8.407 +
   8.408 +    /* Yield any non-container areas. */
   8.409 +
   8.410 +    else
   8.411 +      break;
   8.412 +  }
   8.413 +}
   8.414 +
   8.415 +/* Ascend from a memory area. */
   8.416 +
   8.417 +void AvailableMemoryArea::iterator::ascend()
   8.418 +{
   8.419 +  _iterators.pop();
   8.420 +  _ends.pop();
   8.421 +}
   8.422 +
   8.423 +/* Descend into a memory area. */
   8.424 +
   8.425 +void AvailableMemoryArea::iterator::descend()
   8.426 +{
   8.427 +  AvailableMemoryArea *a = dynamic_cast<AvailableMemoryArea *>(area_iterator()->second);
   8.428 +
   8.429 +  if (a != NULL)
   8.430 +  {
   8.431 +    _iterators.push(a->areas_begin());
   8.432 +    _ends.push(a->areas_end());
   8.433 +  }
   8.434 +}
   8.435 +
   8.436 +/* vim: tabstop=2 expandtab shiftwidth=2
   8.437 +*/
     9.1 --- a/libexec/lib/src/pager.cc	Tue Mar 14 23:51:57 2023 +0100
     9.2 +++ b/libexec/lib/src/pager.cc	Wed Mar 15 00:33:40 2023 +0100
     9.3 @@ -20,7 +20,6 @@
     9.4   */
     9.5  
     9.6  #include <l4/re/env.h>
     9.7 -#include <l4/re/c/rm.h>
     9.8  
     9.9  #include <mem/memory_utils.h>
    9.10  
    9.11 @@ -31,7 +30,7 @@
    9.12  /* Initialise common functionality. */
    9.13  
    9.14  ExecPager::ExecPager(address_t start, address_t end)
    9.15 -: _start(start), _end(end)
    9.16 +: _area(start, end)
    9.17  {
    9.18  }
    9.19  
    9.20 @@ -43,118 +42,34 @@
    9.21  
    9.22  
    9.23  
    9.24 -/* Add a region to the pager. */
    9.25 +/* Add an area to the pager. */
    9.26  
    9.27 -void ExecPager::add(MappedRegion &region)
    9.28 +void ExecPager::add(MemoryArea &area)
    9.29  {
    9.30 -  _regions[region.start] = region;
    9.31 +  _area.add(area);
    9.32  }
    9.33  
    9.34 -/* Remove a region from the pager. */
    9.35 +/* Remove an area from the pager. */
    9.36  
    9.37 -void ExecPager::remove(MappedRegion &region)
    9.38 +void ExecPager::remove(MemoryArea &area)
    9.39  {
    9.40 -  _regions.erase(region.start);
    9.41 +  _area.remove(area);
    9.42  }
    9.43  
    9.44  
    9.45  
    9.46 -/* Attach a region for provision when page faults occur. */
    9.47 +/* Find an area suitable for attaching a memory region. */
    9.48  
    9.49  long ExecPager::find(address_t *start, address_t *size, map_flags_t flags,
    9.50 -                     address_t offset, unsigned char align)
    9.51 +                     unsigned char align, MemoryArea **area)
    9.52  {
    9.53    if (align < L4_PAGESHIFT)
    9.54      align = L4_PAGESHIFT;
    9.55  
    9.56 -  /* Obtain the alignment increment and a properly aligned size. */
    9.57 -
    9.58 -  address_t increment = 1UL << align;
    9.59 -  address_t region_size = round(*size, increment);
    9.60 -
    9.61 -  /* Either attempt to find an address for the specified region, starting from
    9.62 +  /* Attempt to find an address for the specified region, starting from
    9.63       any indicated address. */
    9.64  
    9.65 -  if (flags & L4RE_RM_F_SEARCH_ADDR)
    9.66 -  {
    9.67 -    /* Align any desired location. */
    9.68 -
    9.69 -    address_t region_start = trunc(*start, increment);
    9.70 -
    9.71 -    /* Enforce a minimum address. */
    9.72 -
    9.73 -    if (region_start < _start)
    9.74 -      region_start = round(_start, increment);
    9.75 -
    9.76 -    /* Search for existing regions after the desired, conformant address. */
    9.77 -
    9.78 -    MappedRegions::iterator it = _regions.upper_bound(region_start);
    9.79 -
    9.80 -    /* Consider any region preceding or encompassing the desired address. */
    9.81 -
    9.82 -    if (it != _regions.begin())
    9.83 -    {
    9.84 -      MappedRegions::iterator next = it;
    9.85 -
    9.86 -      /* Step back to the preceding region to get its details. */
    9.87 -
    9.88 -      it--;
    9.89 -      MappedRegion &pr = it->second;
    9.90 -      address_t previous_end = pr.start + pr.size;
    9.91 -      it = next;
    9.92 -
    9.93 -      /* The preceding region may displace the desired region location if it
    9.94 -         is encompassed by the region. */
    9.95 -
    9.96 -      if (region_start < previous_end)
    9.97 -        region_start = round(previous_end, increment);
    9.98 -    }
    9.99 -
   9.100 -    /* Consider the regions following the current region start candidate. */
   9.101 -
   9.102 -    while ((it != _regions.end()) && !(_end && ((region_start + region_size) > _end)))
   9.103 -    {
   9.104 -      MappedRegion &r = it->second;
   9.105 -
   9.106 -      /* Obtain the limit of available space being considered. */
   9.107 -
   9.108 -      address_t end_limit = r.start;
   9.109 -
   9.110 -      /* Investigate subsequent regions if not enough space exists between the
   9.111 -         preceding region (or start of memory) and the current region. */
   9.112 -
   9.113 -      if ((region_start + region_size) > end_limit)
   9.114 -      {
   9.115 -        region_start = round(r.start + r.size, increment);
   9.116 -        it++;
   9.117 -      }
   9.118 -
   9.119 -      /* Otherwise, the region can be positioned. */
   9.120 -
   9.121 -      else
   9.122 -        break;
   9.123 -    }
   9.124 -
   9.125 -    /* Test for enough memory constrained by any predefined limit. */
   9.126 -
   9.127 -    if (_end && ((region_start + region_size) > _end))
   9.128 -      return -L4_ENOMEM;
   9.129 -
   9.130 -    /* Return the configured start and size. */
   9.131 -
   9.132 -    *start = region_start;
   9.133 -    *size = region_size;
   9.134 -    return L4_EOK;
   9.135 -  }
   9.136 -
   9.137 -  /* Or attempt to add the specified region at a specific address. */
   9.138 -
   9.139 -  else
   9.140 -  {
   9.141 -    // NOTE: To be implemented.
   9.142 -
   9.143 -    return -L4_ENOMEM;
   9.144 -  }
   9.145 +  return _area.find(start, size, flags, align, area);
   9.146  }
   9.147  
   9.148  /* vim: tabstop=2 expandtab shiftwidth=2
    10.1 --- a/libexec/lib/src/segment.cc	Tue Mar 14 23:51:57 2023 +0100
    10.2 +++ b/libexec/lib/src/segment.cc	Wed Mar 15 00:33:40 2023 +0100
    10.3 @@ -141,7 +141,8 @@
    10.4  
    10.5  MappedRegion &Segment::region()
    10.6  {
    10.7 -  _region = MappedRegion(_region_base, _region_allocated_size, region_flags(), _ds, (l4_addr_t) _buf);
    10.8 +  _region = MappedRegion(_region_base, _region_base + _region_allocated_size,
    10.9 +                         region_flags(), _ds, (l4_addr_t) _buf);
   10.10    return _region;
   10.11  }
   10.12  
    11.1 --- a/libexec/rm/region_mapper.cc	Tue Mar 14 23:51:57 2023 +0100
    11.2 +++ b/libexec/rm/region_mapper.cc	Wed Mar 15 00:33:40 2023 +0100
    11.3 @@ -57,8 +57,8 @@
    11.4  
    11.5    for (; region && (region->ds != L4_INVALID_CAP); region++)
    11.6    {
    11.7 -    printf("Adding region: {%lx, %llx, %lx, %lx}\n", region->start, region->size, region->flags, region->ds);
    11.8 -    MappedRegion r(region->start, region->size, region->flags, region->ds);
    11.9 +    printf("Adding region: {%lx, %llx, %lx, %lx}\n", region->start, region->start + region->size, region->flags, region->ds);
   11.10 +    MappedRegion r(region->start, region->start + region->size, region->flags, region->ds);
   11.11      exec_pager.add(r);
   11.12    }
   11.13