blob: c5345c1564fc298feea8f153e287f688b294f7ce [file] [log] [blame]
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -07001/*
2 * Copyright (C) 2018 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/qemu_manager.h"
18
19#include <string.h>
20#include <sys/socket.h>
Jorge E. Moreira38193242018-07-06 11:12:13 -070021#include <sys/stat.h>
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070022#include <sys/types.h>
23#include <sys/un.h>
24#include <sys/wait.h>
25#include <unistd.h>
26
27#include <cstdlib>
28#include <sstream>
29#include <string>
30#include <thread>
31#include <vector>
32
Cody Schuffelen97359f82019-11-26 18:40:15 -080033#include <android-base/strings.h>
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070034#include <glog/logging.h>
35
Jorge E. Moreira2b003012018-07-22 17:46:27 -070036#include "common/libs/fs/shared_select.h"
Jorge E. Moreira38193242018-07-06 11:12:13 -070037#include "common/libs/utils/files.h"
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070038#include "common/libs/utils/subprocess.h"
Jorge E. Moreira5020a662018-07-09 17:07:14 -070039#include "common/libs/utils/users.h"
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070040#include "host/libs/config/cuttlefish_config.h"
41
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070042namespace vm_manager {
43
44namespace {
45
Jorge E. Moreiraa00584e2018-10-25 15:07:52 -070046std::string GetMonitorPath(const vsoc::CuttlefishConfig* config) {
Jorge E. Moreira1e8e2f12019-10-07 18:09:49 -070047 return config->PerInstanceInternalPath("qemu_monitor.sock");
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -070048}
49
Greg Hartman213a8a72018-06-28 23:43:40 -070050void LogAndSetEnv(const char* key, const std::string& value) {
51 setenv(key, value.c_str(), 1);
52 LOG(INFO) << key << "=" << value;
53}
54
Cody Schuffelen3c99f5b2019-06-14 17:26:01 -070055std::string JoinString(const std::vector<std::string>& args,
56 const std::string& delim) {
57 bool first = true;
58 std::stringstream output;
59 for (const auto& arg : args) {
60 if (first) {
61 first = false;
62 } else {
63 output << delim;
64 }
65 output << arg;
66 }
67 return output.str();
68}
69
Jorge E. Moreira7123e2e2019-09-05 13:47:29 -070070bool Stop() {
71 auto config = vsoc::CuttlefishConfig::Get();
72 auto monitor_path = GetMonitorPath(config);
73 auto monitor_sock = cvd::SharedFD::SocketLocalClient(
74 monitor_path.c_str(), false, SOCK_STREAM);
75
76 if (!monitor_sock->IsOpen()) {
77 LOG(ERROR) << "The connection to qemu is closed, is it still running?";
78 return false;
79 }
80 char msg[] = "{\"execute\":\"qmp_capabilities\"}{\"execute\":\"quit\"}";
81 ssize_t len = sizeof(msg) - 1;
82 while (len > 0) {
83 int tmp = monitor_sock->Write(msg, len);
84 if (tmp < 0) {
85 LOG(ERROR) << "Error writing to socket: " << monitor_sock->StrError();
86 return false;
87 }
88 len -= tmp;
89 }
90 // Log the reply
91 char buff[1000];
92 while ((len = monitor_sock->Read(buff, sizeof(buff) - 1)) > 0) {
93 buff[len] = '\0';
94 LOG(INFO) << "From qemu monitor: " << buff;
95 }
96
97 return true;
98}
99
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -0700100} // namespace
Jorge E. Moreira88322832018-07-22 16:41:01 -0700101
102const std::string QemuManager::name() { return "qemu_cli"; }
Alistair Strachan050ca932018-11-27 12:41:19 -0800103
Cody Schuffelen2de6ead2019-12-04 16:16:47 -0800104std::vector<std::string> QemuManager::ConfigureGpu(const std::string& gpu_mode) {
105 if (gpu_mode != vsoc::kGpuModeGuestSwiftshader) {
106 return {};
Greg Hartmana3c552d2019-03-28 18:20:48 -0700107 }
108 // Override the default HAL search paths in all cases. We do this because
109 // the HAL search path allows for fallbacks, and fallbacks in conjunction
110 // with properities lead to non-deterministic behavior while loading the
111 // HALs.
Cody Schuffelen2de6ead2019-12-04 16:16:47 -0800112 return {
113 "androidboot.hardware.gralloc=cutf_ashmem",
114 "androidboot.hardware.hwcomposer=cutf_cvm_ashmem",
115 "androidboot.hardware.egl=swiftshader",
116 "androidboot.hardware.vulkan=pastel",
117 };
Greg Hartmana3c552d2019-03-28 18:20:48 -0700118}
Jorge E. Moreira88322832018-07-22 16:41:01 -0700119
Cody Schuffelen2de6ead2019-12-04 16:16:47 -0800120std::vector<std::string> QemuManager::ConfigureBootDevices() {
Alistair Strachan050ca932018-11-27 12:41:19 -0800121 // PCI domain 0, bus 0, device 3, function 0
122 // This is controlled with 'addr=0x3' in cf_qemu.sh
Cody Schuffelen2de6ead2019-12-04 16:16:47 -0800123 return { "androidboot.boot_devices=pci0000:00/0000:00:03.0" };
Alistair Strachan050ca932018-11-27 12:41:19 -0800124}
125
Jorge E. Moreiraa00584e2018-10-25 15:07:52 -0700126QemuManager::QemuManager(const vsoc::CuttlefishConfig* config)
Jorge E. Moreira077d3002018-07-20 11:43:05 -0700127 : VmManager(config) {}
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -0700128
Cody Schuffelen97359f82019-11-26 18:40:15 -0800129std::vector<cvd::Command> QemuManager::StartCommands() {
Jorge E. Moreira9aeb97d2019-01-28 23:19:02 -0800130 // Set the config values in the environment
131 LogAndSetEnv("qemu_binary", config_->qemu_binary());
132 LogAndSetEnv("instance_name", config_->instance_name());
133 LogAndSetEnv("memory_mb", std::to_string(config_->memory_mb()));
134 LogAndSetEnv("cpus", std::to_string(config_->cpus()));
135 LogAndSetEnv("uuid", config_->uuid());
136 LogAndSetEnv("monitor_path", GetMonitorPath(config_));
Jorge E. Moreira80ddd7f2019-02-04 16:30:13 -0800137 LogAndSetEnv("kernel_image_path", config_->GetKernelImageToUse());
Jorge E. Moreira9aeb97d2019-01-28 23:19:02 -0800138 LogAndSetEnv("gdb_flag", config_->gdb_flag());
Cody Schuffelen9fd95472019-10-04 13:49:57 -0700139 LogAndSetEnv("ramdisk_image_path", config_->final_ramdisk_path());
Cody Schuffelen97359f82019-11-26 18:40:15 -0800140 LogAndSetEnv("kernel_cmdline", kernel_cmdline_);
Cody Schuffelen3c99f5b2019-06-14 17:26:01 -0700141 LogAndSetEnv("virtual_disk_paths", JoinString(config_->virtual_disk_paths(),
142 ";"));
Jorge E. Moreira9aeb97d2019-01-28 23:19:02 -0800143 LogAndSetEnv("wifi_tap_name", config_->wifi_tap_name());
144 LogAndSetEnv("mobile_tap_name", config_->mobile_tap_name());
Jorge E. Moreirab1ec4352019-06-04 11:43:08 -0700145 LogAndSetEnv("kernel_log_pipe_name",
146 config_->kernel_log_pipe_name());
Jorge E. Moreira9aeb97d2019-01-28 23:19:02 -0800147 LogAndSetEnv("console_path", config_->console_path());
148 LogAndSetEnv("logcat_path", config_->logcat_path());
Jorge E. Moreira9aeb97d2019-01-28 23:19:02 -0800149 LogAndSetEnv("vsock_guest_cid", std::to_string(config_->vsock_guest_cid()));
Cody Schuffelen5de48652019-09-16 19:49:52 +0000150 LogAndSetEnv("logcat_mode", config_->logcat_mode());
Cody Schuffelen1300f122019-05-28 18:24:34 -0700151 LogAndSetEnv("use_bootloader", config_->use_bootloader() ? "true" : "false");
152 LogAndSetEnv("bootloader", config_->bootloader());
Jorge E. Moreira2b003012018-07-22 17:46:27 -0700153
Jorge E. Moreira7123e2e2019-09-05 13:47:29 -0700154 cvd::Command qemu_cmd(vsoc::DefaultHostArtifactsPath("bin/cf_qemu.sh"),
155 [](cvd::Subprocess* proc) {
156 auto stopped = Stop();
157 if (stopped) {
158 return true;
159 }
160 LOG(WARNING) << "Failed to stop VMM nicely, "
161 << "attempting to KILL";
162 return KillSubprocess(proc);
163 });
Jorge E. Moreira13cbd982019-06-06 16:06:34 -0700164 std::vector<cvd::Command> ret;
165 ret.push_back(std::move(qemu_cmd));
166 return ret;
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -0700167}
Jorge E. Moreira13cbd982019-06-06 16:06:34 -0700168
Jorge E. Moreiraa8142f92018-06-13 17:33:55 -0700169} // namespace vm_manager