L4Re/departure

Annotated libexec/lib/src/internal_pager.cc

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