1 /* 2 * A page mapper providing copied memory pages or deferring to another page 3 * mapper to satisfy file accesses. 4 * 5 * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA 21 */ 22 23 #include <l4/re/c/dataspace.h> 24 25 #include <string.h> 26 27 #include "copied_page_mapper.h" 28 29 30 31 /* Provide mapped pages populated with the given 'mapper', with pages obtained 32 from the given 'pages' collection. */ 33 34 CopiedPageMapper::CopiedPageMapper(GenericPageMapper *mapper) 35 : _mapper(mapper) 36 { 37 _size = _mapper->get_data_size(); 38 } 39 40 /* Upon deallocation, purge active pages. */ 41 42 CopiedPageMapper::~CopiedPageMapper() 43 { 44 } 45 46 /* Interface for the pager. */ 47 48 /* Return a flexpage providing access to the indicated file 'offset'. 49 50 The returned flexpage will either provide direct access to the underlying 51 file content or be a completely new flexpage modified through writes to 52 memory. */ 53 54 Flexpage *CopiedPageMapper::get(offset_t offset, map_flags_t flags) 55 { 56 Flexpage *f = find(offset); 57 58 /* Defer to the underlying page mapper if no flexpage was found. */ 59 60 if (f == NULL) 61 { 62 f = _mapper->get(offset, flags); 63 64 /* Replicate the underlying flexpage if writing. */ 65 66 if (flags & L4RE_DS_F_W) 67 { 68 Flexpage *rf = replicate_flexpage(offset, f); 69 _mapper->queue(f); 70 f = rf; 71 } 72 } 73 74 /* Upgrade the access flags. */ 75 76 f->upgrade(flags); 77 return f; 78 } 79 80 /* Queue the given 'flexpage'. */ 81 82 void CopiedPageMapper::queue(Flexpage *flexpage) 83 { 84 if (dynamic_cast<CopiedFlexpage *>(flexpage) == NULL) 85 _mapper->queue(flexpage); 86 } 87 88 /* Flush pages in the given range from 'start' with 'size'. */ 89 90 void CopiedPageMapper::flush_all(offset_t start, offset_t size) 91 { 92 /* NOTE: This might be superfluous since copy-on-write regions should not 93 update content. */ 94 95 _mapper->flush_all(start, size); 96 } 97 98 /* Return the maximum extent of the mapped resource. */ 99 100 offset_t CopiedPageMapper::get_data_size() 101 { 102 return _size; 103 } 104 105 /* Set the maximum extent of the mapped resource. */ 106 107 void CopiedPageMapper::set_data_size(offset_t size) 108 { 109 _size = size; 110 } 111 112 /* Internal flexpage retrieval methods. */ 113 114 /* Find an existing flexpage for 'offset'. */ 115 116 Flexpage *CopiedPageMapper::find(offset_t offset) 117 { 118 return _map.find(offset); 119 } 120 121 /* Replicate an underlying flexpage for the file 'offset' using the given 122 'flexpage'. */ 123 124 Flexpage *CopiedPageMapper::replicate_flexpage(offset_t offset, Flexpage *flexpage) 125 { 126 /* Obtain a new memory region and a new flexpage. */ 127 128 Region *region = _memory.region(flexpage->size); 129 Flexpage *replicated = new CopiedFlexpage(region); 130 131 /* Configure the flexpage for the file region. */ 132 133 replicated->reset(offset); 134 135 /* Copy the contents of the underlying flexpage. */ 136 137 memcpy((void *) region->start, (const void *) flexpage->region->start, flexpage->size); 138 139 /* Register the flexpage for future accesses. */ 140 141 _map.insert(replicated); 142 return replicated; 143 } 144 145 146 147 /* Copied flexpage constructor. */ 148 149 CopiedFlexpage::CopiedFlexpage(Region *region) 150 : Flexpage(region) 151 { 152 } 153 154 // vim: tabstop=4 expandtab shiftwidth=4