devices: iommu: remove custom permission enum

Replace custom memory_mapper::Permission with base::Protection.

BUG=b:237620529
TEST=boot ARCVM and crostini

Change-Id: Iceaca2ee417e0c37e23e956bf18b8853674caa40
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3737406
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: David Stevens <stevensd@chromium.org>
diff --git a/base/src/sys/unix/mmap.rs b/base/src/sys/unix/mmap.rs
index 146e67a..75dad95 100644
--- a/base/src/sys/unix/mmap.rs
+++ b/base/src/sys/unix/mmap.rs
@@ -74,6 +74,12 @@
         Protection(libc::PROT_READ)
     }
 
+    /// Returns Protection allowing write access.
+    #[inline(always)]
+    pub fn write() -> Protection {
+        Protection(libc::PROT_WRITE)
+    }
+
     /// Set read events.
     #[inline(always)]
     pub fn set_read(self) -> Protection {
@@ -85,6 +91,13 @@
     pub fn set_write(self) -> Protection {
         Protection(self.0 | libc::PROT_WRITE)
     }
+
+    /// Returns true if all access allowed by |other| is also allowed by |self|.
+    #[inline(always)]
+    pub fn allows(&self, other: &Protection) -> bool {
+        (self.0 & libc::PROT_READ) >= (other.0 & libc::PROT_READ)
+            && (self.0 & libc::PROT_WRITE) >= (other.0 & libc::PROT_WRITE)
+    }
 }
 
 impl From<c_int> for Protection {
diff --git a/devices/src/virtio/iommu.rs b/devices/src/virtio/iommu.rs
index 241e4af..da79f64 100644
--- a/devices/src/virtio/iommu.rs
+++ b/devices/src/virtio/iommu.rs
@@ -23,8 +23,8 @@
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 use base::warn;
 use base::{
-    error, pagesize, AsRawDescriptor, Error as SysError, Event, RawDescriptor, Result as SysResult,
-    Tube, TubeError,
+    error, pagesize, AsRawDescriptor, Error as SysError, Event, Protection, RawDescriptor,
+    Result as SysResult, Tube, TubeError,
 };
 use cros_async::{AsyncError, AsyncTube, EventAsync, Executor};
 use data_model::{DataInit, Le64};
@@ -353,9 +353,9 @@
                 iova: req.virt_start.into(),
                 gpa: GuestAddress(req.phys_start.into()),
                 size,
-                perm: match write_en {
-                    true => Permission::RW,
-                    false => Permission::Read,
+                prot: match write_en {
+                    true => Protection::read_write(),
+                    false => Protection::read(),
                 },
             });
 
diff --git a/devices/src/virtio/iommu/ipc_memory_mapper.rs b/devices/src/virtio/iommu/ipc_memory_mapper.rs
index 8b583f7..2447d17 100644
--- a/devices/src/virtio/iommu/ipc_memory_mapper.rs
+++ b/devices/src/virtio/iommu/ipc_memory_mapper.rs
@@ -100,7 +100,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::virtio::memory_mapper::Permission;
+    use base::Protection;
     use std::thread;
     use vm_memory::GuestAddress;
 
@@ -119,7 +119,7 @@
                 .zip(&vec![MemRegion {
                     gpa: GuestAddress(0x777),
                     len: 1,
-                    perm: Permission::RW,
+                    prot: Protection::read_write(),
                 },])
                 .all(|(a, b)| a == b));
         });
@@ -136,7 +136,7 @@
                 .send(&Some(vec![MemRegion {
                     gpa: GuestAddress(0x777),
                     len: 1,
-                    perm: Permission::RW,
+                    prot: Protection::read_write(),
                 }]))
                 .unwrap();
             // This join needs to be here because on Windows, if `response_tx`
diff --git a/devices/src/virtio/iommu/memory_mapper.rs b/devices/src/virtio/iommu/memory_mapper.rs
index 637f94f..685c48f 100644
--- a/devices/src/virtio/iommu/memory_mapper.rs
+++ b/devices/src/virtio/iommu/memory_mapper.rs
@@ -11,23 +11,15 @@
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use anyhow::{anyhow, bail, Context, Result};
-use base::{AsRawDescriptors, RawDescriptor};
+use base::{AsRawDescriptors, Protection, RawDescriptor};
 use serde::{Deserialize, Serialize};
 use vm_memory::GuestAddress;
 
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub enum Permission {
-    Read = 1,
-    Write = 2,
-    RW = 3,
-}
-
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 pub struct MemRegion {
     pub gpa: GuestAddress,
     pub len: u64,
-    pub perm: Permission,
+    pub prot: Protection,
 }
 
 /// Manages the mapping from a guest IO virtual address space to the guest physical address space
