blob: d81c4f51b3715875f79b800071514d7bd56a66da [file] [log] [blame] [edit]
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef VM_TOOLS_CONCIERGE_VM_BUILDER_H_
#define VM_TOOLS_CONCIERGE_VM_BUILDER_H_
#include <optional>
#include <string>
#include <vector>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_split.h>
#include <dbus/object_proxy.h>
#include "vm_tools/concierge/vm_base_impl.h"
#include "vm_tools/concierge/vm_util.h"
namespace vm_tools::concierge {
class VmBuilder {
public:
// Describe the values for --async-executor options passed to crosvm
enum class AsyncExecutor {
kUring,
kEpoll,
};
// VM block storage device.
struct Disk {
// Gets the command line argument that needs to be passed to crosvm
// corresponding to this disk.
base::StringPairs GetCrosvmArgs() const;
// Path to the disk image on the host.
base::FilePath path;
// Whether the disk should be writable by the VM.
bool writable;
// Whether the disk should allow sparse file operations (discard) by the VM.
std::optional<bool> sparse;
// Whether the disk access should be done with O_DIRECT by the VM.
std::optional<bool> o_direct;
// Whether to enable multiple workers
std::optional<bool> multiple_workers;
// Async executor crosvm should use to run the disk devices.
std::optional<AsyncExecutor> async_executor;
// Block size.
std::optional<size_t> block_size;
// Block ID (max 20 chars).
std::optional<std::string> block_id;
};
// Contains the rootfs device and path.
struct Rootfs {
std::string device;
base::FilePath path;
bool writable;
};
// Args related to CPU configuration for a VM.
struct VmCpuArgs {
std::string cpu_affinity;
std::vector<std::string> cpu_capacity;
std::vector<std::vector<std::string>> cpu_clusters;
};
struct PmemDevice {
// Gets the command line argument that needs to be passed to crosvm
// corresponding to this pmem device.
base::StringPairs GetCrosvmArgs() const;
// Path to the disk image on the host, or an anonymous virtual memory area
// name when the vma_size is set.
std::string path;
// Whether the disk should be writable by the VM.
bool writable;
// Size in bytes for an anonymous memory area to be created to back this
// pmem device.
std::optional<uint64_t> vma_size;
// The interval in ms between swapping out the memory mapped by this pmem
// device.
std::optional<uint64_t> swap_interval_ms;
};
VmBuilder();
VmBuilder(VmBuilder&&);
VmBuilder& operator=(VmBuilder&& other);
VmBuilder(const VmBuilder&) = delete;
VmBuilder& operator=(const VmBuilder&) = delete;
~VmBuilder();
VmBuilder& SetKernel(base::FilePath kernel);
VmBuilder& SetInitrd(base::FilePath initrd);
VmBuilder& SetBios(base::FilePath bios);
VmBuilder& SetPflash(base::FilePath pflash);
VmBuilder& SetRootfs(const struct Rootfs& rootfs);
VmBuilder& SetCpus(int32_t cpus);
VmBuilder& SetVmCpuArgs(const struct VmCpuArgs& vm_cpu_args);
VmBuilder& SetVsockCid(uint32_t vsock_cid);
VmBuilder& AppendDisk(Disk disk);
VmBuilder& SetMemory(const std::string& memory_in_mb);
VmBuilder& SetBalloonBias(const std::string& balloon_bias_mib);
VmBuilder& EnableWorkingSetReporting(bool enable);
VmBuilder& SetSyslogTag(const std::string& syslog_tag);
VmBuilder& SetSocketPath(const std::string& socket_path);
VmBuilder& AppendTapFd(base::ScopedFD tap_fd);
VmBuilder& AppendKernelParam(const std::string& param);
VmBuilder& AppendOemString(const std::string& string);
VmBuilder& AppendAudioDevice(const std::string& params);
VmBuilder& AppendSerialDevice(const std::string& device);
VmBuilder& AppendPmemDevice(PmemDevice device);
VmBuilder& AppendSharedDir(SharedDataParam shared_data_param);
VmBuilder& AppendCustomParam(const std::string& key,
const std::string& value);
// Instructs this VM to use a wayland socket, if the empty string is provided
// the default path to the socket will be used, otherwise |socket| will be the
// path.
VmBuilder& SetWaylandSocket(const std::string& socket = "");
VmBuilder& AddExtraWaylandSocket(const std::string& socket);
VmBuilder& EnableGpu(bool enable);
VmBuilder& EnableDGpuPassthrough(bool enable);
VmBuilder& EnableVulkan(bool enable);
// Make virglrenderer use Big GL instead of the default GLES.
VmBuilder& EnableBigGl(bool enable);
// Offload Vulkan use to isolated virglrenderer render server
VmBuilder& EnableRenderServer(bool enable);
VmBuilder& SetGpuCachePath(base::FilePath gpu_cache_path);
VmBuilder& SetGpuCacheSize(std::string gpu_cache_size_str);
VmBuilder& SetRenderServerCachePath(base::FilePath render_server_cache_path);
VmBuilder& SetPrecompiledCachePath(base::FilePath precompiled_cache_path);
VmBuilder& SetFozDbListPath(base::FilePath foz_db_list_path);
VmBuilder& SetRenderServerCacheSize(std::string render_server_cache_size_str);
// By default, VMM infers which context types should be advertised.
// Enabling any specific context type via these API functions instructs VMM to
// skip its inference and only advertise those enabled explicitly. Calling
// EnableGpuContextTypeDefaults() reverts all previous settings back to the
// VMM-inferred context types.
VmBuilder& EnableGpuContextTypeDefaults();
VmBuilder& EnableGpuContextTypeVirgl(bool enable);
VmBuilder& EnableGpuContextTypeVenus(bool enable);
VmBuilder& EnableGpuContextTypeCrossDomain(bool enable);
VmBuilder& EnableGpuContextTypeDrm(bool enable);
VmBuilder& EnableVtpmProxy(bool enable);
VmBuilder& EnableVideoDecoder(bool enable);
VmBuilder& EnableVideoEncoder(bool enable);
VmBuilder& EnableBattery(bool enable);
VmBuilder& EnableSmt(bool enable);
VmBuilder& EnableDelayRt(bool enable);
VmBuilder& EnablePerVmCoreScheduling(bool enable);
VmBuilder& EnablePvClock(bool enable);
// Override flags for O_DIRECT for already appended Nth disk.
VmBuilder& EnableODirectN(int n, bool enable);
// Override flags for multiple_workers for already appended disks.
VmBuilder& EnableMultipleWorkers(bool enable);
// Override options for the async runtime for already appended disks.
VmBuilder& SetBlockAsyncExecutor(AsyncExecutor executor);
// Override block size for already appended disks.
VmBuilder& SetBlockSize(size_t block_size);
VmBuilder& SetBlockSizeN(size_t n, size_t block_size);
VmBuilder& SetVmmSwapDir(base::FilePath vmm_swap_dir);
// Builds the command line required to start a VM. Optionally Applies
// dev_params to modify the configuration. Consumes this (the builder).
// Returns std::nullopt on failure.
std::optional<base::StringPairs> BuildVmArgs(
CustomParametersForDev* dev_params) &&;
static void SetValidWaylandRegexForTesting(char* regex);
private:
// note: used as unsigned "position" index in std::bitset
enum GpuContextType : unsigned int {
GPU_CONTEXT_TYPE_VIRGL,
GPU_CONTEXT_TYPE_VENUS,
GPU_CONTEXT_TYPE_CROSS_DOMAIN,
GPU_CONTEXT_TYPE_DRM,
// note: must remain last
GPU_CONTEXT_TYPE_COUNT,
};
bool HasValidWaylandSockets() const;
// Builds the parameters for `crosvm run` to start a VM based on this
// VmBuilder's settings.
base::StringPairs BuildRunParams() const;
// Builds the parameters between `crosvm` and `run`.
base::StringPairs BuildPreRunParams() const;
bool ProcessCustomParameters(const CustomParametersForDev& devparams);
base::FilePath kernel_;
base::FilePath initrd_;
base::FilePath bios_;
base::FilePath pflash_;
std::optional<Rootfs> rootfs_;
int32_t cpus_ = 0;
std::optional<VmCpuArgs> vm_cpu_args_;
std::optional<uint32_t> vsock_cid_;
std::string memory_in_mib_;
std::string balloon_bias_mib_;
std::string syslog_tag_;
std::string vm_socket_path_;
bool enable_gpu_ = false;
bool enable_dgpu_passthrough_ = false;
bool enable_vulkan_ = false;
bool enable_big_gl_ = false;
bool enable_render_server_ = false;
base::FilePath gpu_cache_path_;
std::string gpu_cache_size_str_;
base::FilePath render_server_cache_path_;
base::FilePath foz_db_list_path_;
base::FilePath precompiled_cache_path_;
std::string render_server_cache_size_str_;
std::bitset<GPU_CONTEXT_TYPE_COUNT> enabled_gpu_context_types_;
bool enable_vtpm_proxy_ = false;
bool enable_video_decoder_ = false;
bool enable_video_encoder_ = false;
bool enable_battery_ = false;
bool enable_pvclock_ = false;
std::optional<bool> enable_smt_ = false;
bool enable_delay_rt_ = false;
bool enable_per_vm_core_scheduling_ = false;
bool enable_working_set_reporting_ = false;
std::vector<Disk> disks_;
std::vector<std::string> kernel_params_;
std::vector<std::string> oem_strings_;
std::vector<base::ScopedFD> tap_fds_;
struct AudioDevice {
std::string params;
};
std::vector<AudioDevice> audio_devices_;
std::vector<std::string> serial_devices_;
std::vector<std::string> wayland_sockets_;
std::vector<SharedDataParam> shared_dirs_;
std::vector<std::vector<int32_t>> cpu_clusters_;
std::vector<PmemDevice> pmem_devices_;
base::FilePath vmm_swap_dir_;
base::StringPairs custom_params_;
};
// Convert a string to the corresponding AsyncExecutor. This returns nullopt if
// the given string is unknown.
std::optional<VmBuilder::AsyncExecutor> StringToAsyncExecutor(
const std::string& async_executor);
} // namespace vm_tools::concierge
#endif // VM_TOOLS_CONCIERGE_VM_BUILDER_H_