| // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| // 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_UTIL_H_ |
| #define VM_TOOLS_CONCIERGE_VM_UTIL_H_ |
| |
| #include <sys/types.h> |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include <base/files/file_path.h> |
| #include <base/strings/string_split.h> |
| #include <base/strings/string_piece.h> |
| #include <base/time/time.h> |
| #include <base/optional.h> |
| #include <brillo/process/process.h> |
| #include <vm_tools/concierge/usb_control.h> |
| #include <vm_tools/concierge/balloon_policy.h> |
| |
| namespace base { |
| class FilePath; |
| } // namespace base |
| |
| namespace vm_tools { |
| namespace concierge { |
| |
| class Disk { |
| public: |
| struct Config { |
| bool writable{false}; |
| base::Optional<bool> sparse; |
| base::Optional<bool> o_direct; |
| }; |
| |
| Disk(base::FilePath path, bool writable); |
| Disk(base::FilePath path, const Config& config); |
| Disk(const Disk&) = delete; |
| Disk& operator=(const Disk&) = delete; |
| Disk(Disk&&); |
| virtual ~Disk(); |
| |
| // Gets the command line argument that needs to be passed to crosvm |
| // corresponding to this disk. |
| base::StringPairs GetCrosvmArgs() const; |
| |
| void EnableODirect(bool enable); |
| |
| private: |
| // 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. |
| base::Optional<bool> sparse_; |
| |
| // Whether the disk access should be done with O_DIRECT by the VM. |
| base::Optional<bool> o_direct_; |
| }; |
| |
| // Path to the crosvm binary. |
| extern const char kCrosvmBin[]; |
| |
| // Uid and gid mappings for the android data directory. This is a |
| // comma-separated list of 3 values: <start of range inside the user namespace> |
| // <start of range outside the user namespace> <count>. The values are taken |
| // from platform2/arc/container-bundle/pi/config.json. |
| extern const char kAndroidUidMap[]; |
| extern const char kAndroidGidMap[]; |
| |
| // Calculates the amount of memory to give the virtual machine. Currently |
| // configured to provide 75% of system memory. This is deliberately over |
| // provisioned with the expectation that we will use the balloon driver to |
| // reduce the actual memory footprint. |
| std::string GetVmMemoryMiB(); |
| |
| // Retrieves the physical package ID for |cpu| from the topology information in |
| // sysfs. |
| base::Optional<int32_t> GetCpuPackageId(int32_t cpu); |
| |
| // Retrieves the CPU capacity property for |cpu| from sysfs. |
| base::Optional<int32_t> GetCpuCapacity(int32_t cpu); |
| |
| // Calculate an appropriate CPU affinity setting based on the host system's |
| // CPU clusters and capacity. CPUs will be grouped based on cluster if multiple |
| // clusters exist, or based on groupings of equal CPU capacity if more than one |
| // such grouping exists. Otherwise, |nullopt| will be returned. |
| base::Optional<std::string> GetCpuAffinityFromClusters( |
| const std::vector<std::vector<std::string>>& cpu_clusters, |
| const std::map<int32_t, std::vector<std::string>>& cpu_capacity_groups); |
| |
| // Puts the current process in a CPU cgroup specificed by |cpu_cgroup|, and |
| // then calls SetPgid(). This function can be called as brillo::ProcessImpl's |
| // PreExecCallback. |
| bool SetUpCrosvmProcess(const base::FilePath& cpu_cgroup); |
| |
| // Sets the pgid of the current process to its pid. This is needed because |
| // crosvm assumes that only it and its children are in the same process group |
| // and indiscriminately sends a SIGKILL if it needs to shut them down. This |
| // function can be called as brillo::ProcessImpl's PreExecCallback. |
| bool SetPgid(); |
| |
| // Waits for the |pid| to exit. Returns true if |pid| successfully exited and |
| // false if it did not exit in time. |
| bool WaitForChild(pid_t child, base::TimeDelta timeout); |
| |
| // Returns true if a process with |pid| exists. |
| bool CheckProcessExists(pid_t pid); |
| |
| // Runs a crosvm subcommand. |
| void RunCrosvmCommand(std::initializer_list<std::string> args); |
| void RunCrosvmCommand(std::string command, std::string socket_path); |
| |
| // Returns balloon stats info retrieved from virtio-balloon device. |
| base::Optional<BalloonStats> GetBalloonStats(std::string socket_path); |
| |
| // Attaches an usb device at host |bus|:|addr|, with |vid|, |pid| and an |
| // opened |fd|. |
| bool AttachUsbDevice(std::string socket_path, |
| uint8_t bus, |
| uint8_t addr, |
| uint16_t vid, |
| uint16_t pid, |
| int fd, |
| UsbControlResponse* response); |
| |
| // Detaches the usb device at guest |port|. |
| bool DetachUsbDevice(std::string socket_path, |
| uint8_t port, |
| UsbControlResponse* response); |
| |
| // Lists all usb devices attached to guest. |
| bool ListUsbDevice(std::string socket_path, std::vector<UsbDevice>* devices); |
| |
| // Resizes the disk identified by |disk_index| to |new_size| in bytes. |
| bool CrosvmDiskResize(std::string socket_path, |
| int disk_index, |
| uint64_t new_size); |
| |
| // Updates |cpu_cgroup|'s cpu.shares to |cpu_shares|. |
| bool UpdateCpuShares(const base::FilePath& cpu_cgroup, int cpu_shares); |
| |
| class CustomParametersForDev { |
| public: |
| // By default this class would do nothing. |
| CustomParametersForDev() = default; |
| |
| // Allow custom parameters on development devices with arcvm_dev.conf. |
| // Loads custom parameters from a string. Please check |
| // vm_tools/init/arcvm_dev.conf for the list of supported directives. |
| explicit CustomParametersForDev(const std::string& data); |
| |
| // Apply the parsed result of configuration files to |args| as a vector of |
| // string pairs. |
| void Apply(base::StringPairs* args); |
| |
| base::Optional<const std::string> ObtainSpecialParameter( |
| const std::string& key); |
| |
| private: |
| // Command line parameter prefix to crosvm to remove. |
| std::vector<std::string> prefix_to_remove_{}; |
| // Command line parameters to crosvm to add. |
| base::StringPairs params_to_add_{}; |
| // Other special handling. |
| std::map<std::string, std::string> special_parameters_{}; |
| bool initialized_{false}; |
| }; |
| |
| // Creates shared data parameter for crovm. |
| std::string CreateSharedDataParam(const base::FilePath& data_dir, |
| const std::string& tag, |
| bool enable_caches, |
| bool ascii_casefold, |
| const std::vector<uid_t>& privileged_uids); |
| |
| class ArcVmCPUTopology { |
| public: |
| ArcVmCPUTopology(uint32_t num_cpus, uint32_t num_rt_cpus); |
| ~ArcVmCPUTopology() = default; |
| |
| ArcVmCPUTopology(const ArcVmCPUTopology&) = delete; |
| ArcVmCPUTopology& operator=(const ArcVmCPUTopology&) = delete; |
| |
| void CreateCPUAffinity(); |
| |
| uint32_t NumCPUs(); |
| uint32_t NumRTCPUs(); |
| void SetNumRTCPUs(uint32_t num_rt_cpus); |
| const std::string& AffinityMask(); |
| const std::string& RTCPUMask(); |
| const std::string& CapacityMask(); |
| const std::vector<std::string>& PackageMask(); |
| |
| // Unit Testing crud |
| void AddCpuToCapacityGroupForTesting(uint32_t cpu, uint32_t capacity); |
| void AddCpuToPackageGroupForTesting(uint32_t cpu, uint32_t package); |
| void CreateCPUAffinityForTesting(); |
| |
| private: |
| void CreateTopology(); |
| void CreateAffinity(); |
| bool IsSymmetricCpu(); |
| |
| // Total number of CPUs VM will be configured with |
| uint32_t num_cpus_; |
| // Number of RT CPUs |
| uint32_t num_rt_cpus_; |
| // CPU mask for RT CPUs |
| std::string rt_cpu_mask_; |
| // CPU affinity |
| std::string affinity_mask_; |
| // A set of RT CPUs |
| std::set<uint32_t> rt_cpus_; |
| // CPU capacity grouping |
| std::map<uint32_t, std::vector<uint32_t>> capacity_; |
| // CPU package grouping |
| std::map<uint32_t, std::vector<uint32_t>> package_; |
| // CPU capacity mask |
| std::string capacity_mask_; |
| // CPU package mask |
| std::vector<std::string> package_mask_; |
| }; |
| |
| } // namespace concierge |
| } // namespace vm_tools |
| |
| #endif // VM_TOOLS_CONCIERGE_VM_UTIL_H_ |