@@ -36,12 +28,12 @@
     pub iova: u64,
     pub gpa: GuestAddress,
     pub size: u64,
-    pub perm: Permission,
+    pub prot: Protection,
 }
 
 impl MappingInfo {
     #[allow(dead_code)]
-    fn new(iova: u64, gpa: GuestAddress, size: u64, perm: Permission) -> Result<Self> {
+    fn new(iova: u64, gpa: GuestAddress, size: u64, prot: Protection) -> Result<Self> {
         if size == 0 {
             bail!("can't create 0 sized region");
         }
@@ -51,7 +43,7 @@
             iova,
             gpa,
             size,
-            perm,
+            prot,
         })
     }
 }
@@ -204,7 +196,7 @@
             // This is the last region to be inserted / first to be returned when iova >= map.iova
             let region_len = last_iova - std::cmp::max::<u64>(map.iova, iova);
             if let Some(last) = regions.last_mut() {
-                if map.gpa.unchecked_add(map.size) == last.gpa && map.perm == last.perm {
+                if map.gpa.unchecked_add(map.size) == last.gpa && map.prot == last.prot {
                     last.gpa = map.gpa;
                     last.len += region_len;
                     new_region = false;
@@ -221,7 +213,7 @@
                 regions.push(MemRegion {
                     gpa: map.gpa,
                     len: region_len,
-                    perm: map.perm,
+                    prot: map.prot,
                 });
             }
             if iova >= map.iova {
@@ -254,42 +246,52 @@
     #[test]
     fn test_mapping_info() {
         // Overflow
-        MappingInfo::new(u64::MAX - 1, GuestAddress(1), 2, Permission::Read).unwrap_err();
-        MappingInfo::new(1, GuestAddress(u64::MAX - 1), 2, Permission::Read).unwrap_err();
-        MappingInfo::new(u64::MAX, GuestAddress(1), 2, Permission::Read).unwrap_err();
-        MappingInfo::new(1, GuestAddress(u64::MAX), 2, Permission::Read).unwrap_err();
-        MappingInfo::new(5, GuestAddress(5), u64::MAX, Permission::Read).unwrap_err();
+        MappingInfo::new(u64::MAX - 1, GuestAddress(1), 2, Protection::read()).unwrap_err();
+        MappingInfo::new(1, GuestAddress(u64::MAX - 1), 2, Protection::read()).unwrap_err();
+        MappingInfo::new(u64::MAX, GuestAddress(1), 2, Protection::read()).unwrap_err();
+        MappingInfo::new(1, GuestAddress(u64::MAX), 2, Protection::read()).unwrap_err();
+        MappingInfo::new(5, GuestAddress(5), u64::MAX, Protection::read()).unwrap_err();
         // size = 0
-        MappingInfo::new(1, GuestAddress(5), 0, Permission::Read).unwrap_err();
+        MappingInfo::new(1, GuestAddress(5), 0, Protection::read()).unwrap_err();
     }
 
     #[test]
     fn test_map_overlap() {
         let mut mapper = BasicMemoryMapper::new(u64::MAX);
         mapper
-            .add_map(MappingInfo::new(10, GuestAddress(1000), 10, Permission::RW).unwrap())
+            .add_map(
+                MappingInfo::new(10, GuestAddress(1000), 10, Protection::read_write()).unwrap(),
+            )
             .unwrap();
         assert_eq!(
             mapper
-                .add_map(MappingInfo::new(14, GuestAddress(1000), 1, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(14, GuestAddress(1000), 1, Protection::read_write()).unwrap()
+                )
                 .unwrap(),
             AddMapResult::OverlapFailure
         );
         assert_eq!(
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 12, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 12, Protection::read_write()).unwrap()
+                )
                 .unwrap(),
             AddMapResult::OverlapFailure
         );
         assert_eq!(
             mapper
-                .add_map(MappingInfo::new(16, GuestAddress(1000), 6, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(16, GuestAddress(1000), 6, Protection::read_write()).unwrap()
+                )
                 .unwrap(),
             AddMapResult::OverlapFailure
         );
         assert_eq!(
             mapper
-                .add_map(MappingInfo::new(5, GuestAddress(1000), 20, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(5, GuestAddress(1000), 20, Protection::read_write()).unwrap()
+                )
                 .unwrap(),
             AddMapResult::OverlapFailure
         );
@@ -307,14 +309,16 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 9, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 9, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert_eq!(
                 mapper.translate(0, 1).unwrap()[0],
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             assert_eq!(
@@ -322,7 +326,7 @@
                 MemRegion {
                     gpa: GuestAddress(1008),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             mapper.translate(9, 1).unwrap_err();
@@ -333,17 +337,21 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             mapper
-                .add_map(MappingInfo::new(5, GuestAddress(50), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(5, GuestAddress(50), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert_eq!(
                 mapper.translate(0, 1).unwrap()[0],
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             assert_eq!(
@@ -351,7 +359,7 @@
                 MemRegion {
                     gpa: GuestAddress(51),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             mapper.remove_map(0, 9).unwrap();
@@ -362,7 +370,9 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 9, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 9, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert!(!mapper.remove_map(0, 4).unwrap());
             assert_eq!(
@@ -370,7 +380,7 @@
                 MemRegion {
                     gpa: GuestAddress(1005),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
         }
@@ -378,17 +388,21 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             mapper
-                .add_map(MappingInfo::new(5, GuestAddress(50), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(5, GuestAddress(50), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert_eq!(
                 mapper.translate(0, 1).unwrap()[0],
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             assert_eq!(
@@ -396,7 +410,7 @@
                 MemRegion {
                     gpa: GuestAddress(50),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             mapper.remove_map(0, 4).unwrap();
@@ -407,7 +421,7 @@
                 MemRegion {
                     gpa: GuestAddress(50),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
         }
@@ -415,14 +429,16 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(0, GuestAddress(1000), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert_eq!(
                 mapper.translate(0, 1).unwrap()[0],
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             mapper.translate(9, 1).unwrap_err();
@@ -434,17 +450,19 @@
         {
             let mut mapper = BasicMemoryMapper::new(u64::MAX);
             mapper
-                .add_map(MappingInfo::new(0, GuestAddress(1000), 4, Permission::Read).unwrap())
+                .add_map(MappingInfo::new(0, GuestAddress(1000), 4, Protection::read()).unwrap())
                 .unwrap();
             mapper
-                .add_map(MappingInfo::new(10, GuestAddress(50), 4, Permission::RW).unwrap())
+                .add_map(
+                    MappingInfo::new(10, GuestAddress(50), 4, Protection::read_write()).unwrap(),
+                )
                 .unwrap();
             assert_eq!(
                 mapper.translate(0, 1).unwrap()[0],
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::Read
+                    prot: Protection::read()
                 }
             );
             assert_eq!(
@@ -452,7 +470,7 @@
                 MemRegion {
                     gpa: GuestAddress(1003),
                     len: 1,
-                    perm: Permission::Read
+                    prot: Protection::read()
                 }
             );
             mapper.translate(4, 1).unwrap_err();
@@ -461,7 +479,7 @@
                 MemRegion {
                     gpa: GuestAddress(50),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             assert_eq!(
@@ -469,7 +487,7 @@
                 MemRegion {
                     gpa: GuestAddress(53),
                     len: 1,
-                    perm: Permission::RW
+                    prot: Protection::read_write()
                 }
             );
             mapper.remove_map(0, 14).unwrap();
@@ -484,13 +502,13 @@
     fn test_remove_map() {
         let mut mapper = BasicMemoryMapper::new(u64::MAX);
         mapper
-            .add_map(MappingInfo::new(1, GuestAddress(1000), 4, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(1, GuestAddress(1000), 4, Protection::read()).unwrap())
             .unwrap();
         mapper
-            .add_map(MappingInfo::new(5, GuestAddress(50), 4, Permission::RW).unwrap())
+            .add_map(MappingInfo::new(5, GuestAddress(50), 4, Protection::read_write()).unwrap())
             .unwrap();
         mapper
-            .add_map(MappingInfo::new(9, GuestAddress(50), 4, Permission::RW).unwrap())
+            .add_map(MappingInfo::new(9, GuestAddress(50), 4, Protection::read_write()).unwrap())
             .unwrap();
         assert_eq!(mapper.len(), 3);
         assert!(!mapper.remove_map(0, 6).unwrap());
@@ -523,7 +541,7 @@
         let mut mapper = BasicMemoryMapper::new(u64::MAX);
         // [1, 5) -> [1000, 1004)
         mapper
-            .add_map(MappingInfo::new(1, GuestAddress(1000), 4, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(1, GuestAddress(1000), 4, Protection::read()).unwrap())
             .unwrap();
         mapper.translate(1, 0).unwrap_err();
         assert_eq!(
@@ -531,7 +549,7 @@
             MemRegion {
                 gpa: GuestAddress(1000),
                 len: 1,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -539,7 +557,7 @@
             MemRegion {
                 gpa: GuestAddress(1000),
                 len: 2,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -547,7 +565,7 @@
             MemRegion {
                 gpa: GuestAddress(1000),
                 len: 3,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -555,7 +573,7 @@
             MemRegion {
                 gpa: GuestAddress(1001),
                 len: 1,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -563,13 +581,13 @@
             MemRegion {
                 gpa: GuestAddress(1001),
                 len: 2,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         mapper.translate(1, 5).unwrap_err();
         // [1, 9) -> [1000, 1008)
         mapper
-            .add_map(MappingInfo::new(5, GuestAddress(1004), 4, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(5, GuestAddress(1004), 4, Protection::read()).unwrap())
             .unwrap();
         // Spanned across 2 maps
         assert_eq!(
@@ -577,7 +595,7 @@
             MemRegion {
                 gpa: GuestAddress(1001),
                 len: 5,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -585,7 +603,7 @@
             MemRegion {
                 gpa: GuestAddress(1001),
                 len: 6,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -593,20 +611,20 @@
             MemRegion {
                 gpa: GuestAddress(1001),
                 len: 7,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         mapper.translate(2, 8).unwrap_err();
         mapper.translate(3, 10).unwrap_err();
         // [1, 9) -> [1000, 1008), [11, 17) -> [1010, 1016)
         mapper
-            .add_map(MappingInfo::new(11, GuestAddress(1010), 6, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(11, GuestAddress(1010), 6, Protection::read()).unwrap())
             .unwrap();
         // Discontiguous iova
         mapper.translate(3, 10).unwrap_err();
         // [1, 17) -> [1000, 1016)
         mapper
-            .add_map(MappingInfo::new(9, GuestAddress(1008), 2, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(9, GuestAddress(1008), 2, Protection::read()).unwrap())
             .unwrap();
         // Spanned across 4 maps
         assert_eq!(
@@ -614,7 +632,7 @@
             MemRegion {
                 gpa: GuestAddress(1002),
                 len: 10,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         assert_eq!(
@@ -622,21 +640,21 @@
             MemRegion {
                 gpa: GuestAddress(1000),
                 len: 16,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         mapper.translate(1, 17).unwrap_err();
         mapper.translate(0, 16).unwrap_err();
         // [0, 1) -> [5, 6), [1, 17) -> [1000, 1016)
         mapper
-            .add_map(MappingInfo::new(0, GuestAddress(5), 1, Permission::Read).unwrap())
+            .add_map(MappingInfo::new(0, GuestAddress(5), 1, Protection::read()).unwrap())
             .unwrap();
         assert_eq!(
             mapper.translate(0, 1).unwrap()[0],
             MemRegion {
                 gpa: GuestAddress(5),
                 len: 1,
-                perm: Permission::Read
+                prot: Protection::read()
             }
         );
         // Discontiguous gpa
@@ -646,12 +664,12 @@
                 MemRegion {
                     gpa: GuestAddress(5),
                     len: 1,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 1,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
             ],
         );
@@ -661,18 +679,18 @@
                 MemRegion {
                     gpa: GuestAddress(5),
                     len: 1,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 15,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
             ],
         );
         // [0, 1) -> [5, 6), [1, 17) -> [1000, 1016), [17, 18) -> [1016, 1017) <RW>
         mapper
-            .add_map(MappingInfo::new(17, GuestAddress(1016), 2, Permission::RW).unwrap())
+            .add_map(MappingInfo::new(17, GuestAddress(1016), 2, Protection::read_write()).unwrap())
             .unwrap();
         // Contiguous iova and gpa, but different perm
         assert_vec_eq(
@@ -681,12 +699,12 @@
                 MemRegion {
                     gpa: GuestAddress(1000),
                     len: 16,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
                 MemRegion {
                     gpa: GuestAddress(1016),
                     len: 1,
-                    perm: Permission::RW,
+                    prot: Protection::read_write(),
                 },
             ],
         );
@@ -697,12 +715,12 @@
                 MemRegion {
                     gpa: GuestAddress(1001),
                     len: 15,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
                 MemRegion {
                     gpa: GuestAddress(1016),
                     len: 1,
-                    perm: Permission::RW,
+                    prot: Protection::read_write(),
                 },
             ],
         );
@@ -712,12 +730,12 @@
                 MemRegion {
                     gpa: GuestAddress(1001),
                     len: 15,
-                    perm: Permission::Read,
+                    prot: Protection::read(),
                 },
                 MemRegion {
                     gpa: GuestAddress(1016),
                     len: 2,
-                    perm: Permission::RW,
+                    prot: Protection::read_write(),
                 },
             ],
         );
diff --git a/devices/src/virtio/iommu/memory_util.rs b/devices/src/virtio/iommu/memory_util.rs
index c0df37d..7664ec2 100644
--- a/devices/src/virtio/iommu/memory_util.rs
+++ b/devices/src/virtio/iommu/memory_util.rs
@@ -9,11 +9,12 @@
 use sync::Mutex;
 
 use anyhow::{bail, Context};
+use base::Protection;
 use data_model::DataInit;
 use vm_memory::{GuestAddress, GuestMemory};
 
 use crate::virtio::iommu::IpcMemoryMapper;
-use crate::virtio::memory_mapper::{Permission, Translate};
+use crate::virtio::memory_mapper::Translate;
 
 /// A wrapper that works with gpa, or iova and an iommu.
 pub fn is_valid_wrapper<T: Translate>(
@@ -83,7 +84,7 @@
     let mut buf = vec![0u8; std::mem::size_of::<T>()];
     let mut addr: usize = 0;
     for r in regions {
-        if (r.perm as u8 & Permission::Read as u8) == 0 {
+        if !r.prot.allows(&Protection::read()) {
             bail!("gpa is not readable");
         }
         mem.read_at_addr(&mut buf[addr..(addr + r.len as usize)], r.gpa)
@@ -126,7 +127,7 @@
     let buf = val.as_slice();
     let mut addr: usize = 0;
     for r in regions {
-        if (r.perm as u8 & Permission::Read as u8) == 0 {
+        if !r.prot.allows(&Protection::write()) {
             bail!("gpa is not writable");
         }
         mem.write_at_addr(&buf[addr..(addr + (r.len as usize))], r.gpa)
diff --git a/devices/src/virtio/iommu/sys/unix/vfio_wrapper.rs b/devices/src/virtio/iommu/sys/unix/vfio_wrapper.rs
index 7868dbe..c68a5ce 100644
--- a/devices/src/virtio/iommu/sys/unix/vfio_wrapper.rs
+++ b/devices/src/virtio/iommu/sys/unix/vfio_wrapper.rs
@@ -7,13 +7,13 @@
 use std::sync::Arc;
 
 use anyhow::{bail, Context};
-use base::{AsRawDescriptor, AsRawDescriptors, RawDescriptor};
+use base::{AsRawDescriptor, AsRawDescriptors, Protection, RawDescriptor};
 use sync::Mutex;
 use vm_memory::{GuestAddress, GuestMemory};
 
 use crate::vfio::VfioError;
 use crate::virtio::iommu::memory_mapper::{
-    AddMapResult, MappingInfo, MemRegion, MemoryMapper, Permission, Translate,
+    AddMapResult, MappingInfo, MemRegion, MemoryMapper, Translate,
 };
 use crate::VfioContainer;
 
@@ -63,7 +63,7 @@
                 map.iova,
                 map.size,
                 map.gpa.offset(),
-                (map.perm as u8 & Permission::Write as u8) != 0,
+                map.prot.allows(&Protection::write()),
             )
         };
         if let Err(VfioError::IommuDmaMap(err)) = res {
diff --git a/devices/src/virtio/queue.rs b/devices/src/virtio/queue.rs
index 8d79f95..59e1310 100644
--- a/devices/src/virtio/queue.rs
+++ b/devices/src/virtio/queue.rs
@@ -10,7 +10,7 @@
 use sync::Mutex;
 
 use anyhow::{bail, Context};
-use base::{error, warn};
+use base::{error, warn, Protection};
 use cros_async::{AsyncError, EventAsync};
 use data_model::{DataInit, Le16, Le32, Le64};
 use virtio_sys::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
@@ -18,7 +18,7 @@
 
 use super::{SignalableInterrupt, VIRTIO_MSI_NO_VECTOR};
 use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
-use crate::virtio::memory_mapper::{MemRegion, Permission, Translate};
+use crate::virtio::memory_mapper::{MemRegion, Translate};
 use crate::virtio::memory_util::{
     is_valid_wrapper, read_obj_from_addr_wrapper, write_obj_at_addr_wrapper,
 };
@@ -153,7 +153,7 @@
             Ok(vec![MemRegion {
                 gpa: self.addr,
                 len: self.len.try_into().expect("u32 doesn't fit in usize"),
-                perm: Permission::RW,
+                prot: Protection::read_write(),
             }])
         }
     }