1.1 --- a/libexec/lib/src/pager.cc Sat Oct 01 16:53:23 2022 +0200
1.2 +++ b/libexec/lib/src/pager.cc Sat Oct 01 16:58:16 2022 +0200
1.3 @@ -1,5 +1,5 @@
1.4 /*
1.5 - * A system pager interface.
1.6 + * Common system pager functionality.
1.7 *
1.8 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 @@ -19,15 +19,132 @@
1.11 * Boston, MA 02110-1301, USA
1.12 */
1.13
1.14 +#include <l4/re/env.h>
1.15 +#include <l4/re/c/rm.h>
1.16 +
1.17 +#include <mem/memory_utils.h>
1.18 +
1.19 #include "pager.h"
1.20
1.21
1.22
1.23 +/* Initialise common functionality. */
1.24 +
1.25 +ExecPager::ExecPager(address_t start, address_t end)
1.26 +: _start(start), _end(end)
1.27 +{
1.28 +}
1.29 +
1.30 /* Necessary virtual destructor. */
1.31
1.32 ExecPager::~ExecPager()
1.33 {
1.34 }
1.35
1.36 +/* Add a region to the pager. */
1.37 +
1.38 +void ExecPager::add(MappedRegion ®ion)
1.39 +{
1.40 + _regions[region.start] = region;
1.41 +}
1.42 +
1.43 +/* Attach a region for provision when page faults occur. */
1.44 +
1.45 +long ExecPager::find(address_t *start, address_t *size, map_flags_t flags,
1.46 + address_t offset, unsigned char align)
1.47 +{
1.48 + if (align < L4_PAGESHIFT)
1.49 + align = L4_PAGESHIFT;
1.50 +
1.51 + /* Obtain the alignment increment and a properly aligned size. */
1.52 +
1.53 + address_t increment = 1UL << align;
1.54 + address_t region_size = round(*size, increment);
1.55 +
1.56 + /* Either attempt to find an address for the specified region, starting from
1.57 + any indicated address. */
1.58 +
1.59 + if (flags & L4RE_RM_F_SEARCH_ADDR)
1.60 + {
1.61 + /* Align any desired location. */
1.62 +
1.63 + address_t region_start = trunc(*start, increment);
1.64 +
1.65 + /* Enforce a minimum address. */
1.66 +
1.67 + if (region_start < _start)
1.68 + region_start = round(_start, increment);
1.69 +
1.70 + /* Search for existing regions after the desired, conformant address. */
1.71 +
1.72 + MappedRegions::iterator it = _regions.upper_bound(region_start);
1.73 +
1.74 + /* Consider any region preceding or encompassing the desired address. */
1.75 +
1.76 + if (it != _regions.begin())
1.77 + {
1.78 + MappedRegions::iterator next = it;
1.79 +
1.80 + /* Step back to the preceding region to get its details. */
1.81 +
1.82 + it--;
1.83 + MappedRegion &pr = it->second;
1.84 + address_t previous_end = pr.start + pr.size;
1.85 + it = next;
1.86 +
1.87 + /* The preceding region may displace the desired region location if it
1.88 + is encompassed by the region. */
1.89 +
1.90 + if (region_start < previous_end)
1.91 + region_start = round(previous_end, increment);
1.92 + }
1.93 +
1.94 + /* Consider the regions following the current region start candidate. */
1.95 +
1.96 + while ((it != _regions.end()) && !(_end && ((region_start + region_size) > _end)))
1.97 + {
1.98 + MappedRegion &r = it->second;
1.99 +
1.100 + /* Obtain the limit of available space being considered. */
1.101 +
1.102 + address_t end_limit = r.start;
1.103 +
1.104 + /* Investigate subsequent regions if not enough space exists between the
1.105 + preceding region (or start of memory) and the current region. */
1.106 +
1.107 + if ((region_start + region_size) > end_limit)
1.108 + {
1.109 + region_start = round(r.start + r.size, increment);
1.110 + it++;
1.111 + }
1.112 +
1.113 + /* Otherwise, the region can be positioned. */
1.114 +
1.115 + else
1.116 + break;
1.117 + }
1.118 +
1.119 + /* Test for enough memory constrained by any predefined limit. */
1.120 +
1.121 + if (_end && ((region_start + region_size) > _end))
1.122 + return -L4_ENOMEM;
1.123 +
1.124 + /* Return the configured start and size. */
1.125 +
1.126 + *start = region_start;
1.127 + *size = region_size;
1.128 + return L4_EOK;
1.129 + }
1.130 +
1.131 + /* Or attempt to add the specified region at a specific address. */
1.132 +
1.133 + else
1.134 + {
1.135 + // NOTE: To be implemented.
1.136 +
1.137 + return -L4_ENOMEM;
1.138 + }
1.139 +}
1.140 +
1.141 /* vim: tabstop=2 expandtab shiftwidth=2
1.142 */