• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use serde::{Deserialize, Serialize};
12 
13 /// Represents an Address in the guest's memory.
14 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
15 pub struct GuestAddress(pub u64);
16 
17 impl GuestAddress {
18     /// Returns the offset from this address to the given base address.
19     ///
20     /// # Examples
21     ///
22     /// ```
23     /// # use vm_memory::GuestAddress;
24     ///   let base = GuestAddress(0x100);
25     ///   let addr = GuestAddress(0x150);
26     ///   assert_eq!(addr.offset_from(base), 0x50u64);
27     /// ```
offset_from(self, base: GuestAddress) -> u6428     pub fn offset_from(self, base: GuestAddress) -> u64 {
29         self.0 - base.0
30     }
31 
32     /// Returns the address as a u64 offset from 0x0.
33     /// Use this when a raw number is needed to pass to the kernel.
offset(self) -> u6434     pub fn offset(self) -> u64 {
35         self.0
36     }
37 
38     /// Returns the result of the add or None if there is overflow.
checked_add(self, other: u64) -> Option<GuestAddress>39     pub fn checked_add(self, other: u64) -> Option<GuestAddress> {
40         self.0.checked_add(other).map(GuestAddress)
41     }
42 
43     /// Returns the result of the base address + the size.
44     /// Only use this when `offset` is guaranteed not to overflow.
unchecked_add(self, offset: u64) -> GuestAddress45     pub fn unchecked_add(self, offset: u64) -> GuestAddress {
46         GuestAddress(self.0 + offset)
47     }
48 
49     /// Returns the result of the subtraction of None if there is underflow.
checked_sub(self, other: u64) -> Option<GuestAddress>50     pub fn checked_sub(self, other: u64) -> Option<GuestAddress> {
51         self.0.checked_sub(other).map(GuestAddress)
52     }
53 
54     /// Returns the bitwise and of the address with the given mask.
mask(self, mask: u64) -> GuestAddress55     pub fn mask(self, mask: u64) -> GuestAddress {
56         GuestAddress(self.0 & mask as u64)
57     }
58 }
59 
60 impl BitAnd<u64> for GuestAddress {
61     type Output = GuestAddress;
62 
bitand(self, other: u64) -> GuestAddress63     fn bitand(self, other: u64) -> GuestAddress {
64         GuestAddress(self.0 & other as u64)
65     }
66 }
67 
68 impl BitOr<u64> for GuestAddress {
69     type Output = GuestAddress;
70 
bitor(self, other: u64) -> GuestAddress71     fn bitor(self, other: u64) -> GuestAddress {
72         GuestAddress(self.0 | other as u64)
73     }
74 }
75 
76 impl PartialEq for GuestAddress {
eq(&self, other: &GuestAddress) -> bool77     fn eq(&self, other: &GuestAddress) -> bool {
78         self.0 == other.0
79     }
80 }
81 impl Eq for GuestAddress {}
82 
83 impl Ord for GuestAddress {
cmp(&self, other: &GuestAddress) -> Ordering84     fn cmp(&self, other: &GuestAddress) -> Ordering {
85         self.0.cmp(&other.0)
86     }
87 }
88 
89 impl PartialOrd for GuestAddress {
partial_cmp(&self, other: &GuestAddress) -> Option<Ordering>90     fn partial_cmp(&self, other: &GuestAddress) -> Option<Ordering> {
91         Some(self.cmp(other))
92     }
93 }
94 
95 impl Display for GuestAddress {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result96     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97         write!(f, "{:#x}", self.0)
98     }
99 }
100 
101 #[cfg(test)]
102 mod tests {
103     use super::*;
104 
105     #[test]
equals()106     fn equals() {
107         let a = GuestAddress(0x300);
108         let b = GuestAddress(0x300);
109         let c = GuestAddress(0x301);
110         assert_eq!(a, b);
111         assert_eq!(b, a);
112         assert_ne!(a, c);
113         assert_ne!(c, a);
114     }
115 
116     #[test]
117     #[allow(clippy::eq_op)]
118     #[allow(clippy::nonminimal_bool)]
cmp()119     fn cmp() {
120         let a = GuestAddress(0x300);
121         let b = GuestAddress(0x301);
122         assert!(a < b);
123         assert!(b > a);
124         assert!(!(a < a));
125         assert!(a >= a);
126     }
127 
128     #[test]
mask()129     fn mask() {
130         let a = GuestAddress(0x5050);
131         assert_eq!(GuestAddress(0x5000), a & 0xff00u64);
132         assert_eq!(GuestAddress(0x5055), a | 0x0005u64);
133     }
134 
135     #[test]
add_sub()136     fn add_sub() {
137         let a = GuestAddress(0x50);
138         let b = GuestAddress(0x60);
139         assert_eq!(Some(GuestAddress(0xb0)), a.checked_add(0x60));
140         assert_eq!(0x10, b.offset_from(a));
141     }
142 
143     #[test]
checked_add_overflow()144     fn checked_add_overflow() {
145         let a = GuestAddress(0xffffffffffffff55);
146         assert_eq!(Some(GuestAddress(0xffffffffffffff57)), a.checked_add(2));
147         assert!(a.checked_add(0xf0).is_none());
148     }
149 }
150