L4Re/departure

libexec/lib/src/internal_pager.cc

574:b2aa14224c26
11 months ago Paul Boddie Ignored unused parameters.
     1 /*     2  * A system pager implementation residing in the same task as a program.     3  *     4  * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software; you can redistribute it and/or     7  * modify it under the terms of the GNU General Public License as     8  * published by the Free Software Foundation; either version 2 of     9  * the License, or (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program; if not, write to the Free Software    18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    19  * Boston, MA  02110-1301, USA    20  */    21     22 #include <l4/re/env.h>    23 #include <l4/re/c/dataspace.h>    24 #include <l4/re/c/rm.h>    25 #include <l4/util/util.h>    26     27 #include <ipc/cap_alloc.h>    28 #include <mem/memory_utils.h>    29 #include <systypes/base.h>    30     31 #include <stdio.h>    32     33 #include "dataspace_client.h"    34 #include "internal_pager.h"    35 #include "mapped_region.h"    36 #include "pager_object_server.h"    37     38     39     40 #define DEBUG 0    41     42     43     44 /* A simple system pager also acting as a region mapper. */    45     46 InternalPager::InternalPager(address_t start, address_t end)    47 : ExecPager(start, end)    48 {    49 }    50     51 ipc_server_default_config_type InternalPager::config()    52 {    53   return config_PagerObject;    54 }    55     56     57     58 /* Close the pager. */    59     60 void InternalPager::close()    61 {    62   printf("Internal pager closing...\n");    63 }    64     65     66     67 /* Handle a general exception. */    68     69 long InternalPager::exception(l4_exc_regs_t regs, l4_snd_fpage_t *region)    70 {    71   (void) region;    72     73   printf("InternalPager::exception(...) -> pfa = %lx, pc = %lx\n", l4_utcb_exc_pfa(&regs), l4_utcb_exc_pc(&regs));    74     75   while (1)    76     l4_sleep_forever();    77     78   return L4_EOK;    79 }    80     81 /* Handle a page fault using any configured regions. */    82     83 long InternalPager::page_fault(l4_umword_t pfa, l4_umword_t pc, l4_snd_fpage_t *region)    84 {    85   l4_umword_t addr = pfa & ~7UL, flags = pfa & 7;    86     87 #if DEBUG    88   printf("page_fault(%lx, %lx) -> %lx (%lx) -> ", pfa, pc, addr, flags);    89   l4_thread_regs_t *regs = l4_utcb_tcr();    90   printf("regs = %p\n; regs->user[0] = %lx\n", regs, regs->user[0]);    91 #endif    92     93   /* Obtain a region supporting the fault address. */    94     95   MemoryArea *r, *parent;    96   long err = _area.find(addr, &r, &parent);    97     98   if (!err)    99   {   100     address_t window_size = L4_PAGESIZE;   101     address_t window_base = trunc(addr, window_size);   102     address_t offset = addr - r->area_start();   103     address_t page_addr = trunc(addr, L4_PAGESIZE);   104     address_t hot_spot = page_addr - window_base;   105    106     /* Interact with the region's dataspace, specifying a receive window for a   107        map operation. Here, a single page is specified. */   108    109     client_Dataspace dataspace(r->dataspace());   110     l4_snd_fpage_t rw_region = {0, l4_fpage(window_base, L4_PAGESHIFT, 0)};   111     map_flags_t map_flags = map_flags_for_fault(flags);   112    113 #if DEBUG   114     printf("window_base = %lx; window_size = %lx\n", window_base, window_size);   115     printf("region = {%lx, {%lx, %d}}\n", rw_region.snd_base, l4_fpage_memaddr(rw_region.fpage), l4_fpage_size(rw_region.fpage));   116     printf("map(%lx, %lx, %lx) -> %lx\n", offset, hot_spot, map_flags, r->dataspace());   117 #endif   118    119     err = dataspace.map(offset, hot_spot, map_flags & r->flags(), &rw_region);   120    121     /* Indicate an unspecified result, since the mapping should have taken   122        place. */   123    124     *region = {0, l4_fpage_invalid()};   125    126     return err;   127   }   128    129   printf("not mapped at %lx for pc %lx\n", addr, pc);   130    131   return err;   132 }   133    134 /* Attach a region for provision when page faults occur. This is required in   135    the initialisation of a program by the C library which requires a region   136    mapper. */   137    138 long InternalPager::attach(address_t *start, address_t size, map_flags_t flags,   139                            l4_cap_idx_t ds, address_t offset,   140                            unsigned char align)   141 {   142   /* NOTE: The offset apparently indicates the offset within the dataspace of   143            the start of the region. */   144    145   (void) offset;   146    147   MemoryArea *area;   148   long err = ExecPager::find(start, &size, flags, align, &area);   149    150   if (!err)   151   {   152     MappedRegion r(*start, *start + size, flags & L4RE_DS_F_RIGHTS_MASK, ds);   153     area->add(r);   154   }   155   else   156     ipc_cap_free_um(ds);   157    158   return err;   159 }   160    161 long InternalPager::detach(address_t addr, address_t size, map_flags_t flags,   162                            address_t *start, address_t *rsize, l4_cap_idx_t *ds)   163 {   164   (void) size; (void) flags;   165    166   /* Obtain the region supporting the given address.   167      NOTE: All regions within the given range should be detached. */   168    169   MemoryArea *r, *parent;   170   long err = _area.find(addr, &r, &parent);   171    172   if (!err)   173   {   174     *start = r->area_start();   175     *rsize = r->area_end() - r->area_start();   176     *ds = r->dataspace();   177     parent->remove(*r);   178   }   179    180   return err;   181 }   182    183 long InternalPager::reserve_area(address_t *start, address_t size,   184                                  map_flags_t flags, unsigned char align)   185 {   186   MemoryArea *area;   187   long err = ExecPager::find(start, &size, flags, align, &area);   188    189   if (!err)   190   {   191     /* Add an object acting like a region but without any associated   192        dataspace. */   193    194     if (flags & L4RE_RM_F_RESERVED)   195     {   196       ReservedMemoryArea r(*start, *start + size);   197       area->add(r);   198     }   199    200     /* Add an object permitting regions to be added within it. */   201    202     else   203     {   204       AvailableMemoryArea r(*start, *start + size);   205       area->add(r);   206     }   207   }   208    209   return err;   210 }   211    212 /* vim: tabstop=2 expandtab shiftwidth=2   213 */