|
44 | 44 | use std::convert::From;
|
45 | 45 | use std::fs::File;
|
46 | 46 | use std::io;
|
| 47 | +use std::mem::size_of; |
47 | 48 | use std::ops::{BitAnd, BitOr, Deref};
|
48 | 49 | use std::rc::Rc;
|
49 | 50 | use std::sync::atomic::Ordering;
|
@@ -677,17 +678,62 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
|
677 | 678 | }
|
678 | 679 |
|
679 | 680 | fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> {
|
680 |
| - // `find_region` should really do what `to_region_addr` is doing right now, except |
681 |
| - // it should keep returning a `Result`. |
682 |
| - self.to_region_addr(addr) |
683 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
684 |
| - .and_then(|(region, region_addr)| region.store(val, region_addr, order)) |
| 681 | + let expected = size_of::<O>(); |
| 682 | + |
| 683 | + let completed = self.try_access( |
| 684 | + expected, |
| 685 | + addr, |
| 686 | + |offset, len, region_addr, region| -> Result<usize> { |
| 687 | + assert_eq!(offset, 0); |
| 688 | + if len < expected { |
| 689 | + return Err(Error::PartialBuffer { |
| 690 | + expected, |
| 691 | + completed: 0, |
| 692 | + }); |
| 693 | + } |
| 694 | + region.store(val, region_addr, order).map(|()| expected) |
| 695 | + }, |
| 696 | + )?; |
| 697 | + |
| 698 | + if completed < expected { |
| 699 | + Err(Error::PartialBuffer { |
| 700 | + expected, |
| 701 | + completed, |
| 702 | + }) |
| 703 | + } else { |
| 704 | + Ok(()) |
| 705 | + } |
685 | 706 | }
|
686 | 707 |
|
687 | 708 | fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> {
|
688 |
| - self.to_region_addr(addr) |
689 |
| - .ok_or(Error::InvalidGuestAddress(addr)) |
690 |
| - .and_then(|(region, region_addr)| region.load(region_addr, order)) |
| 709 | + let expected = size_of::<O>(); |
| 710 | + let mut result = None::<O>; |
| 711 | + |
| 712 | + let completed = self.try_access( |
| 713 | + expected, |
| 714 | + addr, |
| 715 | + |offset, len, region_addr, region| -> Result<usize> { |
| 716 | + assert_eq!(offset, 0); |
| 717 | + if len < expected { |
| 718 | + return Err(Error::PartialBuffer { |
| 719 | + expected, |
| 720 | + completed: 0, |
| 721 | + }); |
| 722 | + } |
| 723 | + result = Some(region.load(region_addr, order)?); |
| 724 | + Ok(expected) |
| 725 | + }, |
| 726 | + )?; |
| 727 | + |
| 728 | + if completed < expected { |
| 729 | + Err(Error::PartialBuffer { |
| 730 | + expected, |
| 731 | + completed, |
| 732 | + }) |
| 733 | + } else { |
| 734 | + // Must be set because `completed == expected` |
| 735 | + Ok(result.unwrap()) |
| 736 | + } |
691 | 737 | }
|
692 | 738 | }
|
693 | 739 |
|
|
0 commit comments