1 /*
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>
21 #include <sys/stat.h>
22 #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
33 #include <glog/logging.h>
34
35 #include "common/libs/fs/shared_select.h"
36 #include "common/libs/utils/files.h"
37 #include "common/libs/utils/subprocess.h"
38 #include "common/libs/utils/users.h"
39 #include "host/libs/config/cuttlefish_config.h"
40
41 namespace vm_manager {
42
43 namespace {
44
GetMonitorPath(const vsoc::CuttlefishConfig * config)45 std::string GetMonitorPath(const vsoc::CuttlefishConfig* config) {
46 return config->PerInstancePath("qemu_monitor.sock");
47 }
48
LogAndSetEnv(const char * key,const std::string & value)49 void LogAndSetEnv(const char* key, const std::string& value) {
50 setenv(key, value.c_str(), 1);
51 LOG(INFO) << key << "=" << value;
52 }
53
54 } // namespace
55
name()56 const std::string QemuManager::name() { return "qemu_cli"; }
57
ConfigureBootDevices(vsoc::CuttlefishConfig * config)58 void QemuManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
59 // PCI domain 0, bus 0, device 3, function 0
60 // This is controlled with 'addr=0x3' in cf_qemu.sh
61 config->add_kernel_cmdline(
62 "androidboot.boot_devices=pci0000:00/0000:00:03.0");
63 }
64
QemuManager(const vsoc::CuttlefishConfig * config)65 QemuManager::QemuManager(const vsoc::CuttlefishConfig* config)
66 : VmManager(config) {}
67
StartCommand()68 cvd::Command QemuManager::StartCommand(){
69 // Set the config values in the environment
70 LogAndSetEnv("qemu_binary", config_->qemu_binary());
71 LogAndSetEnv("instance_name", config_->instance_name());
72 LogAndSetEnv("memory_mb", std::to_string(config_->memory_mb()));
73 LogAndSetEnv("cpus", std::to_string(config_->cpus()));
74 LogAndSetEnv("uuid", config_->uuid());
75 LogAndSetEnv("monitor_path", GetMonitorPath(config_));
76 LogAndSetEnv("kernel_image_path", config_->GetKernelImageToUse());
77 LogAndSetEnv("gdb_flag", config_->gdb_flag());
78 LogAndSetEnv("ramdisk_image_path", config_->ramdisk_image_path());
79 LogAndSetEnv("kernel_cmdline", config_->kernel_cmdline_as_string());
80 LogAndSetEnv("dtb_path", config_->dtb_path());
81 LogAndSetEnv("system_image_path", config_->system_image_path());
82 LogAndSetEnv("data_image_path", config_->data_image_path());
83 LogAndSetEnv("cache_image_path", config_->cache_image_path());
84 LogAndSetEnv("vendor_image_path", config_->vendor_image_path());
85 LogAndSetEnv("metadata_image_path", config_->metadata_image_path());
86 LogAndSetEnv("product_image_path", config_->product_image_path());
87 LogAndSetEnv("super_image_path", config_->super_image_path());
88 LogAndSetEnv("wifi_tap_name", config_->wifi_tap_name());
89 LogAndSetEnv("mobile_tap_name", config_->mobile_tap_name());
90 LogAndSetEnv("kernel_log_socket_name",
91 config_->kernel_log_socket_name());
92 LogAndSetEnv("console_path", config_->console_path());
93 LogAndSetEnv("logcat_path", config_->logcat_path());
94 LogAndSetEnv("ivshmem_qemu_socket_path",
95 config_->ivshmem_qemu_socket_path());
96 LogAndSetEnv("ivshmem_vector_count",
97 std::to_string(config_->ivshmem_vector_count()));
98 LogAndSetEnv("usb_v1_socket_name", config_->usb_v1_socket_name());
99 LogAndSetEnv("vsock_guest_cid", std::to_string(config_->vsock_guest_cid()));
100 LogAndSetEnv("logcat_mode", config_->logcat_mode());
101
102 cvd::Command qemu_cmd(vsoc::DefaultHostArtifactsPath("bin/cf_qemu.sh"));
103 return qemu_cmd;
104 }
Stop()105 bool QemuManager::Stop() {
106 auto monitor_path = GetMonitorPath(config_);
107 auto monitor_sock = cvd::SharedFD::SocketLocalClient(
108 monitor_path.c_str(), false, SOCK_STREAM);
109
110 if (!monitor_sock->IsOpen()) {
111 LOG(ERROR) << "The connection to qemu is closed, is it still running?";
112 return false;
113 }
114 char msg[] = "{\"execute\":\"qmp_capabilities\"}{\"execute\":\"quit\"}";
115 ssize_t len = sizeof(msg) - 1;
116 while (len > 0) {
117 int tmp = monitor_sock->Write(msg, len);
118 if (tmp < 0) {
119 LOG(ERROR) << "Error writing to socket: " << monitor_sock->StrError();
120 return false;
121 }
122 len -= tmp;
123 }
124 // Log the reply
125 char buff[1000];
126 while ((len = monitor_sock->Read(buff, sizeof(buff) - 1)) > 0) {
127 buff[len] = '\0';
128 LOG(INFO) << "From qemu monitor: " << buff;
129 }
130
131 return true;
132 }
133
134 } // namespace vm_manager
135