/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "host/libs/vm_manager/crosvm_manager.h" #include #include #include #include "common/libs/utils/network.h" #include "common/libs/utils/subprocess.h" #include "host/libs/config/cuttlefish_config.h" #include "host/libs/vm_manager/qemu_manager.h" namespace vm_manager { namespace { std::string GetControlSocketPath(const vsoc::CuttlefishConfig* config) { return config->PerInstancePath("crosvm_control.sock"); } cvd::SharedFD ConnectToLogMonitor(const std::string& log_monitor_name) { return cvd::SharedFD::SocketLocalClient(log_monitor_name.c_str(), false, SOCK_STREAM); } void AddTapFdParameter(cvd::Command* crosvm_cmd, const std::string& tap_name) { auto tap_fd = cvd::OpenTapInterface(tap_name); if (tap_fd->IsOpen()) { crosvm_cmd->AddParameter("--tap-fd=", tap_fd); } else { LOG(ERROR) << "Unable to connect to " << tap_name << ": " << tap_fd->StrError(); } } } // namespace const std::string CrosvmManager::name() { return "crosvm"; } void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) { // PCI domain 0, bus 0, device 5, function 0 // TODO There is no way to control this assignment with crosvm (yet) config->add_kernel_cmdline( "androidboot.boot_devices=pci0000:00/0000:00:01.0"); } CrosvmManager::CrosvmManager(const vsoc::CuttlefishConfig* config) : VmManager(config) {} cvd::Command CrosvmManager::StartCommand() { // TODO Add aarch64 support // TODO Add the tap interfaces (--tap-fd) // TODO Redirect logcat output // Run crosvm directly instead of through a cf_crosvm.sh script. The kernel // logs are on crosvm's standard output, so we need to redirect it to the log // monitor socket, a helper script will print more than just the logs to // standard output. cvd::Command command(config_->crosvm_binary()); command.AddParameter("run"); if (!config_->ramdisk_image_path().empty()) { command.AddParameter("--initrd=", config_->ramdisk_image_path()); } command.AddParameter("--null-audio"); command.AddParameter("--mem=", config_->memory_mb()); command.AddParameter("--cpus=", config_->cpus()); command.AddParameter("--params=", config_->kernel_cmdline_as_string()); if (config_->super_image_path().empty()) { command.AddParameter("--rwdisk=", config_->system_image_path()); } else { command.AddParameter("--rwdisk=", config_->super_image_path()); } command.AddParameter("--rwdisk=", config_->data_image_path()); command.AddParameter("--rwdisk=", config_->cache_image_path()); command.AddParameter("--rwdisk=", config_->metadata_image_path()); if (config_->super_image_path().empty()) { command.AddParameter("--rwdisk=", config_->vendor_image_path()); command.AddParameter("--rwdisk=", config_->product_image_path()); } command.AddParameter("--socket=", GetControlSocketPath(config_)); if (!config_->gsi_fstab_path().empty()) { command.AddParameter("--android-fstab=", config_->gsi_fstab_path()); } command.AddParameter("--single-touch=", config_->touch_socket_path(), ":", config_->x_res(), ":", config_->y_res()); command.AddParameter("--keyboard=", config_->keyboard_socket_path()); AddTapFdParameter(&command, config_->wifi_tap_name()); AddTapFdParameter(&command, config_->mobile_tap_name()); // TODO remove this (use crosvm's seccomp files) command.AddParameter("--disable-sandbox"); if (config_->vsock_guest_cid() >= 2) { command.AddParameter("--cid=", config_->vsock_guest_cid()); } auto kernel_log_connection = ConnectToLogMonitor(config_->kernel_log_socket_name()); if (!kernel_log_connection->IsOpen()) { LOG(WARNING) << "Unable to connect to log monitor: " << kernel_log_connection->StrError(); } else { command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, kernel_log_connection); } auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY); if (dev_null->IsOpen()) { command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, dev_null); } else { LOG(ERROR) << "Unable to open /dev/null for stdin redirection"; } // This needs to be the last parameter command.AddParameter(config_->GetKernelImageToUse()); return command; } bool CrosvmManager::Stop() { cvd::Command command(config_->crosvm_binary()); command.AddParameter("stop"); command.AddParameter(GetControlSocketPath(config_)); auto process = command.Start(); return process.Wait() == 0; } } // namespace vm_manager