L4Re/departure

libexec/lib/src/segment.cc

515:bae2ddb47ecd
20 months ago Paul Boddie Introduced support for reserve_area in the internal pager along with different kinds of memory area. This permits the execution of threaded programs.
     1 /*     2  * Program memory segment support.     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/sys/err.h>    23     24 #include <ipc/cap_alloc.h>    25 #include <ipc/mem_ipc.h>    26 #include <mem/memory_utils.h>    27     28 #include <stdio.h>    29 #include <string.h>    30     31 #include "segment.h"    32     33     34     35 /* Free the allocated resources. */    36     37 Segment::~Segment()    38 {    39   if (_allocated)    40   {    41     if (_attached)    42       ipc_detach_dataspace(_buf);    43     44     /* Also unmap the dataspace, not apparently done by the underlying    45        functions. */    46     47     if (l4_is_valid_cap(_ds))    48       ipc_cap_free_um(_ds);    49   }    50   else if (client_opened(_file))    51   {    52     client_close(_file);    53   }    54 }    55     56 /* Common initialisation. */    57     58 void Segment::init()    59 {    60   _region_base = trunc(region_address(), L4_PAGESIZE);    61   _region_content_offset = region_address() - _region_base;    62     63   /* Expand the region size. */    64     65   _region_allocated_size = round(region_size() + _region_content_offset, L4_PAGESIZE);    66 }    67     68 /* Return the capability of the dataspace providing the memory. */    69     70 l4_cap_idx_t Segment::cap()    71 {    72   return _ds;    73 }    74     75 /* Return the address of allocated memory. */    76     77 char *Segment::address()    78 {    79   return _buf;    80 }    81     82 /* Return the size of the allocated memory. */    83     84 offset_t Segment::size()    85 {    86   return _region_allocated_size;    87 }    88     89 /* Allocate a writable region for the segment. */    90     91 long Segment::allocate(bool attach)    92 {    93   _allocated = true;    94   _attached = attach;    95     96   if (attach)    97     return ipc_allocate_align(_region_allocated_size,    98                               L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,    99                               L4_PAGESHIFT, (void **) &_buf, &_ds);   100   else   101     return ipc_new_dataspace(_region_allocated_size,   102                              L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW,   103                              L4_PAGESHIFT, &_ds);   104 }   105    106 /* Fill a segment region with file content. */   107    108 long Segment::fill(file_t *file, bool attach)   109 {   110   /* Provide the exposed file contents in a masked memory mapped region, or if   111      not attaching the region, merely request access via a dataspace. */   112    113   if (attach)   114   {   115     _buf = (char *) client_mmap(file,   116                                 file_offset() - _region_content_offset,   117                                 _region_allocated_size,   118                                 file_offset(),   119                                 file_offset() + file_contents(),   120                                 region_flags());   121     if (_buf == NULL)   122       return -L4_EIO;   123   }   124   else   125   {   126     long err = file_mmap_only(file,   127                               file_offset() - _region_content_offset,   128                               _region_allocated_size,   129                               file_offset(),   130                               file_offset() + file_contents());   131     if (err)   132       return err;   133   }   134    135   _file = file;   136   _ds = file->ref;   137   return L4_EOK;   138 }   139    140 /* Define and return the mapped region for the segment. */   141    142 MappedRegion &Segment::region()   143 {   144   _region = MappedRegion(_region_base, _region_base + _region_allocated_size,   145                          region_flags(), _ds, (l4_addr_t) _buf);   146   return _region;   147 }   148    149 /* Define and return the region dataspace details. */   150    151 struct exec_region &Segment::exec_region()   152 {   153   _exec_region = (struct exec_region) {_region_base, _region_allocated_size, region_flags(), _ds};   154   return _exec_region;   155 }   156    157 /* Return the mapped address corresponding to the given address. */   158    159 l4_addr_t Segment::region_address(char *address)   160 {   161   return (l4_addr_t) ((address - _buf) + (char *) _region_base);   162 }   163    164 l4_addr_t Segment::region_address(l4_addr_t address)   165 {   166   return (address - (l4_addr_t) _buf) + _region_base;   167 }   168    169    170    171 /* Initialise a memory segment using explicit parameters. */   172    173 ExplicitSegment::ExplicitSegment(l4_addr_t base, offset_t size,   174                                  l4re_rm_flags_t flags, offset_t file_offset,   175                                  offset_t file_contents)   176 : _base(base), _size(size), _flags(flags), _file_offset(file_offset),   177   _file_contents(file_contents)   178 {   179   init();   180 }   181    182 /* Return the amount of file content loaded into the segment. */   183    184 bool ExplicitSegment::loadable()   185 {   186   return false;   187 }   188    189 offset_t ExplicitSegment::file_contents()   190 {   191   return _file_contents;   192 }   193    194 offset_t ExplicitSegment::file_offset()   195 {   196   return _file_offset;   197 }   198    199 l4_addr_t ExplicitSegment::region_address()   200 {   201   return _base;   202 }   203    204 offset_t ExplicitSegment::region_size()   205 {   206   return _size;   207 }   208    209 /* Return the region flags for the segment. */   210    211 l4re_rm_flags_t ExplicitSegment::region_flags()   212 {   213   return _flags;   214 }   215    216 /* vim: tabstop=2 expandtab shiftwidth=2   217 */