1.1 --- a/libexec/include/exec/external_pager.h Sat Oct 01 16:53:23 2022 +0200
1.2 +++ b/libexec/include/exec/external_pager.h Sat Oct 01 16:58:16 2022 +0200
1.3 @@ -21,28 +21,16 @@
1.4
1.5 #pragma once
1.6
1.7 -#include <map>
1.8 -
1.9 -#include <exec/mapped_region.h>
1.10 #include <exec/pager.h>
1.11
1.12
1.13
1.14 -/* Collection types. */
1.15 -
1.16 -typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
1.17 -
1.18 -
1.19 -
1.20 /* A simple system pager also acting as a region mapper. */
1.21
1.22 class ExternalPager : public ExecPager
1.23 {
1.24 -protected:
1.25 - MappedRegions _regions;
1.26 -
1.27 public:
1.28 - virtual void add(MappedRegion ®ion);
1.29 + explicit ExternalPager(address_t start = 0, address_t end = 0);
1.30
1.31 /* Notification methods, implementing PagerObject. */
1.32
1.33 @@ -56,7 +44,6 @@
1.34
1.35 virtual long attach(address_t *start, address_t size, map_flags_t flags,
1.36 l4_cap_idx_t ds, address_t offset, unsigned char align);
1.37 -
1.38 };
1.39
1.40 /* vim: tabstop=2 expandtab shiftwidth=2
2.1 --- a/libexec/include/exec/internal_pager.h Sat Oct 01 16:53:23 2022 +0200
2.2 +++ b/libexec/include/exec/internal_pager.h Sat Oct 01 16:58:16 2022 +0200
2.3 @@ -21,29 +21,16 @@
2.4
2.5 #pragma once
2.6
2.7 -#include <map>
2.8 -
2.9 -#include <exec/common.h>
2.10 #include <exec/pager.h>
2.11
2.12
2.13
2.14 -/* Collection types. */
2.15 -
2.16 -typedef std::map<l4_addr_t, struct exec_region> ExecRegions;
2.17 -typedef struct exec_region ExecRegion;
2.18 -
2.19 -
2.20 -
2.21 /* A simple system pager also acting as a region mapper. */
2.22
2.23 class InternalPager : public ExecPager
2.24 {
2.25 -protected:
2.26 - ExecRegions _regions;
2.27 -
2.28 public:
2.29 - virtual void add(ExecRegion ®ion);
2.30 + explicit InternalPager(address_t start = 0, address_t end = 0);
2.31
2.32 /* Notification methods, implementing PagerObject. */
2.33
2.34 @@ -57,7 +44,6 @@
2.35
2.36 virtual long attach(address_t *start, address_t size, map_flags_t flags,
2.37 l4_cap_idx_t ds, address_t offset, unsigned char align);
2.38 -
2.39 };
2.40
2.41 /* vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/libexec/include/exec/mapped_region.h Sat Oct 01 16:53:23 2022 +0200
3.2 +++ b/libexec/include/exec/mapped_region.h Sat Oct 01 16:58:16 2022 +0200
3.3 @@ -35,18 +35,18 @@
3.4 l4_addr_t start;
3.5 offset_t size;
3.6 l4_umword_t flags;
3.7 - l4_addr_t map_start;
3.8 l4_cap_idx_t ds;
3.9 + l4_addr_t ds_start;
3.10
3.11 explicit MappedRegion()
3.12 - : start(0), size(0), flags(0), map_start(0), ds(L4_INVALID_CAP)
3.13 + : start(0), size(0), flags(0), ds(L4_INVALID_CAP), ds_start(0)
3.14 {
3.15 }
3.16
3.17 explicit MappedRegion(l4_addr_t start, l4_addr_t size,
3.18 - l4_umword_t flags, l4_addr_t map_start,
3.19 - l4_cap_idx_t ds = L4_INVALID_CAP)
3.20 - : start(start), size(size), flags(flags), map_start(map_start), ds(ds)
3.21 + l4_umword_t flags, l4_cap_idx_t ds = L4_INVALID_CAP,
3.22 + l4_addr_t ds_start = 0)
3.23 + : start(start), size(size), flags(flags), ds(ds), ds_start(ds_start)
3.24 {
3.25 }
3.26 };
4.1 --- a/libexec/include/exec/pager.h Sat Oct 01 16:53:23 2022 +0200
4.2 +++ b/libexec/include/exec/pager.h Sat Oct 01 16:58:16 2022 +0200
4.3 @@ -1,5 +1,5 @@
4.4 /*
4.5 - * A system pager interface.
4.6 + * Common system pager functionality.
4.7 *
4.8 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
4.9 *
4.10 @@ -21,30 +21,48 @@
4.11
4.12 #pragma once
4.13
4.14 +#include <map>
4.15 +
4.16 +#include <exec/mapped_region.h>
4.17 +
4.18 #include "pager_object_interface.h"
4.19
4.20
4.21
4.22 +/* Collection types. */
4.23 +
4.24 +typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
4.25 +
4.26 +
4.27 +
4.28 /* A simple system pager also acting as a region mapper. */
4.29
4.30 class ExecPager : public PagerObject
4.31 {
4.32 +protected:
4.33 + address_t _start, _end;
4.34 +
4.35 + /* Region manager/mapper functionality. */
4.36 +
4.37 + MappedRegions _regions;
4.38 +
4.39 + virtual long find(address_t *start, address_t *size, map_flags_t flags,
4.40 + address_t offset, unsigned char align);
4.41 +
4.42 public:
4.43 + explicit ExecPager(address_t start = 0, address_t end = 0);
4.44 +
4.45 virtual ~ExecPager();
4.46
4.47 + virtual void add(MappedRegion ®ion);
4.48 +
4.49 /* Notification methods. */
4.50
4.51 virtual long exception(l4_exc_regs_t regs,
4.52 l4_snd_fpage_t *region) = 0;
4.53
4.54 virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
4.55 - l4_snd_fpage_t *region);
4.56 -
4.57 - /* Region manager/mapper methods. */
4.58 -
4.59 - virtual long attach(address_t *start, address_t size, map_flags_t flags,
4.60 - l4_cap_idx_t ds, address_t offset, unsigned char align);
4.61 -
4.62 + l4_snd_fpage_t *region) = 0;
4.63 };
4.64
4.65 /* vim: tabstop=2 expandtab shiftwidth=2
5.1 --- a/libexec/lib/src/external_pager.cc Sat Oct 01 16:53:23 2022 +0200
5.2 +++ b/libexec/lib/src/external_pager.cc Sat Oct 01 16:58:16 2022 +0200
5.3 @@ -20,26 +20,26 @@
5.4 */
5.5
5.6 #include <l4/re/env.h>
5.7 -#include <l4/sys/err.h>
5.8 #include <l4/util/util.h>
5.9
5.10 #include <ipc/mem_ipc.h>
5.11 #include <mem/memory_utils.h>
5.12
5.13 #include <stdio.h>
5.14 -#include <string.h>
5.15
5.16 #include "external_pager.h"
5.17
5.18
5.19
5.20 +#define DEBUG 0
5.21 +
5.22 +
5.23 +
5.24 /* A simple system pager also acting as a region mapper. */
5.25
5.26 -/* Add a region to the pager. */
5.27 -
5.28 -void ExternalPager::add(MappedRegion ®ion)
5.29 +ExternalPager::ExternalPager(address_t start, address_t end)
5.30 +: ExecPager(start, end)
5.31 {
5.32 - _regions[region.map_start] = region;
5.33 }
5.34
5.35 /* Handle a general exception. */
5.36 @@ -48,43 +48,16 @@
5.37 {
5.38 (void) region;
5.39
5.40 - printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
5.41 + printf("ExternalPager::exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
5.42
5.43 -#if 0
5.44 - printf("r15 = %lx\n", regs.r15);
5.45 - printf("r14 = %lx\n", regs.r14);
5.46 - printf("r13 = %lx\n", regs.r13);
5.47 - printf("r12 = %lx\n", regs.r12);
5.48 - printf("r11 = %lx\n", regs.r11);
5.49 - printf("r10 = %lx\n", regs.r10);
5.50 - printf("r9 = %lx\n", regs.r9);
5.51 - printf("r8 = %lx\n", regs.r8);
5.52 - printf("rdi = %lx\n", regs.rdi);
5.53 - printf("rsi = %lx\n", regs.rsi);
5.54 - printf("rbp = %lx\n", regs.rbp);
5.55 - printf("pfa = %lx\n", regs.pfa);
5.56 - printf("rbx = %lx\n", regs.rbx);
5.57 - printf("rdx = %lx\n", regs.rdx);
5.58 - printf("rcx = %lx\n", regs.rcx);
5.59 - printf("rax = %lx\n", regs.rax);
5.60 - printf("trapno = %lx\n", regs.trapno);
5.61 - printf("err = %lx\n", regs.err);
5.62 - printf("ip = %lx\n", regs.ip);
5.63 - printf("flags = %lx\n", regs.flags);
5.64 - printf("sp = %lx\n", regs.sp);
5.65 - printf("ss = %lx\n", regs.ss);
5.66 - printf("fs_base = %lx\n", regs.fs_base);
5.67 - printf("gs_base = %lx\n", regs.gs_base);
5.68 -#endif
5.69 -
5.70 +#if DEBUG
5.71 while (1)
5.72 l4_sleep_forever();
5.73 +#endif
5.74
5.75 return L4_EOK;
5.76 }
5.77
5.78 -#define DEBUG 0
5.79 -
5.80 /* Handle a page fault using any configured regions. */
5.81
5.82 long ExternalPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
5.83 @@ -101,13 +74,13 @@
5.84 it--;
5.85 else
5.86 {
5.87 - printf("not mapped!\n");
5.88 + printf("not mapped at %lx for pc %lx\n", addr, pc);
5.89 return -L4_ENOMEM;
5.90 }
5.91
5.92 MappedRegion &r = it->second;
5.93
5.94 - if ((addr >= r.map_start) && (addr < r.map_start + r.size))
5.95 + if ((addr >= r.start) && (addr < r.start + r.size))
5.96 {
5.97 l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
5.98 map_flags_t map_flags = (flags & 4 ? L4RE_DS_F_RX : 0) | (flags & 2 ? L4RE_DS_F_W : 0) | (flags & 1 ? L4RE_DS_F_R : 0);
5.99 @@ -115,14 +88,14 @@
5.100 if (!map_flags)
5.101 map_flags = L4RE_DS_F_R;
5.102
5.103 - region->fpage = l4_fpage(r.start + (page_addr - r.map_start), L4_PAGESHIFT, map_flags & r.flags);
5.104 + region->fpage = l4_fpage(r.ds_start + (page_addr - r.start), L4_PAGESHIFT, map_flags & r.flags);
5.105 region->snd_base = page_addr;
5.106
5.107 #if DEBUG
5.108 printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x ds %lx\n",
5.109 - r.map_start, region->snd_base,
5.110 - r.start, l4_fpage_memaddr(region->fpage),
5.111 - addr - r.map_start,
5.112 + r.start, region->snd_base,
5.113 + r.ds_start, l4_fpage_memaddr(region->fpage),
5.114 + addr - r.start,
5.115 l4_fpage_size(region->fpage),
5.116 l4_fpage_rights(region->fpage),
5.117 r.ds);
5.118 @@ -130,15 +103,15 @@
5.119 printf("%lx -> ", addr);
5.120
5.121 for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
5.122 - printf("%02x", *((unsigned char *)(r.start + (addr - r.map_start) + i)));
5.123 + printf("%02x", *((unsigned char *)(r.ds_start + (addr - r.start) + i)));
5.124
5.125 printf("\n");
5.126 #endif
5.127
5.128 if (r.flags & L4RE_RM_F_W)
5.129 - l4_touch_rw((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.130 + l4_touch_rw((const void *) (r.ds_start + (page_addr - r.start)), L4_PAGESIZE);
5.131 else
5.132 - l4_touch_ro((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.133 + l4_touch_ro((const void *) (r.ds_start + (page_addr - r.start)), L4_PAGESIZE);
5.134
5.135 return L4_EOK;
5.136 }
5.137 @@ -158,109 +131,28 @@
5.138 l4_cap_idx_t ds, address_t offset,
5.139 unsigned char align)
5.140 {
5.141 -#if DEBUG
5.142 - printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
5.143 -#endif
5.144 -
5.145 - if (align < L4_PAGESHIFT)
5.146 - align = L4_PAGESHIFT;
5.147 -
5.148 - address_t increment = 1UL << align;
5.149 - address_t region_size = round(size, increment);
5.150 -
5.151 - /* Either attempt to find an address for the specified region, starting from
5.152 - any indicated address. */
5.153 -
5.154 - if (flags & L4RE_RM_F_SEARCH_ADDR)
5.155 - {
5.156 - address_t region_start = trunc(*start, increment);
5.157 - MappedRegions::iterator it = _regions.upper_bound(*start);
5.158 -
5.159 - if (!region_start)
5.160 - region_start += increment;
5.161 -
5.162 -#if DEBUG
5.163 - printf("-> search from %lx -> %lx...\n", *start, region_start);
5.164 -#endif
5.165 -
5.166 - /* Before last known region. */
5.167 + long err = find(start, &size, flags, offset, align);
5.168
5.169 - while (it != _regions.end())
5.170 - {
5.171 - MappedRegions::iterator next = it;
5.172 - MappedRegion &r = it->second;
5.173 - address_t start_limit;
5.174 - address_t end_limit = r.map_start;
5.175 -
5.176 - /* Consider any preceding region. If no such region exists, choose an
5.177 - address at the start of memory. */
5.178 -
5.179 - if (it == _regions.begin())
5.180 - start_limit = L4_PAGESIZE;
5.181 - else
5.182 - {
5.183 - it--;
5.184 - MappedRegion &pr = it->second;
5.185 - start_limit = pr.map_start + pr.size;
5.186 - it = next;
5.187 - }
5.188 -
5.189 - /* Test against the limits. */
5.190 -
5.191 - if (region_start < start_limit)
5.192 - region_start = round(start_limit, increment);
5.193 -
5.194 - /* Investigate subsequent regions if not enough space exists between the
5.195 - preceding region (or start of memory) and the current region. */
5.196 -
5.197 - if ((region_start + region_size) > end_limit)
5.198 - {
5.199 - it++;
5.200 - if (it == _regions.end())
5.201 - return -L4_ENOMEM;
5.202 - }
5.203 - else
5.204 - break;
5.205 - }
5.206 -
5.207 + if (!err)
5.208 + {
5.209 /* Attach the provided dataspace.
5.210 NOTE: This is only done in this implementation to support the paging
5.211 mechanism. In a region mapper residing within the actual task, the
5.212 dataspace's map operation would be invoked to obtain mappings. */
5.213
5.214 l4_addr_t ds_start;
5.215 -
5.216 - long err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
5.217 + err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
5.218
5.219 if (err)
5.220 return err;
5.221
5.222 l4_touch_rw((const void *) ds_start, size);
5.223
5.224 -#if DEBUG
5.225 - printf("-> added region at %lx size %ld (%d) from %lx ds %lx\n", region_start, region_size, page_order(region_size), ds_start, ds);
5.226 -#endif
5.227 -
5.228 - MappedRegion r(ds_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, region_start, ds);
5.229 -
5.230 + MappedRegion r(*start, size, flags & L4RE_DS_F_RIGHTS_MASK, ds, ds_start);
5.231 add(r);
5.232 -
5.233 - *start = region_start;
5.234 - return L4_EOK;
5.235 }
5.236
5.237 - /* Or attempt to add the specified region at a specific address. */
5.238 -
5.239 - else
5.240 - {
5.241 - // NOTE: To be implemented.
5.242 -
5.243 -#if DEBUG
5.244 - printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
5.245 -#endif
5.246 -
5.247 - return -L4_ENOMEM;
5.248 - }
5.249 + return err;
5.250 }
5.251
5.252 /* vim: tabstop=2 expandtab shiftwidth=2
6.1 --- a/libexec/lib/src/internal_pager.cc Sat Oct 01 16:53:23 2022 +0200
6.2 +++ b/libexec/lib/src/internal_pager.cc Sat Oct 01 16:58:16 2022 +0200
6.3 @@ -20,27 +20,26 @@
6.4 */
6.5
6.6 #include <l4/re/env.h>
6.7 -#include <l4/sys/err.h>
6.8 -#include <l4/util/util.h>
6.9 +#include <l4/re/c/dataspace.h>
6.10
6.11 -#include <ipc/mem_ipc.h>
6.12 #include <mem/memory_utils.h>
6.13
6.14 #include <stdio.h>
6.15 -#include <string.h>
6.16
6.17 #include "dataspace_client.h"
6.18 #include "internal_pager.h"
6.19
6.20
6.21
6.22 +#define DEBUG 0
6.23 +
6.24 +
6.25 +
6.26 /* A simple system pager also acting as a region mapper. */
6.27
6.28 -/* Add a region to the pager. */
6.29 -
6.30 -void InternalPager::add(ExecRegion ®ion)
6.31 +InternalPager::InternalPager(address_t start, address_t end)
6.32 +: ExecPager(start, end)
6.33 {
6.34 - _regions[region.start] = region;
6.35 }
6.36
6.37 /* Handle a general exception. */
6.38 @@ -49,43 +48,16 @@
6.39 {
6.40 (void) region;
6.41
6.42 - printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
6.43 + printf("InternalPager::exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
6.44
6.45 -#if 0
6.46 - printf("r15 = %lx\n", regs.r15);
6.47 - printf("r14 = %lx\n", regs.r14);
6.48 - printf("r13 = %lx\n", regs.r13);
6.49 - printf("r12 = %lx\n", regs.r12);
6.50 - printf("r11 = %lx\n", regs.r11);
6.51 - printf("r10 = %lx\n", regs.r10);
6.52 - printf("r9 = %lx\n", regs.r9);
6.53 - printf("r8 = %lx\n", regs.r8);
6.54 - printf("rdi = %lx\n", regs.rdi);
6.55 - printf("rsi = %lx\n", regs.rsi);
6.56 - printf("rbp = %lx\n", regs.rbp);
6.57 - printf("pfa = %lx\n", regs.pfa);
6.58 - printf("rbx = %lx\n", regs.rbx);
6.59 - printf("rdx = %lx\n", regs.rdx);
6.60 - printf("rcx = %lx\n", regs.rcx);
6.61 - printf("rax = %lx\n", regs.rax);
6.62 - printf("trapno = %lx\n", regs.trapno);
6.63 - printf("err = %lx\n", regs.err);
6.64 - printf("ip = %lx\n", regs.ip);
6.65 - printf("flags = %lx\n", regs.flags);
6.66 - printf("sp = %lx\n", regs.sp);
6.67 - printf("ss = %lx\n", regs.ss);
6.68 - printf("fs_base = %lx\n", regs.fs_base);
6.69 - printf("gs_base = %lx\n", regs.gs_base);
6.70 -#endif
6.71 -
6.72 +#if DEBUG
6.73 while (1)
6.74 l4_sleep_forever();
6.75 +#endif
6.76
6.77 return L4_EOK;
6.78 }
6.79
6.80 -#define DEBUG 0
6.81 -
6.82 /* Handle a page fault using any configured regions. */
6.83
6.84 long InternalPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
6.85 @@ -94,19 +66,21 @@
6.86
6.87 #if DEBUG
6.88 printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
6.89 + l4_thread_regs_t *regs = l4_utcb_tcr();
6.90 + printf("regs = %p\n; regs->user[0] = %lx\n", regs, regs->user[0]);
6.91 #endif
6.92
6.93 - ExecRegions::iterator it = _regions.upper_bound(addr);
6.94 + MappedRegions::iterator it = _regions.upper_bound(addr);
6.95
6.96 if (it != _regions.begin())
6.97 it--;
6.98 else
6.99 {
6.100 - printf("not mapped!\n");
6.101 + printf("not mapped at %lx for pc %lx\n", addr, pc);
6.102 return -L4_ENOMEM;
6.103 }
6.104
6.105 - ExecRegion &r = it->second;
6.106 + MappedRegion &r = it->second;
6.107
6.108 if ((addr >= r.start) && (addr < r.start + r.size))
6.109 {
6.110 @@ -157,95 +131,15 @@
6.111 l4_cap_idx_t ds, address_t offset,
6.112 unsigned char align)
6.113 {
6.114 -#if DEBUG
6.115 - printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
6.116 -#endif
6.117 -
6.118 - if (align < L4_PAGESHIFT)
6.119 - align = L4_PAGESHIFT;
6.120 -
6.121 - address_t increment = 1UL << align;
6.122 - address_t region_size = round(size, increment);
6.123 -
6.124 - /* Either attempt to find an address for the specified region, starting from
6.125 - any indicated address. */
6.126 -
6.127 - if (flags & L4RE_RM_F_SEARCH_ADDR)
6.128 - {
6.129 - address_t region_start = trunc(*start, increment);
6.130 - ExecRegions::iterator it = _regions.upper_bound(*start);
6.131 -
6.132 - if (!region_start)
6.133 - region_start += increment;
6.134 -
6.135 -#if DEBUG
6.136 - printf("-> search from %lx -> %lx...\n", *start, region_start);
6.137 -#endif
6.138 -
6.139 - /* Before last known region. */
6.140 -
6.141 - while (it != _regions.end())
6.142 - {
6.143 - ExecRegions::iterator next = it;
6.144 - ExecRegion &r = it->second;
6.145 - address_t start_limit;
6.146 - address_t end_limit = r.start;
6.147 -
6.148 - /* Consider any preceding region. If no such region exists, choose an
6.149 - address at the start of memory. */
6.150 + long err = find(start, &size, flags, offset, align);
6.151
6.152 - if (it == _regions.begin())
6.153 - start_limit = L4_PAGESIZE;
6.154 - else
6.155 - {
6.156 - it--;
6.157 - ExecRegion &pr = it->second;
6.158 - start_limit = pr.start + pr.size;
6.159 - it = next;
6.160 - }
6.161 -
6.162 - /* Test against the limits. */
6.163 -
6.164 - if (region_start < start_limit)
6.165 - region_start = round(start_limit, increment);
6.166 -
6.167 - /* Investigate subsequent regions if not enough space exists between the
6.168 - preceding region (or start of memory) and the current region. */
6.169 -
6.170 - if ((region_start + region_size) > end_limit)
6.171 - {
6.172 - it++;
6.173 - if (it == _regions.end())
6.174 - return -L4_ENOMEM;
6.175 - }
6.176 - else
6.177 - break;
6.178 - }
6.179 -
6.180 -#if DEBUG
6.181 - printf("-> added region at %lx size %ld (%d) ds %lx\n", region_start, region_size, page_order(region_size), ds);
6.182 -#endif
6.183 -
6.184 - ExecRegion r = (ExecRegion) {region_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, ds};
6.185 -
6.186 + if (!err)
6.187 + {
6.188 + MappedRegion r(*start, size, flags & L4RE_DS_F_RIGHTS_MASK, ds);
6.189 add(r);
6.190 -
6.191 - *start = region_start;
6.192 - return L4_EOK;
6.193 }
6.194
6.195 - /* Or attempt to add the specified region at a specific address. */
6.196 -
6.197 - else
6.198 - {
6.199 - // NOTE: To be implemented.
6.200 -
6.201 -#if DEBUG
6.202 - printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
6.203 -#endif
6.204 -
6.205 - return -L4_ENOMEM;
6.206 - }
6.207 + return err;
6.208 }
6.209
6.210 /* vim: tabstop=2 expandtab shiftwidth=2
7.1 --- a/libexec/lib/src/pager.cc Sat Oct 01 16:53:23 2022 +0200
7.2 +++ b/libexec/lib/src/pager.cc Sat Oct 01 16:58:16 2022 +0200
7.3 @@ -1,5 +1,5 @@
7.4 /*
7.5 - * A system pager interface.
7.6 + * Common system pager functionality.
7.7 *
7.8 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
7.9 *
7.10 @@ -19,15 +19,132 @@
7.11 * Boston, MA 02110-1301, USA
7.12 */
7.13
7.14 +#include <l4/re/env.h>
7.15 +#include <l4/re/c/rm.h>
7.16 +
7.17 +#include <mem/memory_utils.h>
7.18 +
7.19 #include "pager.h"
7.20
7.21
7.22
7.23 +/* Initialise common functionality. */
7.24 +
7.25 +ExecPager::ExecPager(address_t start, address_t end)
7.26 +: _start(start), _end(end)
7.27 +{
7.28 +}
7.29 +
7.30 /* Necessary virtual destructor. */
7.31
7.32 ExecPager::~ExecPager()
7.33 {
7.34 }
7.35
7.36 +/* Add a region to the pager. */
7.37 +
7.38 +void ExecPager::add(MappedRegion ®ion)
7.39 +{
7.40 + _regions[region.start] = region;
7.41 +}
7.42 +
7.43 +/* Attach a region for provision when page faults occur. */
7.44 +
7.45 +long ExecPager::find(address_t *start, address_t *size, map_flags_t flags,
7.46 + address_t offset, unsigned char align)
7.47 +{
7.48 + if (align < L4_PAGESHIFT)
7.49 + align = L4_PAGESHIFT;
7.50 +
7.51 + /* Obtain the alignment increment and a properly aligned size. */
7.52 +
7.53 + address_t increment = 1UL << align;
7.54 + address_t region_size = round(*size, increment);
7.55 +
7.56 + /* Either attempt to find an address for the specified region, starting from
7.57 + any indicated address. */
7.58 +
7.59 + if (flags & L4RE_RM_F_SEARCH_ADDR)
7.60 + {
7.61 + /* Align any desired location. */
7.62 +
7.63 + address_t region_start = trunc(*start, increment);
7.64 +
7.65 + /* Enforce a minimum address. */
7.66 +
7.67 + if (region_start < _start)
7.68 + region_start = round(_start, increment);
7.69 +
7.70 + /* Search for existing regions after the desired, conformant address. */
7.71 +
7.72 + MappedRegions::iterator it = _regions.upper_bound(region_start);
7.73 +
7.74 + /* Consider any region preceding or encompassing the desired address. */
7.75 +
7.76 + if (it != _regions.begin())
7.77 + {
7.78 + MappedRegions::iterator next = it;
7.79 +
7.80 + /* Step back to the preceding region to get its details. */
7.81 +
7.82 + it--;
7.83 + MappedRegion &pr = it->second;
7.84 + address_t previous_end = pr.start + pr.size;
7.85 + it = next;
7.86 +
7.87 + /* The preceding region may displace the desired region location if it
7.88 + is encompassed by the region. */
7.89 +
7.90 + if (region_start < previous_end)
7.91 + region_start = round(previous_end, increment);
7.92 + }
7.93 +
7.94 + /* Consider the regions following the current region start candidate. */
7.95 +
7.96 + while ((it != _regions.end()) && !(_end && ((region_start + region_size) > _end)))
7.97 + {
7.98 + MappedRegion &r = it->second;
7.99 +
7.100 + /* Obtain the limit of available space being considered. */
7.101 +
7.102 + address_t end_limit = r.start;
7.103 +
7.104 + /* Investigate subsequent regions if not enough space exists between the
7.105 + preceding region (or start of memory) and the current region. */
7.106 +
7.107 + if ((region_start + region_size) > end_limit)
7.108 + {
7.109 + region_start = round(r.start + r.size, increment);
7.110 + it++;
7.111 + }
7.112 +
7.113 + /* Otherwise, the region can be positioned. */
7.114 +
7.115 + else
7.116 + break;
7.117 + }
7.118 +
7.119 + /* Test for enough memory constrained by any predefined limit. */
7.120 +
7.121 + if (_end && ((region_start + region_size) > _end))
7.122 + return -L4_ENOMEM;
7.123 +
7.124 + /* Return the configured start and size. */
7.125 +
7.126 + *start = region_start;
7.127 + *size = region_size;
7.128 + return L4_EOK;
7.129 + }
7.130 +
7.131 + /* Or attempt to add the specified region at a specific address. */
7.132 +
7.133 + else
7.134 + {
7.135 + // NOTE: To be implemented.
7.136 +
7.137 + return -L4_ENOMEM;
7.138 + }
7.139 +}
7.140 +
7.141 /* vim: tabstop=2 expandtab shiftwidth=2
7.142 */
8.1 --- a/libexec/lib/src/segment.cc Sat Oct 01 16:53:23 2022 +0200
8.2 +++ b/libexec/lib/src/segment.cc Sat Oct 01 16:58:16 2022 +0200
8.3 @@ -121,7 +121,7 @@
8.4
8.5 MappedRegion &Segment::region()
8.6 {
8.7 - _region = MappedRegion((l4_addr_t) _buf, _region_allocated_size, region_flags(), _region_base, _ds);
8.8 + _region = MappedRegion(_region_base, _region_allocated_size, region_flags(), _ds, (l4_addr_t) _buf);
8.9 return _region;
8.10 }
8.11
9.1 --- a/libexec/rm/region_mapper.cc Sat Oct 01 16:53:23 2022 +0200
9.2 +++ b/libexec/rm/region_mapper.cc Sat Oct 01 16:58:16 2022 +0200
9.3 @@ -30,7 +30,10 @@
9.4
9.5
9.6
9.7 -static InternalPager exec_pager;
9.8 +/* Initialise a pager for programs, reserving space below the allocated regions
9.9 + for the region mapper itself. */
9.10 +
9.11 +static InternalPager exec_pager(L4_PAGESIZE * 10);
9.12
9.13
9.14
9.15 @@ -56,7 +59,8 @@
9.16 for (; region && (region->ds != L4_INVALID_CAP); region++)
9.17 {
9.18 printf("Adding region: {%lx, %lx, %lx, %lx}\n", region->start, region->size, region->flags, region->ds);
9.19 - exec_pager.add(*region);
9.20 + MappedRegion r(region->start, region->size, region->flags, region->ds);
9.21 + exec_pager.add(r);
9.22 }
9.23
9.24 /* Start the pager. */
10.1 --- a/tests/dstest_exec.cc Sat Oct 01 16:53:23 2022 +0200
10.2 +++ b/tests/dstest_exec.cc Sat Oct 01 16:58:16 2022 +0200
10.3 @@ -40,9 +40,12 @@
10.4
10.5
10.6
10.7 -/* External system-level pager for the region mapper in a created task. */
10.8 +/* External system-level pager for the region mapper in a created task. The
10.9 + allocated regions requested by the region mapper are constrained to an area
10.10 + of memory that must not overlap with the area reserved for the program being
10.11 + run. */
10.12
10.13 -static ExternalPager exec_pager;
10.14 +static ExternalPager exec_pager(0, 10 * L4_PAGESIZE);
10.15
10.16 static const offset_t initial_stack_size = 16 * L4_PAGESIZE;
10.17