vmm/utils/
mod.rs

1// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4/// Module with helpers to read/write bytes into slices
5pub mod byte_order;
6/// Module with network related helpers
7pub mod net;
8/// Module with external libc functions
9pub mod signal;
10/// Module with state machine
11pub mod sm;
12
13use std::fs::{File, OpenOptions};
14use std::num::Wrapping;
15use std::os::unix::fs::OpenOptionsExt;
16use std::path::Path;
17use std::result::Result;
18
19use libc::O_NONBLOCK;
20
21/// How many bits to left-shift by to convert MiB to bytes
22const MIB_TO_BYTES_SHIFT: usize = 20;
23
24/// Return the default page size of the platform, in bytes.
25pub fn get_page_size() -> Result<usize, vmm_sys_util::errno::Error> {
26    // SAFETY: Safe because the parameters are valid.
27    match unsafe { libc::sysconf(libc::_SC_PAGESIZE) } {
28        -1 => Err(vmm_sys_util::errno::Error::last()),
29        ps => Ok(usize::try_from(ps).unwrap()),
30    }
31}
32
33/// Safely converts a u64 value to a usize value.
34/// This bypasses the Clippy lint check because we only support 64-bit platforms.
35#[cfg(target_pointer_width = "64")]
36#[inline]
37#[allow(clippy::cast_possible_truncation)]
38pub const fn u64_to_usize(num: u64) -> usize {
39    num as usize
40}
41
42/// Safely converts a usize value to a u64 value.
43/// This bypasses the Clippy lint check because we only support 64-bit platforms.
44#[cfg(target_pointer_width = "64")]
45#[inline]
46#[allow(clippy::cast_possible_truncation)]
47pub const fn usize_to_u64(num: usize) -> u64 {
48    num as u64
49}
50
51/// Converts a usize into a wrapping u32.
52#[inline]
53pub const fn wrap_usize_to_u32(num: usize) -> Wrapping<u32> {
54    Wrapping(((num as u64) & 0xFFFFFFFF) as u32)
55}
56
57/// Converts MiB to Bytes
58pub const fn mib_to_bytes(mib: usize) -> usize {
59    mib << MIB_TO_BYTES_SHIFT
60}
61
62/// Converts Bytes to MiB, truncating any remainder
63pub const fn bytes_to_mib(bytes: usize) -> usize {
64    bytes >> MIB_TO_BYTES_SHIFT
65}
66
67/// Align address up to the aligment.
68pub const fn align_up(addr: u64, align: u64) -> u64 {
69    debug_assert!(align != 0);
70    (addr + align - 1) & !(align - 1)
71}
72
73/// Align address down to the aligment.
74pub const fn align_down(addr: u64, align: u64) -> u64 {
75    debug_assert!(align != 0);
76    addr & !(align - 1)
77}
78
79/// Create and open a File for writing to it.
80/// In case we open a FIFO, in order to not block the instance if nobody is consuming the message
81/// that is flushed to it, we are opening it with `O_NONBLOCK` flag.
82/// In this case, writing to a pipe will start failing when reaching 64K of unconsumed content.
83pub fn open_file_write_nonblock(path: &Path) -> Result<File, std::io::Error> {
84    OpenOptions::new()
85        .custom_flags(O_NONBLOCK)
86        .create(true)
87        .write(true)
88        .open(path)
89}