1 /* 2 * Generic pager functionality. 3 * 4 * Copyright (C) 2021 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 "dataspace_server.h" 23 #include "ipc.h" 24 #include "pager.h" 25 26 27 28 /* Initialise the pager with a page mapper and the given flags controlling 29 access to a file. */ 30 31 Pager::Pager(PageMapper *mapper, map_flags_t flags) 32 : _start(0), _size(0), _mapper(mapper), _flags(flags) 33 { 34 } 35 36 /* Close the pager. */ 37 38 void Pager::close() 39 { 40 } 41 42 /* Flush data to the file. */ 43 44 long Pager::flush(offset_t populated_size, offset_t *size) 45 { 46 _mapper->flush_all(_start, populated_size); 47 48 *size = _mapper->get_data_size(); 49 return L4_EOK; 50 } 51 52 /* Resize the underlying file. */ 53 54 long Pager::resize(offset_t *size) 55 { 56 _mapper->set_data_size(*size); 57 58 *size = _mapper->get_data_size(); 59 return L4_EOK; 60 } 61 62 /* Expose a region of the file. */ 63 64 long Pager::mmap(offset_t position, offset_t length, offset_t *start_pos, 65 offset_t *end_pos, offset_t *size) 66 { 67 /* Define region characteristics. */ 68 69 _start = trunc(position, PAGE_SIZE); 70 _size = round(position + length, PAGE_SIZE) - _start; 71 72 /* Return the start and end positions plus populated extent. */ 73 74 *start_pos = _start; 75 *end_pos = _start + _size; 76 *size = _mapper->get_data_size(); 77 78 return L4_EOK; 79 } 80 81 /* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' 82 (flexpage offset). */ 83 84 long Pager::map(offset_t offset, address_t hot_spot, map_flags_t flags, 85 l4_snd_fpage_t *region) 86 { 87 offset_t file_offset = _start + offset; 88 offset_t max_offset = _start + _size; 89 90 /* Prevent access beyond that defined by the pager. */ 91 92 if (flags & ~_flags) 93 return -L4_EACCESS; 94 95 Flexpage *flexpage = _mapper->get(file_offset, flags); 96 97 /* Issue the flexpage via the IPC system. */ 98 99 long err = ipc_prepare_flexpage(flexpage, file_offset, max_offset, hot_spot, 100 flags, region); 101 102 if (!err) 103 err = complete_Dataspace_map(*region); 104 105 /* After the flexpage is issued, it is queued for future reuse. */ 106 107 _mapper->queue(flexpage); 108 109 if (err) 110 return err; 111 112 return IPC_MESSAGE_SENT; 113 } 114 115 /* Return the total size of the data. */ 116 117 offset_t Pager::get_data_size() 118 { 119 return _mapper->get_data_size(); 120 } 121 122 // vim: tabstop=4 expandtab shiftwidth=4