1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libexec/include/exec/external_pager.h Sun Jun 12 18:56:25 2022 +0200
1.3 @@ -0,0 +1,63 @@
1.4 +/*
1.5 + * A system pager implementation residing in a separate task.
1.6 + *
1.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#pragma once
1.26 +
1.27 +#include <map>
1.28 +
1.29 +#include <exec/mapped_region.h>
1.30 +#include <exec/pager.h>
1.31 +
1.32 +
1.33 +
1.34 +/* Collection types. */
1.35 +
1.36 +typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
1.37 +
1.38 +
1.39 +
1.40 +/* A simple system pager also acting as a region mapper. */
1.41 +
1.42 +class ExternalPager : public ExecPager
1.43 +{
1.44 +protected:
1.45 + MappedRegions _regions;
1.46 +
1.47 +public:
1.48 + virtual void add(MappedRegion ®ion);
1.49 +
1.50 + /* Notification methods, implementing PagerObject. */
1.51 +
1.52 + virtual long exception(l4_exc_regs_t regs,
1.53 + l4_snd_fpage_t *region);
1.54 +
1.55 + virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
1.56 + l4_snd_fpage_t *region);
1.57 +
1.58 + /* Region manager/mapper methods. */
1.59 +
1.60 + virtual long attach(address_t *start, offset_t size, map_flags_t flags,
1.61 + l4_cap_idx_t ds, address_t offset, unsigned char align);
1.62 +
1.63 +};
1.64 +
1.65 +/* vim: tabstop=2 expandtab shiftwidth=2
1.66 +*/
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/libexec/include/exec/internal_pager.h Sun Jun 12 18:56:25 2022 +0200
2.3 @@ -0,0 +1,64 @@
2.4 +/*
2.5 + * A system pager implementation residing in the same task as a program.
2.6 + *
2.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
2.8 + *
2.9 + * This program is free software; you can redistribute it and/or
2.10 + * modify it under the terms of the GNU General Public License as
2.11 + * published by the Free Software Foundation; either version 2 of
2.12 + * the License, or (at your option) any later version.
2.13 + *
2.14 + * This program is distributed in the hope that it will be useful,
2.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.17 + * GNU General Public License for more details.
2.18 + *
2.19 + * You should have received a copy of the GNU General Public License
2.20 + * along with this program; if not, write to the Free Software
2.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
2.22 + * Boston, MA 02110-1301, USA
2.23 + */
2.24 +
2.25 +#pragma once
2.26 +
2.27 +#include <map>
2.28 +
2.29 +#include <exec/common.h>
2.30 +#include <exec/pager.h>
2.31 +
2.32 +
2.33 +
2.34 +/* Collection types. */
2.35 +
2.36 +typedef std::map<l4_addr_t, struct exec_region> ExecRegions;
2.37 +typedef struct exec_region ExecRegion;
2.38 +
2.39 +
2.40 +
2.41 +/* A simple system pager also acting as a region mapper. */
2.42 +
2.43 +class InternalPager : public ExecPager
2.44 +{
2.45 +protected:
2.46 + ExecRegions _regions;
2.47 +
2.48 +public:
2.49 + virtual void add(ExecRegion ®ion);
2.50 +
2.51 + /* Notification methods, implementing PagerObject. */
2.52 +
2.53 + virtual long exception(l4_exc_regs_t regs,
2.54 + l4_snd_fpage_t *region);
2.55 +
2.56 + virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
2.57 + l4_snd_fpage_t *region);
2.58 +
2.59 + /* Region manager/mapper methods. */
2.60 +
2.61 + virtual long attach(address_t *start, offset_t size, map_flags_t flags,
2.62 + l4_cap_idx_t ds, address_t offset, unsigned char align);
2.63 +
2.64 +};
2.65 +
2.66 +/* vim: tabstop=2 expandtab shiftwidth=2
2.67 +*/
3.1 --- a/libexec/include/exec/pager.h Sun Jun 12 18:04:17 2022 +0200
3.2 +++ b/libexec/include/exec/pager.h Sun Jun 12 18:56:25 2022 +0200
3.3 @@ -1,5 +1,5 @@
3.4 /*
3.5 - * A system pager implementation.
3.6 + * A system pager interface.
3.7 *
3.8 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
3.9 *
3.10 @@ -21,34 +21,21 @@
3.11
3.12 #pragma once
3.13
3.14 -#include <map>
3.15 -
3.16 -#include <exec/mapped_region.h>
3.17 -
3.18 #include "pager_object_interface.h"
3.19
3.20
3.21
3.22 -/* Collection types. */
3.23 -
3.24 -typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
3.25 -
3.26 -
3.27 -
3.28 /* A simple system pager also acting as a region mapper. */
3.29
3.30 class ExecPager : public PagerObject
3.31 {
3.32 -protected:
3.33 - MappedRegions _regions;
3.34 -
3.35 public:
3.36 - virtual void add(MappedRegion region);
3.37 + virtual ~ExecPager();
3.38
3.39 /* Notification methods. */
3.40
3.41 virtual long exception(l4_exc_regs_t regs,
3.42 - l4_snd_fpage_t *region);
3.43 + l4_snd_fpage_t *region) = 0;
3.44
3.45 virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
3.46 l4_snd_fpage_t *region);
4.1 --- a/libexec/lib/src/Makefile Sun Jun 12 18:04:17 2022 +0200
4.2 +++ b/libexec/lib/src/Makefile Sun Jun 12 18:56:25 2022 +0200
4.3 @@ -35,7 +35,8 @@
4.4 # Normal source files.
4.5
4.6 PLAIN_SRC_CC = \
4.7 - common.cc elf.cc memory.cc pager.cc \
4.8 + common.cc elf.cc external_pager.cc \
4.9 + internal_pager.cc memory.cc pager.cc \
4.10 process.cc segment.cc stack.cc
4.11
4.12 # Normal definitions.
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/libexec/lib/src/external_pager.cc Sun Jun 12 18:56:25 2022 +0200
5.3 @@ -0,0 +1,257 @@
5.4 +/*
5.5 + * A system pager implementation residing in a separate task.
5.6 + *
5.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software; you can redistribute it and/or
5.10 + * modify it under the terms of the GNU General Public License as
5.11 + * published by the Free Software Foundation; either version 2 of
5.12 + * the License, or (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program; if not, write to the Free Software
5.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.22 + * Boston, MA 02110-1301, USA
5.23 + */
5.24 +
5.25 +#include <l4/re/env.h>
5.26 +#include <l4/sys/err.h>
5.27 +#include <l4/util/util.h>
5.28 +
5.29 +#include <ipc/mem_ipc.h>
5.30 +#include <mem/memory_utils.h>
5.31 +
5.32 +#include <stdio.h>
5.33 +#include <string.h>
5.34 +
5.35 +#include "external_pager.h"
5.36 +
5.37 +
5.38 +
5.39 +/* A simple system pager also acting as a region mapper. */
5.40 +
5.41 +/* Add a region to the pager. */
5.42 +
5.43 +void ExternalPager::add(MappedRegion ®ion)
5.44 +{
5.45 + _regions[region.map_start] = region;
5.46 +}
5.47 +
5.48 +/* Handle a general exception. */
5.49 +
5.50 +long ExternalPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
5.51 +{
5.52 + (void) region;
5.53 +
5.54 + printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
5.55 +
5.56 + printf("r15 = %lx\n", regs.r15);
5.57 + printf("r14 = %lx\n", regs.r14);
5.58 + printf("r13 = %lx\n", regs.r13);
5.59 + printf("r12 = %lx\n", regs.r12);
5.60 + printf("r11 = %lx\n", regs.r11);
5.61 + printf("r10 = %lx\n", regs.r10);
5.62 + printf("r9 = %lx\n", regs.r9);
5.63 + printf("r8 = %lx\n", regs.r8);
5.64 + printf("rdi = %lx\n", regs.rdi);
5.65 + printf("rsi = %lx\n", regs.rsi);
5.66 + printf("rbp = %lx\n", regs.rbp);
5.67 + printf("pfa = %lx\n", regs.pfa);
5.68 + printf("rbx = %lx\n", regs.rbx);
5.69 + printf("rdx = %lx\n", regs.rdx);
5.70 + printf("rcx = %lx\n", regs.rcx);
5.71 + printf("rax = %lx\n", regs.rax);
5.72 + printf("trapno = %lx\n", regs.trapno);
5.73 + printf("err = %lx\n", regs.err);
5.74 + printf("ip = %lx\n", regs.ip);
5.75 + printf("flags = %lx\n", regs.flags);
5.76 + printf("sp = %lx\n", regs.sp);
5.77 + printf("ss = %lx\n", regs.ss);
5.78 + printf("fs_base = %lx\n", regs.fs_base);
5.79 + printf("gs_base = %lx\n", regs.gs_base);
5.80 +
5.81 + return L4_EOK;
5.82 +}
5.83 +
5.84 +#define DEBUG 0
5.85 +
5.86 +/* Handle a page fault using any configured regions. */
5.87 +
5.88 +long ExternalPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
5.89 +{
5.90 + l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
5.91 +
5.92 +#if DEBUG
5.93 + printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
5.94 +#endif
5.95 +
5.96 + MappedRegions::iterator it = _regions.upper_bound(addr);
5.97 +
5.98 + if (it != _regions.begin())
5.99 + it--;
5.100 + else
5.101 + {
5.102 + printf("not mapped!\n");
5.103 + return -L4_ENOMEM;
5.104 + }
5.105 +
5.106 + MappedRegion &r = it->second;
5.107 +
5.108 + if ((addr >= r.map_start) && (addr < r.map_start + r.size))
5.109 + {
5.110 + l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
5.111 +
5.112 + region->fpage = l4_fpage(r.start + (page_addr - r.map_start), L4_PAGESHIFT, r.flags);
5.113 + region->snd_base = page_addr;
5.114 +
5.115 +#if DEBUG
5.116 + printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x\n",
5.117 + r.map_start, region->snd_base,
5.118 + r.start, l4_fpage_memaddr(region->fpage),
5.119 + addr - r.map_start,
5.120 + l4_fpage_size(region->fpage),
5.121 + l4_fpage_rights(region->fpage));
5.122 +
5.123 + printf("%lx -> ", addr);
5.124 +
5.125 + for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
5.126 + printf("%02x", *((unsigned char *)(r.start + (addr - r.map_start) + i)));
5.127 +
5.128 + printf("\n");
5.129 +#endif
5.130 +
5.131 + if (r.flags & L4RE_RM_F_W)
5.132 + l4_touch_rw((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.133 + else
5.134 + l4_touch_ro((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.135 +
5.136 + return L4_EOK;
5.137 + }
5.138 +
5.139 +#if DEBUG
5.140 + printf("not mapped!\n");
5.141 +#endif
5.142 +
5.143 + return -L4_ENOMEM;
5.144 +}
5.145 +
5.146 +/* Attach a region for provision when page faults occur. This is required in
5.147 + the initialisation of a program by the C library which requires a region
5.148 + mapper. */
5.149 +
5.150 +long ExternalPager::attach(address_t *start, offset_t size, map_flags_t flags,
5.151 + l4_cap_idx_t ds, address_t offset,
5.152 + unsigned char align)
5.153 +{
5.154 +#if DEBUG
5.155 + printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
5.156 +#endif
5.157 +
5.158 + if (align < L4_PAGESHIFT)
5.159 + align = L4_PAGESHIFT;
5.160 +
5.161 + offset_t increment = 1UL << align;
5.162 + offset_t region_size = round(size, increment);
5.163 +
5.164 + /* Either attempt to find an address for the specified region, starting from
5.165 + any indicated address. */
5.166 +
5.167 + if (flags & L4RE_RM_F_SEARCH_ADDR)
5.168 + {
5.169 + address_t region_start = trunc(*start, increment);
5.170 + MappedRegions::iterator it = _regions.upper_bound(*start);
5.171 +
5.172 + if (!region_start)
5.173 + region_start += increment;
5.174 +
5.175 +#if DEBUG
5.176 + printf("-> search from %lx -> %lx...\n", *start, region_start);
5.177 +#endif
5.178 +
5.179 + /* Before last known region. */
5.180 +
5.181 + while (it != _regions.end())
5.182 + {
5.183 + MappedRegions::iterator next = it;
5.184 + MappedRegion &r = it->second;
5.185 + address_t start_limit;
5.186 + address_t end_limit = r.map_start;
5.187 +
5.188 + /* Consider any preceding region. If no such region exists, choose an
5.189 + address at the start of memory. */
5.190 +
5.191 + if (it == _regions.begin())
5.192 + start_limit = L4_PAGESIZE;
5.193 + else
5.194 + {
5.195 + it--;
5.196 + MappedRegion &pr = it->second;
5.197 + start_limit = pr.map_start + pr.size;
5.198 + it = next;
5.199 + }
5.200 +
5.201 + /* Test against the limits. */
5.202 +
5.203 + if (region_start < start_limit)
5.204 + region_start = round(start_limit, increment);
5.205 +
5.206 + /* Investigate subsequent regions if not enough space exists between the
5.207 + preceding region (or start of memory) and the current region. */
5.208 +
5.209 + if ((region_start + region_size) > end_limit)
5.210 + {
5.211 + it++;
5.212 + if (it == _regions.end())
5.213 + return -L4_ENOMEM;
5.214 + }
5.215 + else
5.216 + break;
5.217 + }
5.218 +
5.219 + /* Attach the provided dataspace.
5.220 + NOTE: This is only done in this implementation to support the paging
5.221 + mechanism. In a region mapper residing within the actual task, the
5.222 + dataspace's map operation would be invoked to obtain mappings. */
5.223 +
5.224 + l4_addr_t ds_start;
5.225 +
5.226 + long err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
5.227 +
5.228 + if (err)
5.229 + return err;
5.230 +
5.231 + l4_touch_rw((const void *) ds_start, size);
5.232 +
5.233 +#if DEBUG
5.234 + printf("-> added region for %lx size %ld (%d)\n", region_start, region_size, page_order(region_size));
5.235 +#endif
5.236 +
5.237 + MappedRegion r(ds_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, region_start);
5.238 +
5.239 + add(r);
5.240 +
5.241 + *start = region_start;
5.242 + return L4_EOK;
5.243 + }
5.244 +
5.245 + /* Or attempt to add the specified region at a specific address. */
5.246 +
5.247 + else
5.248 + {
5.249 + // NOTE: To be implemented.
5.250 +
5.251 +#if DEBUG
5.252 + printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
5.253 +#endif
5.254 +
5.255 + return -L4_ENOMEM;
5.256 + }
5.257 +}
5.258 +
5.259 +/* vim: tabstop=2 expandtab shiftwidth=2
5.260 +*/
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/libexec/lib/src/internal_pager.cc Sun Jun 12 18:56:25 2022 +0200
6.3 @@ -0,0 +1,230 @@
6.4 +/*
6.5 + * A system pager implementation residing in the same task as a program.
6.6 + *
6.7 + * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software; you can redistribute it and/or
6.10 + * modify it under the terms of the GNU General Public License as
6.11 + * published by the Free Software Foundation; either version 2 of
6.12 + * the License, or (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program; if not, write to the Free Software
6.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
6.22 + * Boston, MA 02110-1301, USA
6.23 + */
6.24 +
6.25 +#include <l4/re/env.h>
6.26 +#include <l4/sys/err.h>
6.27 +#include <l4/util/util.h>
6.28 +
6.29 +#include <ipc/mem_ipc.h>
6.30 +#include <mem/memory_utils.h>
6.31 +
6.32 +#include <stdio.h>
6.33 +#include <string.h>
6.34 +
6.35 +#include "dataspace_client.h"
6.36 +#include "internal_pager.h"
6.37 +
6.38 +
6.39 +
6.40 +/* A simple system pager also acting as a region mapper. */
6.41 +
6.42 +/* Add a region to the pager. */
6.43 +
6.44 +void InternalPager::add(ExecRegion ®ion)
6.45 +{
6.46 + _regions[region.start] = region;
6.47 +}
6.48 +
6.49 +/* Handle a general exception. */
6.50 +
6.51 +long InternalPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
6.52 +{
6.53 + (void) region;
6.54 +
6.55 + printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
6.56 +
6.57 + printf("r15 = %lx\n", regs.r15);
6.58 + printf("r14 = %lx\n", regs.r14);
6.59 + printf("r13 = %lx\n", regs.r13);
6.60 + printf("r12 = %lx\n", regs.r12);
6.61 + printf("r11 = %lx\n", regs.r11);
6.62 + printf("r10 = %lx\n", regs.r10);
6.63 + printf("r9 = %lx\n", regs.r9);
6.64 + printf("r8 = %lx\n", regs.r8);
6.65 + printf("rdi = %lx\n", regs.rdi);
6.66 + printf("rsi = %lx\n", regs.rsi);
6.67 + printf("rbp = %lx\n", regs.rbp);
6.68 + printf("pfa = %lx\n", regs.pfa);
6.69 + printf("rbx = %lx\n", regs.rbx);
6.70 + printf("rdx = %lx\n", regs.rdx);
6.71 + printf("rcx = %lx\n", regs.rcx);
6.72 + printf("rax = %lx\n", regs.rax);
6.73 + printf("trapno = %lx\n", regs.trapno);
6.74 + printf("err = %lx\n", regs.err);
6.75 + printf("ip = %lx\n", regs.ip);
6.76 + printf("flags = %lx\n", regs.flags);
6.77 + printf("sp = %lx\n", regs.sp);
6.78 + printf("ss = %lx\n", regs.ss);
6.79 + printf("fs_base = %lx\n", regs.fs_base);
6.80 + printf("gs_base = %lx\n", regs.gs_base);
6.81 +
6.82 + return L4_EOK;
6.83 +}
6.84 +
6.85 +#define DEBUG 0
6.86 +
6.87 +/* Handle a page fault using any configured regions. */
6.88 +
6.89 +long InternalPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
6.90 +{
6.91 + l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
6.92 +
6.93 +#if DEBUG
6.94 + printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
6.95 +#endif
6.96 +
6.97 + ExecRegions::iterator it = _regions.upper_bound(addr);
6.98 +
6.99 + if (it != _regions.begin())
6.100 + it--;
6.101 + else
6.102 + {
6.103 + printf("not mapped!\n");
6.104 + return -L4_ENOMEM;
6.105 + }
6.106 +
6.107 + ExecRegion &r = it->second;
6.108 +
6.109 + if ((addr >= r.start) && (addr < r.start + r.size))
6.110 + {
6.111 + l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
6.112 +
6.113 + /* Interact with the region's dataspace, specifying a receive window for a
6.114 + map operation. Here, a single page is specified. */
6.115 +
6.116 + client_Dataspace dataspace(r.ds);
6.117 + l4_snd_fpage_t region = {0, l4_fpage(page_addr, L4_PAGESHIFT, 0)};
6.118 +
6.119 +#if DEBUG
6.120 + printf("region = {%lx, {%lx, %d}}\n", region.snd_base, l4_fpage_memaddr(region.fpage), l4_fpage_size(region.fpage));
6.121 +#endif
6.122 +
6.123 + return dataspace.map(0, 0, L4_FPAGE_RO, ®ion);
6.124 + }
6.125 +
6.126 +#if DEBUG
6.127 + printf("not mapped!\n");
6.128 +#endif
6.129 +
6.130 + return -L4_ENOMEM;
6.131 +}
6.132 +
6.133 +/* Attach a region for provision when page faults occur. This is required in
6.134 + the initialisation of a program by the C library which requires a region
6.135 + mapper. */
6.136 +
6.137 +long InternalPager::attach(address_t *start, offset_t size, map_flags_t flags,
6.138 + l4_cap_idx_t ds, address_t offset,
6.139 + unsigned char align)
6.140 +{
6.141 +#if DEBUG
6.142 + printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
6.143 +#endif
6.144 +
6.145 + if (align < L4_PAGESHIFT)
6.146 + align = L4_PAGESHIFT;
6.147 +
6.148 + offset_t increment = 1UL << align;
6.149 + offset_t region_size = round(size, increment);
6.150 +
6.151 + /* Either attempt to find an address for the specified region, starting from
6.152 + any indicated address. */
6.153 +
6.154 + if (flags & L4RE_RM_F_SEARCH_ADDR)
6.155 + {
6.156 + address_t region_start = trunc(*start, increment);
6.157 + ExecRegions::iterator it = _regions.upper_bound(*start);
6.158 +
6.159 + if (!region_start)
6.160 + region_start += increment;
6.161 +
6.162 +#if DEBUG
6.163 + printf("-> search from %lx -> %lx...\n", *start, region_start);
6.164 +#endif
6.165 +
6.166 + /* Before last known region. */
6.167 +
6.168 + while (it != _regions.end())
6.169 + {
6.170 + ExecRegions::iterator next = it;
6.171 + ExecRegion &r = it->second;
6.172 + address_t start_limit;
6.173 + address_t end_limit = r.start;
6.174 +
6.175 + /* Consider any preceding region. If no such region exists, choose an
6.176 + address at the start of memory. */
6.177 +
6.178 + if (it == _regions.begin())
6.179 + start_limit = L4_PAGESIZE;
6.180 + else
6.181 + {
6.182 + it--;
6.183 + ExecRegion &pr = it->second;
6.184 + start_limit = pr.start + pr.size;
6.185 + it = next;
6.186 + }
6.187 +
6.188 + /* Test against the limits. */
6.189 +
6.190 + if (region_start < start_limit)
6.191 + region_start = round(start_limit, increment);
6.192 +
6.193 + /* Investigate subsequent regions if not enough space exists between the
6.194 + preceding region (or start of memory) and the current region. */
6.195 +
6.196 + if ((region_start + region_size) > end_limit)
6.197 + {
6.198 + it++;
6.199 + if (it == _regions.end())
6.200 + return -L4_ENOMEM;
6.201 + }
6.202 + else
6.203 + break;
6.204 + }
6.205 +
6.206 +#if DEBUG
6.207 + printf("-> added region for %lx size %ld (%d)\n", region_start, region_size, page_order(region_size));
6.208 +#endif
6.209 +
6.210 + ExecRegion r = (ExecRegion) {region_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, ds};
6.211 +
6.212 + add(r);
6.213 +
6.214 + *start = region_start;
6.215 + return L4_EOK;
6.216 + }
6.217 +
6.218 + /* Or attempt to add the specified region at a specific address. */
6.219 +
6.220 + else
6.221 + {
6.222 + // NOTE: To be implemented.
6.223 +
6.224 +#if DEBUG
6.225 + printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
6.226 +#endif
6.227 +
6.228 + return -L4_ENOMEM;
6.229 + }
6.230 +}
6.231 +
6.232 +/* vim: tabstop=2 expandtab shiftwidth=2
6.233 +*/
7.1 --- a/libexec/lib/src/pager.cc Sun Jun 12 18:04:17 2022 +0200
7.2 +++ b/libexec/lib/src/pager.cc Sun Jun 12 18:56:25 2022 +0200
7.3 @@ -1,5 +1,5 @@
7.4 /*
7.5 - * A system pager implementation.
7.6 + * A system pager interface.
7.7 *
7.8 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
7.9 *
7.10 @@ -19,236 +19,14 @@
7.11 * Boston, MA 02110-1301, USA
7.12 */
7.13
7.14 -#include <l4/re/env.h>
7.15 -#include <l4/sys/err.h>
7.16 -#include <l4/util/util.h>
7.17 -
7.18 -#include <ipc/mem_ipc.h>
7.19 -#include <mem/memory_utils.h>
7.20 -
7.21 -#include <stdio.h>
7.22 -#include <string.h>
7.23 -
7.24 #include "pager.h"
7.25 -#include "pager_object_server.h"
7.26
7.27
7.28
7.29 -/* A simple system pager also acting as a region mapper. */
7.30 -
7.31 -/* Add a region to the pager. */
7.32 -
7.33 -void ExecPager::add(MappedRegion region)
7.34 -{
7.35 - _regions[region.map_start] = region;
7.36 -}
7.37 -
7.38 -/* Handle a general exception. */
7.39 -
7.40 -long ExecPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
7.41 -{
7.42 - (void) region;
7.43 -
7.44 - printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
7.45 -
7.46 - printf("r15 = %lx\n", regs.r15);
7.47 - printf("r14 = %lx\n", regs.r14);
7.48 - printf("r13 = %lx\n", regs.r13);
7.49 - printf("r12 = %lx\n", regs.r12);
7.50 - printf("r11 = %lx\n", regs.r11);
7.51 - printf("r10 = %lx\n", regs.r10);
7.52 - printf("r9 = %lx\n", regs.r9);
7.53 - printf("r8 = %lx\n", regs.r8);
7.54 - printf("rdi = %lx\n", regs.rdi);
7.55 - printf("rsi = %lx\n", regs.rsi);
7.56 - printf("rbp = %lx\n", regs.rbp);
7.57 - printf("pfa = %lx\n", regs.pfa);
7.58 - printf("rbx = %lx\n", regs.rbx);
7.59 - printf("rdx = %lx\n", regs.rdx);
7.60 - printf("rcx = %lx\n", regs.rcx);
7.61 - printf("rax = %lx\n", regs.rax);
7.62 - printf("trapno = %lx\n", regs.trapno);
7.63 - printf("err = %lx\n", regs.err);
7.64 - printf("ip = %lx\n", regs.ip);
7.65 - printf("flags = %lx\n", regs.flags);
7.66 - printf("sp = %lx\n", regs.sp);
7.67 - printf("ss = %lx\n", regs.ss);
7.68 - printf("fs_base = %lx\n", regs.fs_base);
7.69 - printf("gs_base = %lx\n", regs.gs_base);
7.70 -
7.71 - return L4_EOK;
7.72 -}
7.73 -
7.74 -#define DEBUG 0
7.75 -
7.76 -/* Handle a page fault using any configured regions. */
7.77 -
7.78 -long ExecPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
7.79 -{
7.80 - l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
7.81 -
7.82 -#if DEBUG
7.83 - printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
7.84 -#endif
7.85 -
7.86 - MappedRegions::iterator it = _regions.upper_bound(addr);
7.87 -
7.88 - if (it != _regions.begin())
7.89 - it--;
7.90 - else
7.91 - {
7.92 - printf("not mapped!\n");
7.93 - return -L4_ENOMEM;
7.94 - }
7.95 -
7.96 - MappedRegion &r = it->second;
7.97 -
7.98 - if ((addr >= r.map_start) && (addr < r.map_start + r.size))
7.99 - {
7.100 - l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
7.101 -
7.102 - region->fpage = l4_fpage(r.start + (page_addr - r.map_start), L4_PAGESHIFT, r.flags);
7.103 - region->snd_base = page_addr;
7.104 -
7.105 -#if DEBUG
7.106 - printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x\n",
7.107 - r.map_start, region->snd_base,
7.108 - r.start, l4_fpage_memaddr(region->fpage),
7.109 - addr - r.map_start,
7.110 - l4_fpage_size(region->fpage),
7.111 - l4_fpage_rights(region->fpage));
7.112 -
7.113 - printf("%lx -> ", addr);
7.114 -
7.115 - for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
7.116 - printf("%02x", *((unsigned char *)(r.start + (addr - r.map_start) + i)));
7.117 -
7.118 - printf("\n");
7.119 -#endif
7.120 -
7.121 - if (r.flags & L4RE_RM_F_W)
7.122 - l4_touch_rw((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
7.123 - else
7.124 - l4_touch_ro((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
7.125 -
7.126 - return L4_EOK;
7.127 - }
7.128 -
7.129 -#if DEBUG
7.130 - printf("not mapped!\n");
7.131 -#endif
7.132 -
7.133 - return -L4_ENOMEM;
7.134 -}
7.135 +/* Necessary virtual destructor. */
7.136
7.137 -/* Attach a region for provision when page faults occur. This is required in
7.138 - the initialisation of a program by the C library which requires a region
7.139 - mapper. */
7.140 -
7.141 -long ExecPager::attach(address_t *start, offset_t size, map_flags_t flags,
7.142 - l4_cap_idx_t ds, address_t offset, unsigned char align)
7.143 +ExecPager::~ExecPager()
7.144 {
7.145 -#if DEBUG
7.146 - printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
7.147 -#endif
7.148 -
7.149 - if (align < L4_PAGESHIFT)
7.150 - align = L4_PAGESHIFT;
7.151 -
7.152 - offset_t increment = 1UL << align;
7.153 - offset_t region_size = round(size, increment);
7.154 -
7.155 - /* Either attempt to find an address for the specified region, starting from
7.156 - any indicated address. */
7.157 -
7.158 - if (flags & L4RE_RM_F_SEARCH_ADDR)
7.159 - {
7.160 - address_t region_start = trunc(*start, increment);
7.161 - MappedRegions::iterator it = _regions.upper_bound(*start);
7.162 -
7.163 - if (!region_start)
7.164 - region_start += increment;
7.165 -
7.166 -#if DEBUG
7.167 - printf("-> search from %lx -> %lx...\n", *start, region_start);
7.168 -#endif
7.169 -
7.170 - /* Before last known region. */
7.171 -
7.172 - while (it != _regions.end())
7.173 - {
7.174 - MappedRegions::iterator next = it;
7.175 - MappedRegion &r = it->second;
7.176 - address_t start_limit;
7.177 - address_t end_limit = r.map_start;
7.178 -
7.179 - /* Consider any preceding region. If no such region exists, choose an
7.180 - address at the start of memory. */
7.181 -
7.182 - if (it == _regions.begin())
7.183 - start_limit = L4_PAGESIZE;
7.184 - else
7.185 - {
7.186 - it--;
7.187 - MappedRegion &pr = it->second;
7.188 - start_limit = pr.map_start + pr.size;
7.189 - it = next;
7.190 - }
7.191 -
7.192 - /* Test against the limits. */
7.193 -
7.194 - if (region_start < start_limit)
7.195 - region_start = round(start_limit, increment);
7.196 -
7.197 - /* Investigate subsequent regions if not enough space exists between the
7.198 - preceding region (or start of memory) and the current region. */
7.199 -
7.200 - if ((region_start + region_size) > end_limit)
7.201 - {
7.202 - it++;
7.203 - if (it == _regions.end())
7.204 - return -L4_ENOMEM;
7.205 - }
7.206 - else
7.207 - break;
7.208 - }
7.209 -
7.210 - /* Attach the provided dataspace.
7.211 - NOTE: This is only done in this implementation to support the paging
7.212 - mechanism. In a region mapper residing within the actual task, the
7.213 - dataspace's map operation would be invoked to obtain mappings. */
7.214 -
7.215 - l4_addr_t ds_start;
7.216 -
7.217 - long err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
7.218 -
7.219 - if (err)
7.220 - return err;
7.221 -
7.222 - l4_touch_rw((const void *) ds_start, size);
7.223 -
7.224 -#if DEBUG
7.225 - printf("-> added region for %lx size %ld (%d)\n", region_start, region_size, page_order(region_size));
7.226 -#endif
7.227 -
7.228 - add(MappedRegion(ds_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, region_start));
7.229 -
7.230 - *start = region_start;
7.231 - return L4_EOK;
7.232 - }
7.233 -
7.234 - /* Or attempt to add the specified region at a specific address. */
7.235 -
7.236 - else
7.237 - {
7.238 - // NOTE: To be implemented.
7.239 -
7.240 -#if DEBUG
7.241 - printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
7.242 -#endif
7.243 -
7.244 - return -L4_ENOMEM;
7.245 - }
7.246 }
7.247
7.248 /* vim: tabstop=2 expandtab shiftwidth=2
8.1 --- a/tests/dstest_exec.cc Sun Jun 12 18:04:17 2022 +0200
8.2 +++ b/tests/dstest_exec.cc Sun Jun 12 18:56:25 2022 +0200
8.3 @@ -25,7 +25,7 @@
8.4
8.5 #include <exec/elf.h>
8.6 #include <exec/memory.h>
8.7 -#include <exec/pager.h>
8.8 +#include <exec/external_pager.h>
8.9 #include <exec/process.h>
8.10 #include <ipc/server.h>
8.11
8.12 @@ -38,7 +38,7 @@
8.13
8.14
8.15
8.16 -static ExecPager exec_pager;
8.17 +static ExternalPager exec_pager;
8.18
8.19
8.20