1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Represents an address in the guest's memory space.
6 
7 use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
8 use std::fmt::{self, Display};
9 use std::ops::{BitAnd, BitOr};
10 
11 /// Represents an Address in the guest's memory.
12 #[derive(Clone, Copy, Debug)]
13 pub struct GuestAddress(pub u64);
14 
15 impl GuestAddress {
16     /// Returns the offset from this address to the given base address.
17     ///
18     /// # Examples
19     ///
20     /// ```
21     /// # use vm_memory::GuestAddress;
22     ///   let base = GuestAddress(0x100);
23     ///   let addr = GuestAddress(0x150);
24     ///   assert_eq!(addr.offset_from(base), 0x50u64);
25     /// ```
offset_from(self, base: GuestAddress) -> u6426     pub fn offset_from(self, base: GuestAddress) -> u64 {
27         self.0 - base.0
28     }
29 
30     /// Returns the address as a u64 offset from 0x0.
31     /// Use this when a raw number is needed to pass to the kernel.
offset(self) -> u6432     pub fn offset(self) -> u64 {
33         self.0
34     }
35 
36     /// Returns the result of the add or None if there is overflow.
checked_add(self, other: u64) -> Option<GuestAddress>37     pub fn checked_add(self, other: u64) -> Option<GuestAddress> {
38         self.0.checked_add(other).map(GuestAddress)
39     }
40 
41     /// Returns the result of the base address + the size.
42     /// Only use this when `offset` is guaranteed not to overflow.
unchecked_add(self, offset: u64) -> GuestAddress43     pub fn unchecked_add(self, offset: u64) -> GuestAddress {
44         GuestAddress(self.0 + offset)
45     }
46 
47     /// Returns the result of the subtraction of None if there is underflow.
checked_sub(self, other: u64) -> Option<GuestAddress>48     pub fn checked_sub(self, other: u64) -> Option<GuestAddress> {
49         self.0.checked_sub(other).map(GuestAddress)
50     }
51 
52     /// Returns the bitwise and of the address with the given mask.
mask(self, mask: u64) -> GuestAddress53     pub fn mask(self, mask: u64) -> GuestAddress {
54         GuestAddress(self.0 & mask as u64)
55     }
56 }
57 
58 impl BitAnd<u64> for GuestAddress {
59     type Output = GuestAddress;
60 
bitand(self, other: u64) -> GuestAddress61     fn bitand(self, other: u64) -> GuestAddress {
62         GuestAddress(self.0 & other as u64)
63     }
64 }
65 
66 impl BitOr<u64> for GuestAddress {
67     type Output = GuestAddress;
68 
bitor(self, other: u64) -> GuestAddress69     fn bitor(self, other: u64) -> GuestAddress {
70         GuestAddress(self.0 | other as u64)
71     }
72 }
73 
74 impl PartialEq for GuestAddress {
eq(&self, other: &GuestAddress) -> bool75     fn eq(&self, other: &GuestAddress) -> bool {
76         self.0 == other.0
77     }
78 }
79 impl Eq for GuestAddress {}
80 
81 impl Ord for GuestAddress {
cmp(&self, other: &GuestAddress) -> Ordering82     fn cmp(&self, other: &GuestAddress) -> Ordering {
83         self.0.cmp(&other.0)
84     }
85 }
86 
87 impl PartialOrd for GuestAddress {
partial_cmp(&self, other: &GuestAddress) -> Option<Ordering>88     fn partial_cmp(&self, other: &GuestAddress) -> Option<Ordering> {
89         Some(self.cmp(other))
90     }
91 }
92 
93 impl Display for GuestAddress {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result94     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95         write!(f, "{:#x}", self.0)
96     }
97 }
98 
99 #[cfg(test)]
100 mod tests {
101     use super::*;
102 
103     #[test]
equals()104     fn equals() {
105         let a = GuestAddress(0x300);
106         let b = GuestAddress(0x300);
107         let c = GuestAddress(0x301);
108         assert_eq!(a, b);
109         assert_eq!(b, a);
110         assert_ne!(a, c);
111         assert_ne!(c, a);
112     }
113 
114     #[test]
cmp()115     fn cmp() {
116         let a = GuestAddress(0x300);
117         let b = GuestAddress(0x301);
118         assert!(a < b);
119         assert!(b > a);
120         assert!(!(a < a));
121     }
122 
123     #[test]
mask()124     fn mask() {
125         let a = GuestAddress(0x5050);
126         assert_eq!(GuestAddress(0x5000), a & 0xff00u64);
127         assert_eq!(GuestAddress(0x5055), a | 0x0005u64);
128     }
129 
130     #[test]
add_sub()131     fn add_sub() {
132         let a = GuestAddress(0x50);
133         let b = GuestAddress(0x60);
134         assert_eq!(Some(GuestAddress(0xb0)), a.checked_add(0x60));
135         assert_eq!(0x10, b.offset_from(a));
136     }
137 
138     #[test]
checked_add_overflow()139     fn checked_add_overflow() {
140         let a = GuestAddress(0xffffffffffffff55);
141         assert_eq!(Some(GuestAddress(0xffffffffffffff57)), a.checked_add(2));
142         assert!(a.checked_add(0xf0).is_none());
143     }
144 }
145