1#![warn(missing_docs)]
40
41use super::AccessError;
42use super::GuestMemory;
43use super::MemoryRead;
44use super::MemoryWrite;
45use super::PAGE_SIZE;
46use super::PAGE_SIZE64;
47use crate::InvalidGpn;
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq)]
51pub struct AddressRange {
52 pub start: u64,
54 pub end: u64,
56}
57
58impl AddressRange {
59 pub fn len(&self) -> u64 {
61 self.end - self.start
62 }
63
64 pub fn is_empty(&self) -> bool {
66 self.end == self.start
67 }
68}
69
70impl From<std::ops::Range<u64>> for AddressRange {
71 fn from(range: std::ops::Range<u64>) -> Self {
72 Self {
73 start: range.start,
74 end: range.end,
75 }
76 }
77}
78
79#[derive(Debug, Copy, Clone)]
107pub struct PagedRange<'a> {
108 start: usize,
111 end: usize,
114 gpns: &'a [u64],
116}
117
118impl<'a> PagedRange<'a> {
119 pub const PAGE_SIZE: usize = PAGE_SIZE;
121
122 pub const fn new(offset: usize, len: usize, gpns: &'a [u64]) -> Option<Self> {
126 let maxlen = gpns.len() * PAGE_SIZE;
127 if maxlen < offset || maxlen - offset < len {
128 return None;
129 }
130 Some(PagedRange {
131 start: offset,
132 end: offset + len,
133 gpns,
134 })
135 }
136
137 pub const fn empty() -> Self {
139 PagedRange {
140 start: 0,
141 end: 0,
142 gpns: &[],
143 }
144 }
145
146 pub fn try_subrange(&self, offset: usize, len: usize) -> Option<Self> {
148 if self.len() >= offset && self.len() - offset >= len {
149 Some(PagedRange {
150 start: self.start + offset,
151 end: self.start + offset + len,
152 gpns: self.gpns,
153 })
154 } else {
155 None
156 }
157 }
158
159 #[track_caller]
163 pub fn subrange(&self, offset: usize, len: usize) -> Self {
164 self.try_subrange(offset, len)
165 .unwrap_or_else(|| panic!("invalid subrange: {} + {} > {}", offset, len, self.len()))
166 }
167
168 pub fn len(&self) -> usize {
170 self.end - self.start
171 }
172
173 pub fn is_empty(&self) -> bool {
175 self.start == self.end
176 }
177
178 pub fn offset(&self) -> usize {
183 self.start % PAGE_SIZE
184 }
185
186 pub fn gpns(&self) -> &'a [u64] {
188 let start_page = self.start / PAGE_SIZE;
189 let end_page = self.end.div_ceil(PAGE_SIZE);
190 &self.gpns[start_page..end_page]
191 }
192
193 pub fn skip(&mut self, len: usize) {
197 assert!(self.len() >= len);
198 self.start += len;
199 }
200
201 pub fn truncate(&mut self, len: usize) {
205 assert!(self.len() >= len);
206 self.end = self.start + len;
207 }
208
209 pub fn split(self, offset: usize) -> (Self, Self) {
213 assert!(self.len() >= offset);
214 (
215 Self {
216 start: self.start,
217 end: self.start + offset,
218 gpns: self.gpns,
219 },
220 Self {
221 start: self.start + offset,
222 end: self.end,
223 gpns: self.gpns,
224 },
225 )
226 }
227
228 pub fn try_split(self, offset: usize) -> Option<(Self, Self)> {
231 if self.len() >= offset {
232 Some((
233 Self {
234 start: self.start,
235 end: self.start + offset,
236 gpns: self.gpns,
237 },
238 Self {
239 start: self.start + offset,
240 end: self.end,
241 gpns: self.gpns,
242 },
243 ))
244 } else {
245 None
246 }
247 }
248
249 pub fn pop_front_range(&mut self) -> Option<Result<AddressRange, InvalidGpn>> {
251 if self.is_empty() {
252 None
253 } else {
254 let start_page = self.start / PAGE_SIZE;
255 let end_page = self.end.div_ceil(PAGE_SIZE);
256 let mut page = start_page + 1;
257 while page < end_page && self.gpns[page - 1] + 1 == self.gpns[page] {
258 page += 1;
259 }
260
261 let end = (page * PAGE_SIZE).min(self.end);
262
263 let gpa = match crate::gpn_to_gpa(self.gpns[start_page]) {
264 Ok(gpa) => gpa,
265 Err(e) => return Some(Err(e)),
266 };
267 let start_gpa = gpa + self.start as u64 % PAGE_SIZE64;
268 let range = AddressRange {
269 start: start_gpa,
270 end: start_gpa + (end - self.start) as u64,
271 };
272 self.start = end;
273 Some(Ok(range))
274 }
275 }
276
277 pub fn reader(self, mem: &'a GuestMemory) -> PagedRangeReader<'a> {
279 PagedRangeReader { range: self, mem }
280 }
281
282 pub fn writer(self, mem: &'a GuestMemory) -> PagedRangeWriter<'a> {
284 PagedRangeWriter { range: self, mem }
285 }
286
287 pub fn ranges(self) -> PagedRangeRangeIter<'a> {
290 PagedRangeRangeIter(self)
291 }
292}
293
294#[derive(Debug, Clone)]
296pub struct PagedRangeRangeIter<'a>(PagedRange<'a>);
297
298impl Iterator for PagedRangeRangeIter<'_> {
299 type Item = Result<AddressRange, InvalidGpn>;
300
301 fn next(&mut self) -> Option<Self::Item> {
302 self.0.pop_front_range()
303 }
304}
305
306pub struct PagedRangeReader<'a> {
308 range: PagedRange<'a>,
309 mem: &'a GuestMemory,
310}
311
312impl MemoryRead for PagedRangeReader<'_> {
313 fn read(&mut self, data: &mut [u8]) -> Result<&mut Self, AccessError> {
314 let range = self
315 .range
316 .try_subrange(0, data.len())
317 .ok_or_else(|| AccessError::OutOfRange(self.len(), data.len()))?;
318 self.mem
319 .read_range(&range, data)
320 .map_err(AccessError::Memory)?;
321 self.range.skip(data.len());
322 Ok(self)
323 }
324
325 fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
326 if self.len() < len {
327 return Err(AccessError::OutOfRange(self.len(), len));
328 }
329 self.range.skip(len);
330 Ok(self)
331 }
332
333 fn len(&self) -> usize {
334 self.range.len()
335 }
336}
337
338pub struct PagedRangeWriter<'a> {
340 range: PagedRange<'a>,
341 mem: &'a GuestMemory,
342}
343
344impl MemoryWrite for PagedRangeWriter<'_> {
345 fn write(&mut self, data: &[u8]) -> Result<(), AccessError> {
346 let range = self
347 .range
348 .try_subrange(0, data.len())
349 .ok_or_else(|| AccessError::OutOfRange(self.len(), data.len()))?;
350 self.mem
351 .write_range(&range, data)
352 .map_err(AccessError::Memory)?;
353 self.range.skip(data.len());
354 Ok(())
355 }
356
357 fn fill(&mut self, val: u8, len: usize) -> Result<(), AccessError> {
358 let range = self
359 .range
360 .try_subrange(0, len)
361 .ok_or_else(|| AccessError::OutOfRange(self.len(), len))?;
362 self.mem
363 .fill_range(&range, val)
364 .map_err(AccessError::Memory)?;
365 self.range.skip(len);
366 Ok(())
367 }
368
369 fn len(&self) -> usize {
370 self.range.len()
371 }
372}
373
374#[derive(Debug, Clone)]
376pub struct PagedRanges<'a, T> {
377 ranges: T,
378 current: Option<PagedRange<'a>>,
379 start: usize,
380 end: usize,
381}
382
383impl<'a, T: Iterator<Item = PagedRange<'a>> + Clone> PagedRanges<'a, T> {
384 pub fn new<I>(ranges: I) -> Self
386 where
387 I: IntoIterator<IntoIter = T>,
388 {
389 let ranges = ranges.into_iter();
390 let len = ranges.clone().map(|range| range.len()).sum();
391 Self {
392 ranges,
393 current: None,
394 start: 0,
395 end: len,
396 }
397 }
398}
399
400impl<'a, T: Iterator<Item = PagedRange<'a>>> PagedRanges<'a, T> {
401 pub fn len(&self) -> usize {
403 self.end - self.start
404 }
405
406 pub fn is_empty(&self) -> bool {
408 self.start == self.end
409 }
410
411 pub fn skip(&mut self, mut len: usize) {
413 assert!(self.len() >= len);
414 while len > 0 {
415 let n = self.current(len).len();
416 self.advance(n);
417 len -= n;
418 }
419 }
420
421 pub fn truncate(&mut self, len: usize) {
425 assert!(self.len() >= len);
426 self.end = self.start + len;
427 }
428
429 pub fn paged_ranges(self) -> PagedRangesIter<'a, T> {
431 PagedRangesIter(self)
432 }
433
434 pub fn reader(self, mem: &'a GuestMemory) -> PagedRangesReader<'a, T> {
436 PagedRangesReader { views: self, mem }
437 }
438
439 pub fn writer(self, mem: &'a GuestMemory) -> PagedRangesWriter<'a, T> {
441 PagedRangesWriter { views: self, mem }
442 }
443
444 fn current(&mut self, max_len: usize) -> PagedRange<'a> {
445 debug_assert!(max_len <= self.len());
446 if self.current.is_none() {
447 self.current = self.ranges.next();
448 }
449 let range = self.current.unwrap();
450 range.subrange(self.start, max_len.min(range.len() - self.start))
451 }
452
453 fn advance(&mut self, n: usize) {
454 let current = self.current.as_ref().unwrap();
455 self.start += n;
456 if self.start == current.len() {
457 self.current = None;
458 self.end -= self.start;
459 self.start = 0;
460 }
461 }
462}
463
464pub struct PagedRangesIter<'a, T>(PagedRanges<'a, T>);
466
467impl<'a, T: Iterator<Item = PagedRange<'a>>> Iterator for PagedRangesIter<'a, T> {
468 type Item = PagedRange<'a>;
469
470 fn next(&mut self) -> Option<Self::Item> {
471 if self.0.is_empty() {
472 return None;
473 }
474 let current = self
475 .0
476 .current
477 .take()
478 .or_else(|| self.0.ranges.next())
479 .unwrap();
480 let offset = self.0.start;
481 let len = self.0.end.min(current.len()) - offset;
482 self.0.end -= offset + len;
483 self.0.current = None;
484 self.0.start = 0;
485 Some(current.subrange(offset, len))
486 }
487}
488
489#[derive(Debug, Clone)]
491pub struct PagedRangesReader<'a, T> {
492 views: PagedRanges<'a, T>,
493 mem: &'a GuestMemory,
494}
495
496impl<'a, T> PagedRangesReader<'a, T> {
497 pub fn into_inner(self) -> PagedRanges<'a, T> {
499 self.views
500 }
501}
502
503impl<'a, T: Iterator<Item = PagedRange<'a>>> MemoryRead for PagedRangesReader<'a, T> {
504 fn read(&mut self, mut data: &mut [u8]) -> Result<&mut Self, AccessError> {
505 if self.len() < data.len() {
506 return Err(AccessError::OutOfRange(self.len(), data.len()));
507 }
508 while !data.is_empty() {
509 let range = self.views.current(data.len());
510 let (buf, rest) = data.split_at_mut(range.len());
511 self.mem
512 .read_range(&range, buf)
513 .map_err(AccessError::Memory)?;
514 self.views.advance(range.len());
515 data = rest;
516 }
517 Ok(self)
518 }
519
520 fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
521 if self.len() < len {
522 return Err(AccessError::OutOfRange(self.len(), len));
523 }
524 self.views.skip(len);
525 Ok(self)
526 }
527
528 fn len(&self) -> usize {
529 self.views.len()
530 }
531}
532
533#[derive(Debug)]
535pub struct PagedRangesWriter<'a, T> {
536 views: PagedRanges<'a, T>,
537 mem: &'a GuestMemory,
538}
539
540impl<'a, T> PagedRangesWriter<'a, T> {
541 pub fn into_inner(self) -> PagedRanges<'a, T> {
543 self.views
544 }
545}
546
547impl<'a, T: Iterator<Item = PagedRange<'a>>> MemoryWrite for PagedRangesWriter<'a, T> {
548 fn write(&mut self, mut data: &[u8]) -> Result<(), AccessError> {
549 if self.len() < data.len() {
550 return Err(AccessError::OutOfRange(self.len(), data.len()));
551 }
552 while !data.is_empty() {
553 let range = self.views.current(data.len());
554 let (buf, rest) = data.split_at(range.len());
555 self.mem
556 .write_range(&range, buf)
557 .map_err(AccessError::Memory)?;
558 self.views.advance(range.len());
559 data = rest;
560 }
561 Ok(())
562 }
563
564 fn fill(&mut self, val: u8, mut len: usize) -> Result<(), AccessError> {
565 if self.len() < len {
566 return Err(AccessError::OutOfRange(self.len(), len));
567 }
568 while len > 0 {
569 let range = self.views.current(len);
570 self.mem
571 .fill_range(&range, val)
572 .map_err(AccessError::Memory)?;
573 self.views.advance(range.len());
574 len -= range.len();
575 }
576 Ok(())
577 }
578
579 fn len(&self) -> usize {
580 self.views.len()
581 }
582}
583
584#[cfg(test)]
585mod tests {
586 use super::*;
587
588 #[test]
589 fn test_ranges() {
590 assert!(PagedRange::new(1, PAGE_SIZE, &[1]).is_none());
591
592 let view1 = PagedRange::new(0x123, 0x2012, &[0x11, 0x22, 0x33]).unwrap();
593 let view2 = PagedRange::new(0x456, 0x2017, &[0x111, 0x112, 0x222]).unwrap();
594 let views = [view1, view2];
595 let mut multi = PagedRanges::new(views.iter().copied());
596 multi.skip(0x100);
597 multi.truncate(0x2f29);
598
599 let r1: Result<Vec<_>, _> = multi.paged_ranges().flat_map(|r| r.ranges()).collect();
600 let r2: Vec<_> = [
601 0x11223..0x12000,
602 0x22000..0x23000,
603 0x33000..0x33135,
604 0x111456..0x11246d,
605 ]
606 .map(AddressRange::from)
607 .to_vec();
608
609 assert_eq!(&r1.unwrap(), &r2);
610 }
611}