summary refs log tree commit diff
path: root/devices/src/virtio/virtio_pci_common_config.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2018-10-24 11:30:34 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-11-21 01:25:28 -0800
commite81a3e66cc266821fa5faec258d33c2eb3d8e102 (patch)
treee968ec22d1db178aa08ffc3f4d067c47a9dc88b1 /devices/src/virtio/virtio_pci_common_config.rs
parent5c4ad02dd4865949e7f4df1a04f4c1cc603e6c64 (diff)
downloadcrosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar.gz
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar.bz2
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar.lz
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar.xz
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.tar.zst
crosvm-e81a3e66cc266821fa5faec258d33c2eb3d8e102.zip
devices: convert virtio features to a u64
The virtio specification only defines feature bits in the 0-63 range
currently, so we can represent the features as a u64.  The Linux kernel
makes the same simplifying assumption, and very few features have been
defined beyond the first 32 bits, so this is probably safe for a while.

This allows the device models to be simplified, since they no longer
need to deal with the features paging mechanism (it is handled by the
generic virtio transport code).

BUG=None
TEST=build_test; boot termina on kevin

Change-Id: I6fd86907b2bdf494466c205e85072ebfeb7f5b73
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1313012
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/virtio/virtio_pci_common_config.rs')
-rw-r--r--devices/src/virtio/virtio_pci_common_config.rs26
1 files changed, 19 insertions, 7 deletions
diff --git a/devices/src/virtio/virtio_pci_common_config.rs b/devices/src/virtio/virtio_pci_common_config.rs
index 8596563..efbfbe0 100644
--- a/devices/src/virtio/virtio_pci_common_config.rs
+++ b/devices/src/virtio/virtio_pci_common_config.rs
@@ -138,10 +138,13 @@ impl VirtioPciCommonConfig {
                 // TODO(dverkamp): This hack (copied from MmioDevice) unconditionally
                 // reports support for VIRTIO_F_VERSION_1; once all devices have been
                 // fixed to report VIRTIO_F_VERSION_1, remove this workaround.
-                device.features(self.device_feature_select) | if self.device_feature_select == 1 {
-                    0x1
+                let features = device.features() | 1 << VIRTIO_F_VERSION_1;
+                // Only 64 bits of features (2 pages) are defined for now, so limit
+                // device_feature_select to avoid shifting by 64 or more bits.
+                if self.device_feature_select < 2 {
+                    (features >> (self.device_feature_select * 32)) as u32
                 } else {
-                    0x0
+                    0
                 }
             }
             0x08 => self.driver_feature_select,
@@ -167,7 +170,16 @@ impl VirtioPciCommonConfig {
         match offset {
             0x00 => self.device_feature_select = value,
             0x08 => self.driver_feature_select = value,
-            0x0c => device.ack_features(self.driver_feature_select, value),
+            0x0c => {
+                if self.driver_feature_select < 2 {
+                    device.ack_features((value as u64) << (self.driver_feature_select * 32));
+                } else {
+                    warn!(
+                        "invalid ack_features (page {}, value 0x{:x})",
+                        self.driver_feature_select, value
+                    );
+                }
+            }
             0x20 => self.with_queue_mut(queues, |q| lo(&mut q.desc_table, value)),
             0x24 => self.with_queue_mut(queues, |q| hi(&mut q.desc_table, value)),
             0x28 => self.with_queue_mut(queues, |q| lo(&mut q.avail_ring, value)),
@@ -221,7 +233,7 @@ mod tests {
     struct DummyDevice(u32);
     const QUEUE_SIZE: u16 = 256;
     const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE];
-    const DUMMY_FEATURES: u32 = 0x5555_aaaa;
+    const DUMMY_FEATURES: u64 = 0x5555_aaaa;
     impl VirtioDevice for DummyDevice {
         fn keep_fds(&self) -> Vec<RawFd> {
             Vec::new()
@@ -242,7 +254,7 @@ mod tests {
             _queue_evts: Vec<EventFd>,
         ) {
         }
-        fn features(&self, _page: u32) -> u32 {
+        fn features(&self) -> u64 {
             DUMMY_FEATURES
         }
     }
@@ -276,7 +288,7 @@ mod tests {
         regs.write(0x04, &[0, 0, 0, 0], &mut queues, &mut dev);
         let mut read_back = vec![0, 0, 0, 0];
         regs.read(0x04, &mut read_back, &mut queues, &mut dev);
-        assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES);
+        assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES as u32);
 
         // Feature select registers are read/write.
         regs.write(0x00, &[1, 2, 3, 4], &mut queues, &mut dev);