L4Re/departure

libfsserver/lib/generic/pager.cc

618:7123a7307a82
8 months ago Paul Boddie Introduced some debugging output control.
     1 /*     2  * Generic pager functionality.     3  *     4  * Copyright (C) 2021, 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 <mem/ipc.h>    23     24 #include "dataspace_server.h"    25 #include "pager.h"    26     27 #include "copied_page_mapper.h"    28 #include "masked_page_mapper.h"    29     30     31     32 /* Initialise the pager with a page mapper and the given flags controlling    33    access to a file. */    34     35 Pager::Pager(GenericPageMapper *mapper, map_flags_t map_flags)    36 : _start(0), _size(0),    37   _mapper(mapper), _mapper_base(mapper), _mapper_masked(NULL),    38   _mapper_copied(NULL),    39   _map_flags(map_flags)    40 {    41 }    42     43 /* Close the pager. */    44     45 void Pager::close()    46 {    47     if (_mapper_masked != NULL)    48     {    49         delete _mapper_masked;    50         _mapper_masked = NULL;    51     }    52     53     if (_mapper_copied != NULL)    54     {    55         delete _mapper_copied;    56         _mapper_copied = NULL;    57     }    58 }    59     60 /* Flush data to the file. */    61     62 long Pager::flush(offset_t populated_size, offset_t *size)    63 {    64     _mapper->flush_all(_start, populated_size);    65     66     *size = _mapper->get_data_size();    67     return L4_EOK;    68 }    69     70 /* Resize the file. This will only resize the underlying file where masking and    71    copy-on-write mapping is not being performed. */    72     73 long Pager::resize(offset_t *size)    74 {    75     _mapper->set_data_size(*size);    76     77     *size = _mapper->get_data_size();    78     return L4_EOK;    79 }    80     81 /* Expose a region of the file. */    82     83 long Pager::mmap(offset_t position, offset_t length,    84                  offset_t start_visible, offset_t end_visible,    85                  offset_t *start_pos, offset_t *end_pos, offset_t *size)    86 {    87     /* Define region characteristics. */    88     89     _start = trunc(position, PAGE_SIZE);    90     _size = round(position + length, PAGE_SIZE) - _start;    91     92     /* Return the start and end positions plus file size. */    93     94     *start_pos = _start;    95     *end_pos = _start + _size;    96     *size = _mapper_base->get_data_size();    97     98     /* Permit masking of mapped regions. */    99    100     if ((start_visible || end_visible) &&   101         ((*start_pos != start_visible) || (*end_pos != end_visible)))   102     {   103         /* Introduce the masked page and copied page mappers. */   104    105         _mapper_masked = new MaskedPageMapper(_mapper_base, start_visible, end_visible);   106         _mapper_copied = new CopiedPageMapper(_mapper_masked);   107         _mapper = _mapper_copied;   108     }   109     else   110         _mapper = _mapper_base;   111    112     return L4_EOK;   113 }   114    115 /* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot'   116    (flexpage offset). */   117    118 long Pager::map(offset_t offset, map_address_t hot_spot, map_flags_t map_flags,   119                 l4_snd_fpage_t *region)   120 {   121     offset_t file_offset = _start + offset;   122     offset_t max_offset = _start + _size;   123    124     /* Prevent access beyond that defined by the pager.   125        NOTE: Permitting executable requests here. This needs to be configured   126              when opening the pager or by another means. */   127    128     if (map_flags & (~(_map_flags | L4RE_DS_F_X)))   129         return -L4_EACCESS;   130    131     /* Obtain a flexpage from the page mapper. */   132    133     Flexpage *flexpage = _mapper->get(file_offset, map_flags);   134    135     /* Issue the flexpage via the IPC system. */   136    137     long err = ipc_prepare_flexpage(flexpage, file_offset, max_offset,   138                                     hot_spot, map_flags, region);   139    140     if (!err)   141         err = complete_Dataspace_map(*region);   142    143     /* After the obtained flexpage is issued, it is queued for future reuse, if   144        appropriate for the mapper concerned. */   145    146     _mapper->queue(flexpage);   147    148     if (err)   149         return err;   150    151     return IPC_MESSAGE_SENT;   152 }   153    154 /* Return the total size of the data. */   155    156 offset_t Pager::get_data_size()   157 {   158     return _mapper->get_data_size();   159 }   160    161 // vim: tabstop=4 expandtab shiftwidth=4