vmm/devices/virtio/balloon/
mod.rs

1// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Implements a virtio balloon device.
5
6pub mod device;
7mod event_handler;
8pub mod metrics;
9pub mod persist;
10pub mod test_utils;
11mod util;
12
13use log::error;
14
15pub use self::device::{Balloon, BalloonConfig, BalloonStats};
16use super::queue::{InvalidAvailIdx, QueueError};
17use crate::devices::virtio::balloon::metrics::METRICS;
18use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
19use crate::logger::IncMetric;
20use crate::vstate::interrupts::InterruptError;
21
22/// Device ID used in MMIO device identification.
23/// Because Balloon is unique per-vm, this ID can be hardcoded.
24pub const BALLOON_DEV_ID: &str = "balloon";
25/// The size of the config space.
26pub const BALLOON_CONFIG_SPACE_SIZE: usize = 12;
27/// Min number of virtio queues.
28pub const BALLOON_MIN_NUM_QUEUES: usize = 2;
29/// Virtio queue size, in number of descriptor chain heads.
30pub const BALLOON_QUEUE_SIZE: u16 = FIRECRACKER_MAX_QUEUE_SIZE;
31// Number of 4K pages in a MiB.
32pub const MIB_TO_4K_PAGES: u32 = 256;
33/// The maximum number of pages that can be received in a single descriptor.
34pub const MAX_PAGES_IN_DESC: usize = 256;
35/// The maximum number of pages that can be compacted into ranges during process_inflate().
36/// Needs to be a multiple of MAX_PAGES_IN_DESC.
37pub const MAX_PAGE_COMPACT_BUFFER: usize = 2048;
38/// The addresses given by the driver are divided by 4096.
39pub const VIRTIO_BALLOON_PFN_SHIFT: u32 = 12;
40/// The index of the inflate queue from Balloon device queues/queues_evts vector.
41pub const INFLATE_INDEX: usize = 0;
42/// The index of the deflate queue from Balloon device queues/queues_evts vector.
43pub const DEFLATE_INDEX: usize = 1;
44/// The index of the stats queue from Balloon device queues/queues_evts vector.
45pub const STATS_INDEX: usize = 2;
46
47/// Command used in free page hinting to indicate the guest has finished
48pub const FREE_PAGE_HINT_STOP: u32 = 0;
49/// Command used in free page hinting to indicate to the guest to release pages
50pub const FREE_PAGE_HINT_DONE: u32 = 1;
51
52// The feature bitmap for virtio balloon.
53const VIRTIO_BALLOON_F_STATS_VQ: u32 = 1; // Enable statistics.
54const VIRTIO_BALLOON_F_DEFLATE_ON_OOM: u32 = 2; // Deflate balloon on OOM.
55const VIRTIO_BALLOON_F_FREE_PAGE_HINTING: u32 = 3; // Enable free page hinting
56const VIRTIO_BALLOON_F_FREE_PAGE_REPORTING: u32 = 5; // Enable free page reporting
57
58// The statistics tags. defined in linux "include/uapi/linux/virtio_balloon.h".
59const VIRTIO_BALLOON_S_SWAP_IN: u16 = 0;
60const VIRTIO_BALLOON_S_SWAP_OUT: u16 = 1;
61const VIRTIO_BALLOON_S_MAJFLT: u16 = 2;
62const VIRTIO_BALLOON_S_MINFLT: u16 = 3;
63const VIRTIO_BALLOON_S_MEMFREE: u16 = 4;
64const VIRTIO_BALLOON_S_MEMTOT: u16 = 5;
65const VIRTIO_BALLOON_S_AVAIL: u16 = 6;
66const VIRTIO_BALLOON_S_CACHES: u16 = 7;
67const VIRTIO_BALLOON_S_HTLB_PGALLOC: u16 = 8;
68const VIRTIO_BALLOON_S_HTLB_PGFAIL: u16 = 9;
69const VIRTIO_BALLOON_S_OOM_KILL: u16 = 10;
70const VIRTIO_BALLOON_S_ALLOC_STALL: u16 = 11;
71const VIRTIO_BALLOON_S_ASYNC_SCAN: u16 = 12;
72const VIRTIO_BALLOON_S_DIRECT_SCAN: u16 = 13;
73const VIRTIO_BALLOON_S_ASYNC_RECLAIM: u16 = 14;
74const VIRTIO_BALLOON_S_DIRECT_RECLAIM: u16 = 15;
75
76/// Balloon device related errors.
77#[derive(Debug, thiserror::Error, displaydoc::Display)]
78pub enum BalloonError {
79    /// Device not activated yet.
80    DeviceNotActive,
81    /// Attempting to use hinting when not enabled
82    HintingNotEnabled,
83    /// EventFd error: {0}
84    EventFd(std::io::Error),
85    /// Received error while sending an interrupt: {0}
86    InterruptError(InterruptError),
87    /// Guest gave us a malformed descriptor.
88    MalformedDescriptor,
89    /// Guest gave us a malformed payload.
90    MalformedPayload,
91    /// Error restoring the balloon device queues.
92    QueueRestoreError,
93    /// Received stats query when stats are disabled.
94    StatisticsDisabled,
95    /// Statistics cannot be enabled/disabled after activation.
96    StatisticsStateChange,
97    /// Requested memory should be less than {0}MiB
98    TooMuchMemoryRequested(u32),
99    /// Error while processing the virt queues: {0}
100    Queue(#[from] QueueError),
101    /// {0}
102    InvalidAvailIdx(#[from] InvalidAvailIdx),
103    /// Error creating the statistics timer: {0}
104    Timer(std::io::Error),
105}
106
107#[derive(Debug, thiserror::Error, displaydoc::Display)]
108pub enum RemoveRegionError {
109    /// Address translation error.
110    AddressTranslation,
111    /// Malformed guest address range.
112    MalformedRange,
113    /// Error calling madvise: {0}
114    MadviseFail(std::io::Error),
115    /// Error calling mmap: {0}
116    MmapFail(std::io::Error),
117    /// Region not found.
118    RegionNotFound,
119}
120
121pub(super) fn report_balloon_event_fail(err: BalloonError) {
122    if let BalloonError::InvalidAvailIdx(err) = err {
123        panic!("{}", err);
124    }
125    error!("{:?}", err);
126    METRICS.event_fails.inc();
127}