1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libexec/include/exec/pager.h Mon Jun 06 01:02:59 2022 +0200
1.3 @@ -0,0 +1,64 @@
1.4 +/*
1.5 + * A system pager implementation.
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 +
1.31 +#include "pager_object_interface.h"
1.32 +
1.33 +
1.34 +
1.35 +/* Collection types. */
1.36 +
1.37 +typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
1.38 +
1.39 +
1.40 +
1.41 +/* A simple system pager also acting as a region mapper. */
1.42 +
1.43 +class ExecPager : public PagerObject
1.44 +{
1.45 +protected:
1.46 + MappedRegions _regions;
1.47 +
1.48 +public:
1.49 + virtual void add(MappedRegion region);
1.50 +
1.51 + /* Notification methods. */
1.52 +
1.53 + virtual long exception(l4_exc_regs_t regs,
1.54 + l4_snd_fpage_t *region);
1.55 +
1.56 + virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
1.57 + l4_snd_fpage_t *region);
1.58 +
1.59 + /* Region manager/mapper methods. */
1.60 +
1.61 + virtual long attach(address_t *start, offset_t size, map_flags_t flags,
1.62 + l4_cap_idx_t ds, address_t offset, unsigned char align);
1.63 +
1.64 +};
1.65 +
1.66 +/* vim: tabstop=2 expandtab shiftwidth=2
1.67 +*/
2.1 --- a/libexec/lib/src/Makefile Mon Jun 06 00:36:14 2022 +0200
2.2 +++ b/libexec/lib/src/Makefile Mon Jun 06 01:02:59 2022 +0200
2.3 @@ -3,10 +3,55 @@
2.4
2.5 TARGET = libexec.a libexec.so
2.6 PC_FILENAME = libexec
2.7 -SRC_CC = elf.cc memory.cc process.cc segment.cc stack.cc
2.8 -REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes libfsclient
2.9 +
2.10 +# Locations for interface input and generated output.
2.11 +
2.12 +IDL_DIR = $(PKGDIR)/../libsystypes/idl
2.13 +IDL_MK_DIR = $(L4DIR)/idl4re/mk
2.14 +IDL_BUILD_DIR = .
2.15 +IDL_EXPORT_DIR = .
2.16 +
2.17 +include $(IDL_MK_DIR)/idl.mk
2.18 +
2.19 +# Compound interfaces.
2.20 +
2.21 +pager_object_NAME = PagerObject
2.22 +pager_object_INTERFACES = region_mapper system_pager
2.23 +
2.24 +COMP_INTERFACES_CC = pager_object
2.25 +
2.26 +# Individual interfaces.
2.27 +
2.28 +CLIENT_INTERFACES_CC = dataspace mapped_file
2.29
2.30 -PRIVATE_INCDIR += $(PKGDIR)/include/exec
2.31 +SERVER_INTERFACES_CC = $(call common_interfaces,$(COMP_INTERFACES_CC))
2.32 +
2.33 +# Generated and plain source files.
2.34 +
2.35 +CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))
2.36 +
2.37 +SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC) $(COMP_INTERFACES_CC))
2.38 +
2.39 +# Normal source files.
2.40 +
2.41 +PLAIN_SRC_CC = elf.cc memory.cc pager.cc process.cc segment.cc stack.cc
2.42 +
2.43 +# Normal definitions.
2.44 +
2.45 +SRC_CC = \
2.46 + $(CLIENT_INTERFACES_SRC_CC) \
2.47 + $(SERVER_INTERFACES_SRC_CC) \
2.48 + $(PLAIN_SRC_CC)
2.49 +
2.50 +REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes libfsclient
2.51 +
2.52 +PRIVATE_INCDIR = $(PKGDIR)/include/exec $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
2.53 +
2.54 CONTRIB_INCDIR = libexec
2.55
2.56 include $(L4DIR)/mk/lib.mk
2.57 +include $(IDL_MK_DIR)/interface_rules.mk
2.58 +
2.59 +$(PLAIN_SRC_CC): $(CLIENT_INTERFACES_SRC_CC)
2.60 +
2.61 +$(PLAIN_SRC_CC): $(SERVER_INTERFACES_SRC_CC)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/libexec/lib/src/pager.cc Mon Jun 06 01:02:59 2022 +0200
3.3 @@ -0,0 +1,255 @@
3.4 +/*
3.5 + * A system pager implementation.
3.6 + *
3.7 + * Copyright (C) 2022 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 +#include <l4/re/env.h>
3.26 +#include <l4/sys/err.h>
3.27 +#include <l4/util/util.h>
3.28 +
3.29 +#include <ipc/mem_ipc.h>
3.30 +#include <mem/memory_utils.h>
3.31 +
3.32 +#include <stdio.h>
3.33 +#include <string.h>
3.34 +
3.35 +#include "pager.h"
3.36 +#include "pager_object_server.h"
3.37 +
3.38 +
3.39 +
3.40 +/* A simple system pager also acting as a region mapper. */
3.41 +
3.42 +/* Add a region to the pager. */
3.43 +
3.44 +void ExecPager::add(MappedRegion region)
3.45 +{
3.46 + _regions[region.map_start] = region;
3.47 +}
3.48 +
3.49 +/* Handle a general exception. */
3.50 +
3.51 +long ExecPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
3.52 +{
3.53 + (void) region;
3.54 +
3.55 + printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
3.56 +
3.57 + printf("r15 = %lx\n", regs.r15);
3.58 + printf("r14 = %lx\n", regs.r14);
3.59 + printf("r13 = %lx\n", regs.r13);
3.60 + printf("r12 = %lx\n", regs.r12);
3.61 + printf("r11 = %lx\n", regs.r11);
3.62 + printf("r10 = %lx\n", regs.r10);
3.63 + printf("r9 = %lx\n", regs.r9);
3.64 + printf("r8 = %lx\n", regs.r8);
3.65 + printf("rdi = %lx\n", regs.rdi);
3.66 + printf("rsi = %lx\n", regs.rsi);
3.67 + printf("rbp = %lx\n", regs.rbp);
3.68 + printf("pfa = %lx\n", regs.pfa);
3.69 + printf("rbx = %lx\n", regs.rbx);
3.70 + printf("rdx = %lx\n", regs.rdx);
3.71 + printf("rcx = %lx\n", regs.rcx);
3.72 + printf("rax = %lx\n", regs.rax);
3.73 + printf("trapno = %lx\n", regs.trapno);
3.74 + printf("err = %lx\n", regs.err);
3.75 + printf("ip = %lx\n", regs.ip);
3.76 + printf("flags = %lx\n", regs.flags);
3.77 + printf("sp = %lx\n", regs.sp);
3.78 + printf("ss = %lx\n", regs.ss);
3.79 + printf("fs_base = %lx\n", regs.fs_base);
3.80 + printf("gs_base = %lx\n", regs.gs_base);
3.81 +
3.82 + return L4_EOK;
3.83 +}
3.84 +
3.85 +#define DEBUG 0
3.86 +
3.87 +/* Handle a page fault using any configured regions. */
3.88 +
3.89 +long ExecPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
3.90 +{
3.91 + l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
3.92 +
3.93 +#if DEBUG
3.94 + printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
3.95 +#endif
3.96 +
3.97 + MappedRegions::iterator it = _regions.upper_bound(addr);
3.98 +
3.99 + if (it != _regions.begin())
3.100 + it--;
3.101 + else
3.102 + {
3.103 + printf("not mapped!\n");
3.104 + return -L4_ENOMEM;
3.105 + }
3.106 +
3.107 + MappedRegion &r = it->second;
3.108 +
3.109 + if ((addr >= r.map_start) && (addr < r.map_start + r.size))
3.110 + {
3.111 + l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
3.112 +
3.113 + region->fpage = l4_fpage(r.start + (page_addr - r.map_start), L4_PAGESHIFT, r.flags);
3.114 + region->snd_base = page_addr;
3.115 +
3.116 +#if DEBUG
3.117 + printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x\n",
3.118 + r.map_start, region->snd_base,
3.119 + r.start, l4_fpage_memaddr(region->fpage),
3.120 + addr - r.map_start,
3.121 + l4_fpage_size(region->fpage),
3.122 + l4_fpage_rights(region->fpage));
3.123 +
3.124 + printf("%lx -> ", addr);
3.125 +
3.126 + for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
3.127 + printf("%02x", *((unsigned char *)(r.start + (addr - r.map_start) + i)));
3.128 +
3.129 + printf("\n");
3.130 +#endif
3.131 +
3.132 + if (r.flags & L4RE_RM_F_W)
3.133 + l4_touch_rw((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
3.134 + else
3.135 + l4_touch_ro((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
3.136 +
3.137 + return L4_EOK;
3.138 + }
3.139 +
3.140 +#if DEBUG
3.141 + printf("not mapped!\n");
3.142 +#endif
3.143 +
3.144 + return -L4_ENOMEM;
3.145 +}
3.146 +
3.147 +/* Attach a region for provision when page faults occur. This is required in
3.148 + the initialisation of a program by the C library which requires a region
3.149 + mapper. */
3.150 +
3.151 +long ExecPager::attach(address_t *start, offset_t size, map_flags_t flags,
3.152 + l4_cap_idx_t ds, address_t offset, unsigned char align)
3.153 +{
3.154 +#if DEBUG
3.155 + printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
3.156 +#endif
3.157 +
3.158 + if (align < L4_PAGESHIFT)
3.159 + align = L4_PAGESHIFT;
3.160 +
3.161 + offset_t increment = 1UL << align;
3.162 + offset_t region_size = round(size, increment);
3.163 +
3.164 + /* Either attempt to find an address for the specified region, starting from
3.165 + any indicated address. */
3.166 +
3.167 + if (flags & L4RE_RM_F_SEARCH_ADDR)
3.168 + {
3.169 + address_t region_start = trunc(*start, increment);
3.170 + MappedRegions::iterator it = _regions.upper_bound(*start);
3.171 +
3.172 + if (!region_start)
3.173 + region_start += increment;
3.174 +
3.175 +#if DEBUG
3.176 + printf("-> search from %lx -> %lx...\n", *start, region_start);
3.177 +#endif
3.178 +
3.179 + /* Before last known region. */
3.180 +
3.181 + while (it != _regions.end())
3.182 + {
3.183 + MappedRegions::iterator next = it;
3.184 + MappedRegion &r = it->second;
3.185 + address_t start_limit;
3.186 + address_t end_limit = r.map_start;
3.187 +
3.188 + /* Consider any preceding region. If no such region exists, choose an
3.189 + address at the start of memory. */
3.190 +
3.191 + if (it == _regions.begin())
3.192 + start_limit = L4_PAGESIZE;
3.193 + else
3.194 + {
3.195 + it--;
3.196 + MappedRegion &pr = it->second;
3.197 + start_limit = pr.map_start + pr.size;
3.198 + it = next;
3.199 + }
3.200 +
3.201 + /* Test against the limits. */
3.202 +
3.203 + if (region_start < start_limit)
3.204 + region_start = round(start_limit, increment);
3.205 +
3.206 + /* Investigate subsequent regions if not enough space exists between the
3.207 + preceding region (or start of memory) and the current region. */
3.208 +
3.209 + if ((region_start + region_size) > end_limit)
3.210 + {
3.211 + it++;
3.212 + if (it == _regions.end())
3.213 + return -L4_ENOMEM;
3.214 + }
3.215 + else
3.216 + break;
3.217 + }
3.218 +
3.219 + /* Attach the provided dataspace.
3.220 + NOTE: This is only done in this implementation to support the paging
3.221 + mechanism. In a region mapper residing within the actual task, the
3.222 + dataspace's map operation would be invoked to obtain mappings. */
3.223 +
3.224 + l4_addr_t ds_start;
3.225 +
3.226 + long err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
3.227 +
3.228 + if (err)
3.229 + return err;
3.230 +
3.231 + l4_touch_rw((const void *) ds_start, size);
3.232 +
3.233 +#if DEBUG
3.234 + printf("-> added region for %lx size %ld (%d)\n", region_start, region_size, page_order(region_size));
3.235 +#endif
3.236 +
3.237 + add(MappedRegion(ds_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, region_start));
3.238 +
3.239 + *start = region_start;
3.240 + return L4_EOK;
3.241 + }
3.242 +
3.243 + /* Or attempt to add the specified region at a specific address. */
3.244 +
3.245 + else
3.246 + {
3.247 + // NOTE: To be implemented.
3.248 +
3.249 +#if DEBUG
3.250 + printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
3.251 +#endif
3.252 +
3.253 + return -L4_ENOMEM;
3.254 + }
3.255 +}
3.256 +
3.257 +/* vim: tabstop=2 expandtab shiftwidth=2
3.258 +*/
4.1 --- a/tests/Makefile Mon Jun 06 00:36:14 2022 +0200
4.2 +++ b/tests/Makefile Mon Jun 06 01:02:59 2022 +0200
4.3 @@ -28,25 +28,14 @@
4.4
4.5 include $(IDL_MK_DIR)/idl.mk
4.6
4.7 -# Compound interfaces.
4.8 -
4.9 -pager_object_NAME = PagerObject
4.10 -pager_object_INTERFACES = region_mapper system_pager
4.11 -
4.12 -COMP_INTERFACES_CC = pager_object
4.13 -
4.14 # Individual interfaces.
4.15
4.16 CLIENT_INTERFACES_CC = dataspace mapped_file
4.17
4.18 -SERVER_INTERFACES_CC = $(call common_interfaces,$(COMP_INTERFACES_CC))
4.19 -
4.20 # Generated and plain source files.
4.21
4.22 CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))
4.23
4.24 -SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC) $(COMP_INTERFACES_CC))
4.25 -
4.26 # Normal source files.
4.27
4.28 SRC_CC_dstest_block_client = dstest_block_client.cc
4.29 @@ -73,8 +62,7 @@
4.30
4.31 SRC_CC_dstest_test_client = dstest_test_client.cc
4.32
4.33 -PLAIN_SRC_CC_dstest_exec = dstest_exec.cc
4.34 -SRC_CC_dstest_exec = $(PLAIN_SRC_CC_dstest_exec) $(SERVER_INTERFACES_SRC_CC)
4.35 +SRC_CC_dstest_exec = dstest_exec.cc
4.36
4.37 PLAIN_SRC_CC_dstest_file_mapping = dstest_file_mapping.cc
4.38 SRC_CC_dstest_file_mapping = $(PLAIN_SRC_CC_dstest_file_mapping) $(CLIENT_INTERFACES_SRC_CC)
4.39 @@ -86,5 +74,3 @@
4.40 include $(IDL_MK_DIR)/interface_rules.mk
4.41
4.42 $(PLAIN_SRC_CC_dstest_file_mapping): $(CLIENT_INTERFACES_SRC_CC)
4.43 -
4.44 -$(PLAIN_SRC_CC_dstest_exec): $(SERVER_INTERFACES_SRC_CC)
5.1 --- a/tests/dstest_exec.cc Mon Jun 06 00:36:14 2022 +0200
5.2 +++ b/tests/dstest_exec.cc Mon Jun 06 01:02:59 2022 +0200
5.3 @@ -25,265 +25,19 @@
5.4
5.5 #include <exec/elf.h>
5.6 #include <exec/memory.h>
5.7 +#include <exec/pager.h>
5.8 #include <exec/process.h>
5.9 -#include <ipc/mem_ipc.h>
5.10 #include <ipc/server.h>
5.11 -#include <mem/memory_utils.h>
5.12 -
5.13 -#include <map>
5.14
5.15 #include <stdio.h>
5.16 -#include <stdlib.h>
5.17 -#include <string.h>
5.18
5.19 #include <pthread-l4.h>
5.20 #include <pthread.h>
5.21
5.22 -#include "pager_object_interface.h"
5.23 #include "pager_object_server.h"
5.24
5.25
5.26
5.27 -/* A simple system pager also acting as a region mapper. */
5.28 -
5.29 -typedef std::map<l4_addr_t, MappedRegion> MappedRegions;
5.30 -
5.31 -class ExecPager : public PagerObject
5.32 -{
5.33 -protected:
5.34 - MappedRegions _regions;
5.35 -
5.36 -public:
5.37 - virtual void add(MappedRegion region)
5.38 - {
5.39 - _regions[region.map_start] = region;
5.40 - }
5.41 -
5.42 - /* Notification methods. */
5.43 -
5.44 - virtual long exception(l4_exc_regs_t regs,
5.45 - l4_snd_fpage_t *region);
5.46 -
5.47 - virtual long page_fault(l4_umword_t pfa, l4_umword_t pc,
5.48 - l4_snd_fpage_t *region);
5.49 -
5.50 - /* Region manager/mapper methods. */
5.51 -
5.52 - virtual long attach(address_t *start, offset_t size, map_flags_t flags,
5.53 - l4_cap_idx_t ds, address_t offset, unsigned char align);
5.54 -
5.55 -};
5.56 -
5.57 -/* Handle a general exception. */
5.58 -
5.59 -long ExecPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)
5.60 -{
5.61 - (void) region;
5.62 -
5.63 - printf("exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(®s), l4_utcb_exc_pc(®s));
5.64 -
5.65 - printf("r15 = %lx\n", regs.r15);
5.66 - printf("r14 = %lx\n", regs.r14);
5.67 - printf("r13 = %lx\n", regs.r13);
5.68 - printf("r12 = %lx\n", regs.r12);
5.69 - printf("r11 = %lx\n", regs.r11);
5.70 - printf("r10 = %lx\n", regs.r10);
5.71 - printf("r9 = %lx\n", regs.r9);
5.72 - printf("r8 = %lx\n", regs.r8);
5.73 - printf("rdi = %lx\n", regs.rdi);
5.74 - printf("rsi = %lx\n", regs.rsi);
5.75 - printf("rbp = %lx\n", regs.rbp);
5.76 - printf("pfa = %lx\n", regs.pfa);
5.77 - printf("rbx = %lx\n", regs.rbx);
5.78 - printf("rdx = %lx\n", regs.rdx);
5.79 - printf("rcx = %lx\n", regs.rcx);
5.80 - printf("rax = %lx\n", regs.rax);
5.81 - printf("trapno = %lx\n", regs.trapno);
5.82 - printf("err = %lx\n", regs.err);
5.83 - printf("ip = %lx\n", regs.ip);
5.84 - printf("flags = %lx\n", regs.flags);
5.85 - printf("sp = %lx\n", regs.sp);
5.86 - printf("ss = %lx\n", regs.ss);
5.87 - printf("fs_base = %lx\n", regs.fs_base);
5.88 - printf("gs_base = %lx\n", regs.gs_base);
5.89 -
5.90 - return L4_EOK;
5.91 -}
5.92 -
5.93 -#define DEBUG 0
5.94 -
5.95 -/* Handle a page fault using any configured regions. */
5.96 -
5.97 -long ExecPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)
5.98 -{
5.99 - l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;
5.100 -
5.101 -#if DEBUG
5.102 - printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);
5.103 -#endif
5.104 -
5.105 - MappedRegions::iterator it = _regions.upper_bound(addr);
5.106 -
5.107 - if (it != _regions.begin())
5.108 - it--;
5.109 - else
5.110 - {
5.111 - printf("not mapped!\n");
5.112 - return -L4_ENOMEM;
5.113 - }
5.114 -
5.115 - MappedRegion &r = it->second;
5.116 -
5.117 - if ((addr >= r.map_start) && (addr < r.map_start + r.size))
5.118 - {
5.119 - l4_addr_t page_addr = trunc(addr, L4_PAGESIZE);
5.120 -
5.121 - region->fpage = l4_fpage(r.start + (page_addr - r.map_start), L4_PAGESHIFT, r.flags);
5.122 - region->snd_base = page_addr;
5.123 -
5.124 -#if DEBUG
5.125 - printf("%lx...%lx from %lx...%lx offset %lx size %d rights %x\n",
5.126 - r.map_start, region->snd_base,
5.127 - r.start, l4_fpage_memaddr(region->fpage),
5.128 - addr - r.map_start,
5.129 - l4_fpage_size(region->fpage),
5.130 - l4_fpage_rights(region->fpage));
5.131 -
5.132 - printf("%lx -> ", addr);
5.133 -
5.134 - for (unsigned int i = 0; i < sizeof(l4_umword_t); i++)
5.135 - printf("%02x", *((unsigned char *)(r.start + (addr - r.map_start) + i)));
5.136 -
5.137 - printf("\n");
5.138 -#endif
5.139 -
5.140 - if (r.flags & L4RE_RM_F_W)
5.141 - l4_touch_rw((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.142 - else
5.143 - l4_touch_ro((const void *) (r.start + (page_addr - r.map_start)), L4_PAGESIZE);
5.144 -
5.145 - return L4_EOK;
5.146 - }
5.147 -
5.148 -#if DEBUG
5.149 - printf("not mapped!\n");
5.150 -#endif
5.151 -
5.152 - return -L4_ENOMEM;
5.153 -}
5.154 -
5.155 -/* Attach a region for provision when page faults occur. This is required in
5.156 - the initialisation of a program by the C library which requires a region
5.157 - mapper. */
5.158 -
5.159 -long ExecPager::attach(address_t *start, offset_t size, map_flags_t flags,
5.160 - l4_cap_idx_t ds, address_t offset, unsigned char align)
5.161 -{
5.162 -#if DEBUG
5.163 - printf("attach(%lx, %ld, %lx, ..., %lx, %d)\n", *start, size, flags, offset, align);
5.164 -#endif
5.165 -
5.166 - if (align < L4_PAGESHIFT)
5.167 - align = L4_PAGESHIFT;
5.168 -
5.169 - offset_t increment = 1UL << align;
5.170 - offset_t region_size = round(size, increment);
5.171 -
5.172 - /* Either attempt to find an address for the specified region, starting from
5.173 - any indicated address. */
5.174 -
5.175 - if (flags & L4RE_RM_F_SEARCH_ADDR)
5.176 - {
5.177 - address_t region_start = trunc(*start, increment);
5.178 - MappedRegions::iterator it = _regions.upper_bound(*start);
5.179 -
5.180 - if (!region_start)
5.181 - region_start += increment;
5.182 -
5.183 -#if DEBUG
5.184 - printf("-> search from %lx -> %lx...\n", *start, region_start);
5.185 -#endif
5.186 -
5.187 - /* Before last known region. */
5.188 -
5.189 - while (it != _regions.end())
5.190 - {
5.191 - MappedRegions::iterator next = it;
5.192 - MappedRegion &r = it->second;
5.193 - address_t start_limit;
5.194 - address_t end_limit = r.map_start;
5.195 -
5.196 - /* Consider any preceding region. If no such region exists, choose an
5.197 - address at the start of memory. */
5.198 -
5.199 - if (it == _regions.begin())
5.200 - start_limit = L4_PAGESIZE;
5.201 - else
5.202 - {
5.203 - it--;
5.204 - MappedRegion &pr = it->second;
5.205 - start_limit = pr.map_start + pr.size;
5.206 - it = next;
5.207 - }
5.208 -
5.209 - /* Test against the limits. */
5.210 -
5.211 - if (region_start < start_limit)
5.212 - region_start = round(start_limit, increment);
5.213 -
5.214 - /* Investigate subsequent regions if not enough space exists between the
5.215 - preceding region (or start of memory) and the current region. */
5.216 -
5.217 - if ((region_start + region_size) > end_limit)
5.218 - {
5.219 - it++;
5.220 - if (it == _regions.end())
5.221 - return -L4_ENOMEM;
5.222 - }
5.223 - else
5.224 - break;
5.225 - }
5.226 -
5.227 - /* Attach the provided dataspace.
5.228 - NOTE: This is only done in this implementation to support the paging
5.229 - mechanism. In a region mapper residing within the actual task, the
5.230 - dataspace's map operation would be invoked to obtain mappings. */
5.231 -
5.232 - l4_addr_t ds_start;
5.233 -
5.234 - long err = ipc_attach_dataspace(ds, size, (void **) &ds_start);
5.235 -
5.236 - if (err)
5.237 - return err;
5.238 -
5.239 - l4_touch_rw((const void *) ds_start, size);
5.240 -
5.241 -#if DEBUG
5.242 - printf("-> added region for %lx size %ld (%d)\n", region_start, region_size, page_order(region_size));
5.243 -#endif
5.244 -
5.245 - add(MappedRegion(ds_start, region_size, flags & L4RE_DS_F_RIGHTS_MASK, region_start));
5.246 -
5.247 - *start = region_start;
5.248 - return L4_EOK;
5.249 - }
5.250 -
5.251 - /* Or attempt to add the specified region at a specific address. */
5.252 -
5.253 - else
5.254 - {
5.255 - // NOTE: To be implemented.
5.256 -
5.257 -#if DEBUG
5.258 - printf("-> region of size %ld (%d) not added!\n", region_size, page_order(region_size));
5.259 -#endif
5.260 -
5.261 - return -L4_ENOMEM;
5.262 - }
5.263 -}
5.264 -
5.265 -
5.266 -
5.267 static ExecPager exec_pager;
5.268
5.269