| /* |
| * 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 <string> |
| #include <vector> |
| |
| #include <glog/logging.h> |
| |
| #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"); |
| } |
| |
| 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"; } |
| |
| bool CrosvmManager::ConfigureGpu(vsoc::CuttlefishConfig* config) { |
| // Override the default HAL search paths in all cases. We do this because |
| // the HAL search path allows for fallbacks, and fallbacks in conjunction |
| // with properities lead to non-deterministic behavior while loading the |
| // HALs. |
| if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl) { |
| config->add_kernel_cmdline("androidboot.hardware.gralloc=minigbm"); |
| config->add_kernel_cmdline("androidboot.hardware.hwcomposer=drm_minigbm"); |
| config->add_kernel_cmdline("androidboot.hardware.egl=mesa"); |
| return true; |
| } |
| if (config->gpu_mode() == vsoc::kGpuModeGuestSwiftshader) { |
| config->add_kernel_cmdline( |
| "androidboot.hardware.gralloc=cutf_ashmem"); |
| config->add_kernel_cmdline( |
| "androidboot.hardware.hwcomposer=cutf_cvm_ashmem"); |
| config->add_kernel_cmdline("androidboot.hardware.egl=swiftshader"); |
| return true; |
| } |
| return false; |
| } |
| |
| void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) { |
| // PCI domain 0, bus 0, device 1, 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) {} |
| |
| std::vector<cvd::Command> CrosvmManager::StartCommands(bool with_frontend) { |
| cvd::Command crosvm_cmd(config_->crosvm_binary()); |
| crosvm_cmd.AddParameter("run"); |
| |
| if (config_->gpu_mode() != vsoc::kGpuModeGuestSwiftshader) { |
| crosvm_cmd.AddParameter("--gpu"); |
| if (config_->wayland_socket().size()) { |
| crosvm_cmd.AddParameter("--wayland-sock=", config_->wayland_socket()); |
| } |
| if (config_->x_display().size()) { |
| crosvm_cmd.AddParameter("--x-display=", config_->x_display()); |
| } |
| } |
| if (!config_->ramdisk_image_path().empty()) { |
| crosvm_cmd.AddParameter("--initrd=", config_->ramdisk_image_path()); |
| } |
| crosvm_cmd.AddParameter("--null-audio"); |
| crosvm_cmd.AddParameter("--mem=", config_->memory_mb()); |
| crosvm_cmd.AddParameter("--cpus=", config_->cpus()); |
| crosvm_cmd.AddParameter("--params=", config_->kernel_cmdline_as_string()); |
| for (const auto& disk : config_->virtual_disk_paths()) { |
| crosvm_cmd.AddParameter("--rwdisk=", disk); |
| } |
| crosvm_cmd.AddParameter("--socket=", GetControlSocketPath(config_)); |
| if (!config_->gsi_fstab_path().empty()) { |
| crosvm_cmd.AddParameter("--android-fstab=", config_->gsi_fstab_path()); |
| } |
| |
| if (with_frontend) { |
| crosvm_cmd.AddParameter("--single-touch=", config_->touch_socket_path(), ":", |
| config_->x_res(), ":", config_->y_res()); |
| crosvm_cmd.AddParameter("--keyboard=", config_->keyboard_socket_path()); |
| } |
| |
| AddTapFdParameter(&crosvm_cmd, config_->wifi_tap_name()); |
| AddTapFdParameter(&crosvm_cmd, config_->mobile_tap_name()); |
| |
| // TODO remove this (use crosvm's seccomp files) |
| crosvm_cmd.AddParameter("--disable-sandbox"); |
| |
| if (config_->vsock_guest_cid() >= 2) { |
| crosvm_cmd.AddParameter("--cid=", config_->vsock_guest_cid()); |
| } |
| |
| // Redirect the first serial port with the kernel logs to the appropriate file |
| crosvm_cmd.AddParameter("--serial=num=1,type=file,path=", |
| config_->kernel_log_pipe_name()); |
| // Use stdio for the second serial port, it contains the serial console. |
| crosvm_cmd.AddParameter("--serial=num=2,type=stdout,console=true"); |
| |
| // Redirect standard input and output to a couple of pipes for the console |
| // forwarder host process to handle. |
| cvd::SharedFD console_in_rd, console_in_wr, console_out_rd, console_out_wr; |
| if (!cvd::SharedFD::Pipe(&console_in_rd, &console_in_wr) || |
| !cvd::SharedFD::Pipe(&console_out_rd, &console_out_wr)) { |
| LOG(ERROR) << "Failed to create console pipes for crosvm: " |
| << strerror(errno); |
| return {}; |
| } |
| |
| crosvm_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, |
| console_in_rd); |
| crosvm_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, |
| console_out_wr); |
| cvd::Command console_cmd(config_->console_forwarder_binary()); |
| console_cmd.AddParameter("--console_in_fd=", console_in_wr); |
| console_cmd.AddParameter("--console_out_fd=", console_out_rd); |
| |
| // This needs to be the last parameter |
| crosvm_cmd.AddParameter(config_->GetKernelImageToUse()); |
| |
| std::vector<cvd::Command> ret; |
| ret.push_back(std::move(crosvm_cmd)); |
| ret.push_back(std::move(console_cmd)); |
| return ret; |
| } |
| |
| 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 |