• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "host/libs/vm_manager/crosvm_manager.h"
18 
19 #include <string>
20 #include <vector>
21 
22 #include <glog/logging.h>
23 
24 #include "common/libs/utils/network.h"
25 #include "common/libs/utils/subprocess.h"
26 #include "host/libs/config/cuttlefish_config.h"
27 #include "host/libs/vm_manager/qemu_manager.h"
28 
29 namespace vm_manager {
30 
31 namespace {
32 
GetControlSocketPath(const vsoc::CuttlefishConfig * config)33 std::string GetControlSocketPath(const vsoc::CuttlefishConfig* config) {
34   return config->PerInstancePath("crosvm_control.sock");
35 }
36 
ConnectToLogMonitor(const std::string & log_monitor_name)37 cvd::SharedFD ConnectToLogMonitor(const std::string& log_monitor_name) {
38   return cvd::SharedFD::SocketLocalClient(log_monitor_name.c_str(), false,
39                                           SOCK_STREAM);
40 }
41 
AddTapFdParameter(cvd::Command * crosvm_cmd,const std::string & tap_name)42 void AddTapFdParameter(cvd::Command* crosvm_cmd, const std::string& tap_name) {
43   auto tap_fd = cvd::OpenTapInterface(tap_name);
44   if (tap_fd->IsOpen()) {
45     crosvm_cmd->AddParameter("--tap-fd=", tap_fd);
46   } else {
47     LOG(ERROR) << "Unable to connect to " << tap_name << ": "
48                << tap_fd->StrError();
49   }
50 }
51 
52 }  // namespace
53 
name()54 const std::string CrosvmManager::name() { return "crosvm"; }
55 
ConfigureBootDevices(vsoc::CuttlefishConfig * config)56 void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
57   // PCI domain 0, bus 0, device 5, function 0
58   // TODO There is no way to control this assignment with crosvm (yet)
59   config->add_kernel_cmdline(
60     "androidboot.boot_devices=pci0000:00/0000:00:01.0");
61 }
62 
CrosvmManager(const vsoc::CuttlefishConfig * config)63 CrosvmManager::CrosvmManager(const vsoc::CuttlefishConfig* config)
64     : VmManager(config) {}
65 
StartCommand()66 cvd::Command CrosvmManager::StartCommand() {
67   // TODO Add aarch64 support
68   // TODO Add the tap interfaces (--tap-fd)
69   // TODO Redirect logcat output
70 
71   // Run crosvm directly instead of through a cf_crosvm.sh script. The kernel
72   // logs are on crosvm's standard output, so we need to redirect it to the log
73   // monitor socket, a helper script will print more than just the logs to
74   // standard output.
75   cvd::Command command(config_->crosvm_binary());
76   command.AddParameter("run");
77 
78   if (!config_->ramdisk_image_path().empty()) {
79     command.AddParameter("--initrd=", config_->ramdisk_image_path());
80   }
81   command.AddParameter("--null-audio");
82   command.AddParameter("--mem=", config_->memory_mb());
83   command.AddParameter("--cpus=", config_->cpus());
84   command.AddParameter("--params=", config_->kernel_cmdline_as_string());
85   if (config_->super_image_path().empty()) {
86     command.AddParameter("--rwdisk=", config_->system_image_path());
87   } else {
88     command.AddParameter("--rwdisk=", config_->super_image_path());
89   }
90   command.AddParameter("--rwdisk=", config_->data_image_path());
91   command.AddParameter("--rwdisk=", config_->cache_image_path());
92   command.AddParameter("--rwdisk=", config_->metadata_image_path());
93   if (config_->super_image_path().empty()) {
94     command.AddParameter("--rwdisk=", config_->vendor_image_path());
95     command.AddParameter("--rwdisk=", config_->product_image_path());
96   }
97   command.AddParameter("--socket=", GetControlSocketPath(config_));
98   if (!config_->gsi_fstab_path().empty()) {
99     command.AddParameter("--android-fstab=", config_->gsi_fstab_path());
100   }
101   command.AddParameter("--single-touch=", config_->touch_socket_path(), ":",
102                        config_->x_res(), ":", config_->y_res());
103   command.AddParameter("--keyboard=", config_->keyboard_socket_path());
104 
105   AddTapFdParameter(&command, config_->wifi_tap_name());
106   AddTapFdParameter(&command, config_->mobile_tap_name());
107 
108   // TODO remove this (use crosvm's seccomp files)
109   command.AddParameter("--disable-sandbox");
110 
111   if (config_->vsock_guest_cid() >= 2) {
112     command.AddParameter("--cid=", config_->vsock_guest_cid());
113   }
114 
115   auto kernel_log_connection =
116       ConnectToLogMonitor(config_->kernel_log_socket_name());
117   if (!kernel_log_connection->IsOpen()) {
118     LOG(WARNING) << "Unable to connect to log monitor: "
119                  << kernel_log_connection->StrError();
120   } else {
121     command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
122                           kernel_log_connection);
123   }
124 
125   auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY);
126   if (dev_null->IsOpen()) {
127     command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, dev_null);
128   } else {
129     LOG(ERROR) << "Unable to open /dev/null for stdin redirection";
130   }
131 
132   // This needs to be the last parameter
133   command.AddParameter(config_->GetKernelImageToUse());
134 
135   return command;
136 }
137 
Stop()138 bool CrosvmManager::Stop() {
139   cvd::Command command(config_->crosvm_binary());
140   command.AddParameter("stop");
141   command.AddParameter(GetControlSocketPath(config_));
142 
143   auto process = command.Start();
144 
145   return process.Wait() == 0;
146 }
147 
148 }  // namespace vm_manager
149 
150