xref: /kvmtool/kvm-ipc.c (revision d77bd4f466f341d4b35fe8b91176ef8a37160e19)
14b1addaeSSasha Levin #include <sys/epoll.h>
24b1addaeSSasha Levin #include <sys/un.h>
34b1addaeSSasha Levin #include <sys/types.h>
44b1addaeSSasha Levin #include <sys/socket.h>
5c733c80bSSasha Levin #include <sys/eventfd.h>
6e1063726SSasha Levin #include <dirent.h>
7e1063726SSasha Levin 
8e1063726SSasha Levin #include "kvm/kvm-ipc.h"
9e1063726SSasha Levin #include "kvm/rwsem.h"
10e1063726SSasha Levin #include "kvm/read-write.h"
11e1063726SSasha Levin #include "kvm/util.h"
12e1063726SSasha Levin #include "kvm/kvm.h"
13e1063726SSasha Levin #include "kvm/builtin-debug.h"
14e1063726SSasha Levin #include "kvm/strbuf.h"
15e1063726SSasha Levin #include "kvm/kvm-cpu.h"
16e1063726SSasha Levin #include "kvm/8250-serial.h"
174b1addaeSSasha Levin 
18a9aae6c5SLai Jiangshan struct kvm_ipc_head {
19a9aae6c5SLai Jiangshan 	u32 type;
20a9aae6c5SLai Jiangshan 	u32 len;
21a9aae6c5SLai Jiangshan };
22a9aae6c5SLai Jiangshan 
234b1addaeSSasha Levin #define KVM_IPC_MAX_MSGS 16
244b1addaeSSasha Levin 
25e1063726SSasha Levin #define KVM_SOCK_SUFFIX		".sock"
26e1063726SSasha Levin #define KVM_SOCK_SUFFIX_LEN	((ssize_t)sizeof(KVM_SOCK_SUFFIX) - 1)
27e1063726SSasha Levin 
28e1063726SSasha Levin extern __thread struct kvm_cpu *current_kvm_cpu;
29e1063726SSasha Levin static void (*msgs[KVM_IPC_MAX_MSGS])(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
304b1addaeSSasha Levin static DECLARE_RWSEM(msgs_rwlock);
31c733c80bSSasha Levin static int epoll_fd, server_fd, stop_fd;
32c733c80bSSasha Levin static pthread_t thread;
334b1addaeSSasha Levin 
34e1063726SSasha Levin static int kvm__create_socket(struct kvm *kvm)
35e1063726SSasha Levin {
36e1063726SSasha Levin 	char full_name[PATH_MAX];
37a2583dbfSAndre Przywara 	int s;
38e1063726SSasha Levin 	struct sockaddr_un local;
39e1063726SSasha Levin 	int len, r;
40e1063726SSasha Levin 
41e1063726SSasha Levin 	/* This usually 108 bytes long */
42e1063726SSasha Levin 	BUILD_BUG_ON(sizeof(local.sun_path) < 32);
43e1063726SSasha Levin 
44e1063726SSasha Levin 	snprintf(full_name, sizeof(full_name), "%s/%s%s",
45e1063726SSasha Levin 		 kvm__get_dir(), kvm->cfg.guest_name, KVM_SOCK_SUFFIX);
46e1063726SSasha Levin 	if (access(full_name, F_OK) == 0) {
47e1063726SSasha Levin 		pr_err("Socket file %s already exist", full_name);
48e1063726SSasha Levin 		return -EEXIST;
49e1063726SSasha Levin 	}
50e1063726SSasha Levin 
51e1063726SSasha Levin 	s = socket(AF_UNIX, SOCK_STREAM, 0);
52211370d6SMichael Ellerman 	if (s < 0) {
53211370d6SMichael Ellerman 		perror("socket");
54e1063726SSasha Levin 		return s;
55211370d6SMichael Ellerman 	}
56211370d6SMichael Ellerman 
57e1063726SSasha Levin 	local.sun_family = AF_UNIX;
58e1063726SSasha Levin 	strlcpy(local.sun_path, full_name, sizeof(local.sun_path));
59e1063726SSasha Levin 	len = strlen(local.sun_path) + sizeof(local.sun_family);
60e1063726SSasha Levin 	r = bind(s, (struct sockaddr *)&local, len);
61211370d6SMichael Ellerman 	if (r < 0) {
62211370d6SMichael Ellerman 		perror("bind");
63e1063726SSasha Levin 		goto fail;
64211370d6SMichael Ellerman 	}
65e1063726SSasha Levin 
66e1063726SSasha Levin 	r = listen(s, 5);
67211370d6SMichael Ellerman 	if (r < 0) {
68211370d6SMichael Ellerman 		perror("listen");
69e1063726SSasha Levin 		goto fail;
70211370d6SMichael Ellerman 	}
71e1063726SSasha Levin 
72e1063726SSasha Levin 	return s;
73e1063726SSasha Levin 
74e1063726SSasha Levin fail:
75e1063726SSasha Levin 	close(s);
76e1063726SSasha Levin 	return r;
77e1063726SSasha Levin }
78e1063726SSasha Levin 
79e1063726SSasha Levin void kvm__remove_socket(const char *name)
80e1063726SSasha Levin {
81e1063726SSasha Levin 	char full_name[PATH_MAX];
82e1063726SSasha Levin 
83e1063726SSasha Levin 	snprintf(full_name, sizeof(full_name), "%s/%s%s",
84e1063726SSasha Levin 		 kvm__get_dir(), name, KVM_SOCK_SUFFIX);
85e1063726SSasha Levin 	unlink(full_name);
86e1063726SSasha Levin }
87e1063726SSasha Levin 
88e1063726SSasha Levin int kvm__get_sock_by_instance(const char *name)
89e1063726SSasha Levin {
90e1063726SSasha Levin 	int s, len, r;
91e1063726SSasha Levin 	char sock_file[PATH_MAX];
92e1063726SSasha Levin 	struct sockaddr_un local;
93e1063726SSasha Levin 
94e1063726SSasha Levin 	snprintf(sock_file, sizeof(sock_file), "%s/%s%s",
95e1063726SSasha Levin 		 kvm__get_dir(), name, KVM_SOCK_SUFFIX);
96e1063726SSasha Levin 	s = socket(AF_UNIX, SOCK_STREAM, 0);
97e1063726SSasha Levin 
98e1063726SSasha Levin 	local.sun_family = AF_UNIX;
99e1063726SSasha Levin 	strlcpy(local.sun_path, sock_file, sizeof(local.sun_path));
100e1063726SSasha Levin 	len = strlen(local.sun_path) + sizeof(local.sun_family);
101e1063726SSasha Levin 
102*d77bd4f4SAndre Przywara 	r = connect(s, (struct sockaddr *)&local, len);
103e1063726SSasha Levin 	if (r < 0 && errno == ECONNREFUSED) {
104e1063726SSasha Levin 		/* Tell the user clean ghost socket file */
105e1063726SSasha Levin 		pr_err("\"%s\" could be a ghost socket file, please remove it",
106e1063726SSasha Levin 				sock_file);
107e1063726SSasha Levin 		return r;
108e1063726SSasha Levin 	} else if (r < 0) {
109e1063726SSasha Levin 		return r;
110e1063726SSasha Levin 	}
111e1063726SSasha Levin 
112e1063726SSasha Levin 	return s;
113e1063726SSasha Levin }
114e1063726SSasha Levin 
11522fb13f6SMilan Kocian static bool is_socket(const char *base_path, const struct dirent *dent)
11622fb13f6SMilan Kocian {
11722fb13f6SMilan Kocian 	switch (dent->d_type) {
11822fb13f6SMilan Kocian 	case DT_SOCK:
11922fb13f6SMilan Kocian 		return true;
12022fb13f6SMilan Kocian 
12122fb13f6SMilan Kocian 	case DT_UNKNOWN: {
12222fb13f6SMilan Kocian 		char path[PATH_MAX];
12322fb13f6SMilan Kocian 		struct stat st;
12422fb13f6SMilan Kocian 
12522fb13f6SMilan Kocian 		sprintf(path, "%s/%s", base_path, dent->d_name);
12622fb13f6SMilan Kocian 		if (stat(path, &st))
12722fb13f6SMilan Kocian 			return false;
12822fb13f6SMilan Kocian 
12922fb13f6SMilan Kocian 		return S_ISSOCK(st.st_mode);
13022fb13f6SMilan Kocian 	}
13122fb13f6SMilan Kocian 	default:
13222fb13f6SMilan Kocian 		return false;
13322fb13f6SMilan Kocian 	}
13422fb13f6SMilan Kocian }
13522fb13f6SMilan Kocian 
136e1063726SSasha Levin int kvm__enumerate_instances(int (*callback)(const char *name, int fd))
137e1063726SSasha Levin {
138e1063726SSasha Levin 	int sock;
139e1063726SSasha Levin 	DIR *dir;
140e1063726SSasha Levin 	struct dirent entry, *result;
141e1063726SSasha Levin 	int ret = 0;
14222fb13f6SMilan Kocian 	const char *path;
143e1063726SSasha Levin 
14422fb13f6SMilan Kocian 	path = kvm__get_dir();
14522fb13f6SMilan Kocian 
14622fb13f6SMilan Kocian 	dir = opendir(path);
147e1063726SSasha Levin 	if (!dir)
148e1063726SSasha Levin 		return -errno;
149e1063726SSasha Levin 
150e1063726SSasha Levin 	for (;;) {
151e1063726SSasha Levin 		readdir_r(dir, &entry, &result);
152e1063726SSasha Levin 		if (result == NULL)
153e1063726SSasha Levin 			break;
15422fb13f6SMilan Kocian 		if (is_socket(path, &entry)) {
155e1063726SSasha Levin 			ssize_t name_len = strlen(entry.d_name);
156e1063726SSasha Levin 			char *p;
157e1063726SSasha Levin 
158e1063726SSasha Levin 			if (name_len <= KVM_SOCK_SUFFIX_LEN)
159e1063726SSasha Levin 				continue;
160e1063726SSasha Levin 
161e1063726SSasha Levin 			p = &entry.d_name[name_len - KVM_SOCK_SUFFIX_LEN];
162e1063726SSasha Levin 			if (memcmp(KVM_SOCK_SUFFIX, p, KVM_SOCK_SUFFIX_LEN))
163e1063726SSasha Levin 				continue;
164e1063726SSasha Levin 
165e1063726SSasha Levin 			*p = 0;
166e1063726SSasha Levin 			sock = kvm__get_sock_by_instance(entry.d_name);
167e1063726SSasha Levin 			if (sock < 0)
168e1063726SSasha Levin 				continue;
169e1063726SSasha Levin 			ret = callback(entry.d_name, sock);
170e1063726SSasha Levin 			close(sock);
171e1063726SSasha Levin 			if (ret < 0)
172e1063726SSasha Levin 				break;
173e1063726SSasha Levin 		}
174e1063726SSasha Levin 	}
175e1063726SSasha Levin 
176e1063726SSasha Levin 	closedir(dir);
177e1063726SSasha Levin 
178e1063726SSasha Levin 	return ret;
179e1063726SSasha Levin }
180e1063726SSasha Levin 
181e1063726SSasha Levin int kvm_ipc__register_handler(u32 type, void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg))
1824b1addaeSSasha Levin {
1834b1addaeSSasha Levin 	if (type >= KVM_IPC_MAX_MSGS)
1844b1addaeSSasha Levin 		return -ENOSPC;
1854b1addaeSSasha Levin 
1864b1addaeSSasha Levin 	down_write(&msgs_rwlock);
1874b1addaeSSasha Levin 	msgs[type] = cb;
1884b1addaeSSasha Levin 	up_write(&msgs_rwlock);
1894b1addaeSSasha Levin 
1904b1addaeSSasha Levin 	return 0;
1914b1addaeSSasha Levin }
1924b1addaeSSasha Levin 
19350dc18aeSLai Jiangshan int kvm_ipc__send(int fd, u32 type)
19450dc18aeSLai Jiangshan {
19550dc18aeSLai Jiangshan 	struct kvm_ipc_head head = {.type = type, .len = 0,};
19650dc18aeSLai Jiangshan 
197ca088268SAsias He 	if (write_in_full(fd, &head, sizeof(head)) < 0)
19850dc18aeSLai Jiangshan 		return -1;
19950dc18aeSLai Jiangshan 
20050dc18aeSLai Jiangshan 	return 0;
20150dc18aeSLai Jiangshan }
20250dc18aeSLai Jiangshan 
20350dc18aeSLai Jiangshan int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg)
20450dc18aeSLai Jiangshan {
20550dc18aeSLai Jiangshan 	struct kvm_ipc_head head = {.type = type, .len = len,};
20650dc18aeSLai Jiangshan 
207ca088268SAsias He 	if (write_in_full(fd, &head, sizeof(head)) < 0)
20850dc18aeSLai Jiangshan 		return -1;
20950dc18aeSLai Jiangshan 
210fd5b45a1SAsias He 	if (write_in_full(fd, msg, len) < 0)
21150dc18aeSLai Jiangshan 		return -1;
21250dc18aeSLai Jiangshan 
21350dc18aeSLai Jiangshan 	return 0;
21450dc18aeSLai Jiangshan }
21550dc18aeSLai Jiangshan 
216e1063726SSasha Levin static int kvm_ipc__handle(struct kvm *kvm, int fd, u32 type, u32 len, u8 *data)
2174b1addaeSSasha Levin {
218e1063726SSasha Levin 	void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
2194b1addaeSSasha Levin 
22044a56bfdSLai Jiangshan 	if (type >= KVM_IPC_MAX_MSGS)
2214b1addaeSSasha Levin 		return -ENOSPC;
2224b1addaeSSasha Levin 
2234b1addaeSSasha Levin 	down_read(&msgs_rwlock);
22444a56bfdSLai Jiangshan 	cb = msgs[type];
2254b1addaeSSasha Levin 	up_read(&msgs_rwlock);
2264b1addaeSSasha Levin 
2274b1addaeSSasha Levin 	if (cb == NULL) {
22844a56bfdSLai Jiangshan 		pr_warning("No device handles type %u\n", type);
2294b1addaeSSasha Levin 		return -ENODEV;
2304b1addaeSSasha Levin 	}
2314b1addaeSSasha Levin 
232e1063726SSasha Levin 	cb(kvm, fd, type, len, data);
2334b1addaeSSasha Levin 
2344b1addaeSSasha Levin 	return 0;
2354b1addaeSSasha Levin }
2364b1addaeSSasha Levin 
2374b1addaeSSasha Levin static int kvm_ipc__new_conn(int fd)
2384b1addaeSSasha Levin {
2394b1addaeSSasha Levin 	int client;
2404b1addaeSSasha Levin 	struct epoll_event ev;
2414b1addaeSSasha Levin 
2424b1addaeSSasha Levin 	client = accept(fd, NULL, NULL);
2434b1addaeSSasha Levin 	if (client < 0)
2444b1addaeSSasha Levin 		return -1;
2454b1addaeSSasha Levin 
2464b1addaeSSasha Levin 	ev.events = EPOLLIN | EPOLLRDHUP;
2474b1addaeSSasha Levin 	ev.data.fd = client;
2484b1addaeSSasha Levin 	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client, &ev) < 0) {
2494b1addaeSSasha Levin 		close(client);
2504b1addaeSSasha Levin 		return -1;
2514b1addaeSSasha Levin 	}
2524b1addaeSSasha Levin 
2534b1addaeSSasha Levin 	return client;
2544b1addaeSSasha Levin }
2554b1addaeSSasha Levin 
2564b1addaeSSasha Levin static void kvm_ipc__close_conn(int fd)
2574b1addaeSSasha Levin {
2584b1addaeSSasha Levin 	epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
2594b1addaeSSasha Levin 	close(fd);
2604b1addaeSSasha Levin }
2614b1addaeSSasha Levin 
262e1063726SSasha Levin static int kvm_ipc__receive(struct kvm *kvm, int fd)
2634b1addaeSSasha Levin {
264a9aae6c5SLai Jiangshan 	struct kvm_ipc_head head;
265a9aae6c5SLai Jiangshan 	u8 *msg = NULL;
2664b1addaeSSasha Levin 	u32 n;
2674b1addaeSSasha Levin 
268a9aae6c5SLai Jiangshan 	n = read(fd, &head, sizeof(head));
269a9aae6c5SLai Jiangshan 	if (n != sizeof(head))
270a9aae6c5SLai Jiangshan 		goto done;
271a9aae6c5SLai Jiangshan 
272a9aae6c5SLai Jiangshan 	msg = malloc(head.len);
2734b1addaeSSasha Levin 	if (msg == NULL)
2744b1addaeSSasha Levin 		goto done;
2754b1addaeSSasha Levin 
276a9aae6c5SLai Jiangshan 	n = read_in_full(fd, msg, head.len);
277a9aae6c5SLai Jiangshan 	if (n != head.len)
2784b1addaeSSasha Levin 		goto done;
2794b1addaeSSasha Levin 
280e1063726SSasha Levin 	kvm_ipc__handle(kvm, fd, head.type, head.len, msg);
2814b1addaeSSasha Levin 
2828e463c62SAsias He 	return 0;
2838e463c62SAsias He 
2844b1addaeSSasha Levin done:
2854b1addaeSSasha Levin 	free(msg);
2868e463c62SAsias He 	return -1;
2874b1addaeSSasha Levin }
2884b1addaeSSasha Levin 
2894b1addaeSSasha Levin static void *kvm_ipc__thread(void *param)
2904b1addaeSSasha Levin {
2914b1addaeSSasha Levin 	struct epoll_event event;
292e1063726SSasha Levin 	struct kvm *kvm = param;
2934b1addaeSSasha Levin 
294a4d8c55eSSasha Levin 	kvm__set_thread_name("kvm-ipc");
295a4d8c55eSSasha Levin 
2964b1addaeSSasha Levin 	for (;;) {
2974b1addaeSSasha Levin 		int nfds;
2984b1addaeSSasha Levin 
2994b1addaeSSasha Levin 		nfds = epoll_wait(epoll_fd, &event, 1, -1);
3004b1addaeSSasha Levin 		if (nfds > 0) {
3014b1addaeSSasha Levin 			int fd = event.data.fd;
3024b1addaeSSasha Levin 
30347f72b90SSasha Levin 			if (fd == stop_fd && event.events & EPOLLIN) {
304c733c80bSSasha Levin 				break;
305c733c80bSSasha Levin 			} else if (fd == server_fd) {
3068e463c62SAsias He 				int client, r;
3074b1addaeSSasha Levin 
3084b1addaeSSasha Levin 				client = kvm_ipc__new_conn(fd);
3098e463c62SAsias He 				/*
3108e463c62SAsias He 				 * Handle multiple IPC cmd at a time
3118e463c62SAsias He 				 */
3128e463c62SAsias He 				do {
313e1063726SSasha Levin 					r = kvm_ipc__receive(kvm, client);
3148e463c62SAsias He 				} while	(r == 0);
3158e463c62SAsias He 
316066c5809SSasha Levin 			} else if (event.events & (EPOLLERR | EPOLLRDHUP | EPOLLHUP)) {
3174b1addaeSSasha Levin 				kvm_ipc__close_conn(fd);
3184b1addaeSSasha Levin 			} else {
319e1063726SSasha Levin 				kvm_ipc__receive(kvm, fd);
3204b1addaeSSasha Levin 			}
3214b1addaeSSasha Levin 		}
3224b1addaeSSasha Levin 	}
3234b1addaeSSasha Levin 
3244b1addaeSSasha Levin 	return NULL;
3254b1addaeSSasha Levin }
3264b1addaeSSasha Levin 
327e1063726SSasha Levin static void kvm__pid(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
328e1063726SSasha Levin {
329e1063726SSasha Levin 	pid_t pid = getpid();
330e1063726SSasha Levin 	int r = 0;
331e1063726SSasha Levin 
332e1063726SSasha Levin 	if (type == KVM_IPC_PID)
333e1063726SSasha Levin 		r = write(fd, &pid, sizeof(pid));
334e1063726SSasha Levin 
335e1063726SSasha Levin 	if (r < 0)
336e1063726SSasha Levin 		pr_warning("Failed sending PID");
337e1063726SSasha Levin }
338e1063726SSasha Levin 
339e1063726SSasha Levin static void handle_stop(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
340e1063726SSasha Levin {
341e1063726SSasha Levin 	if (WARN_ON(type != KVM_IPC_STOP || len))
342e1063726SSasha Levin 		return;
343e1063726SSasha Levin 
344e1063726SSasha Levin 	kvm_cpu__reboot(kvm);
345e1063726SSasha Levin }
346e1063726SSasha Levin 
347e1063726SSasha Levin /* Pause/resume the guest using SIGUSR2 */
348e1063726SSasha Levin static int is_paused;
349e1063726SSasha Levin 
350e1063726SSasha Levin static void handle_pause(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
351e1063726SSasha Levin {
352e1063726SSasha Levin 	if (WARN_ON(len))
353e1063726SSasha Levin 		return;
354e1063726SSasha Levin 
355e1063726SSasha Levin 	if (type == KVM_IPC_RESUME && is_paused) {
356e1063726SSasha Levin 		kvm->vm_state = KVM_VMSTATE_RUNNING;
3574346fd8fSSasha Levin 		kvm__continue(kvm);
358e1063726SSasha Levin 	} else if (type == KVM_IPC_PAUSE && !is_paused) {
359e1063726SSasha Levin 		kvm->vm_state = KVM_VMSTATE_PAUSED;
360e1063726SSasha Levin 		ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL);
3614346fd8fSSasha Levin 		kvm__pause(kvm);
362e1063726SSasha Levin 	} else {
363e1063726SSasha Levin 		return;
364e1063726SSasha Levin 	}
365e1063726SSasha Levin 
366e1063726SSasha Levin 	is_paused = !is_paused;
367e1063726SSasha Levin }
368e1063726SSasha Levin 
369e1063726SSasha Levin static void handle_vmstate(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
370e1063726SSasha Levin {
371e1063726SSasha Levin 	int r = 0;
372e1063726SSasha Levin 
373e1063726SSasha Levin 	if (type == KVM_IPC_VMSTATE)
374e1063726SSasha Levin 		r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
375e1063726SSasha Levin 
376e1063726SSasha Levin 	if (r < 0)
377e1063726SSasha Levin 		pr_warning("Failed sending VMSTATE");
378e1063726SSasha Levin }
379e1063726SSasha Levin 
380e1063726SSasha Levin /*
381e1063726SSasha Levin  * Serialize debug printout so that the output of multiple vcpus does not
382e1063726SSasha Levin  * get mixed up:
383e1063726SSasha Levin  */
384e1063726SSasha Levin static int printout_done;
385e1063726SSasha Levin 
386e1063726SSasha Levin static void handle_sigusr1(int sig)
387e1063726SSasha Levin {
388e1063726SSasha Levin 	struct kvm_cpu *cpu = current_kvm_cpu;
389e1063726SSasha Levin 	int fd = kvm_cpu__get_debug_fd();
390e1063726SSasha Levin 
391e1063726SSasha Levin 	if (!cpu || cpu->needs_nmi)
392e1063726SSasha Levin 		return;
393e1063726SSasha Levin 
394e1063726SSasha Levin 	dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
395e1063726SSasha Levin 	kvm_cpu__show_registers(cpu);
396e1063726SSasha Levin 	kvm_cpu__show_code(cpu);
397e1063726SSasha Levin 	kvm_cpu__show_page_tables(cpu);
398e1063726SSasha Levin 	fflush(stdout);
399e1063726SSasha Levin 	printout_done = 1;
400e1063726SSasha Levin }
401e1063726SSasha Levin 
402e1063726SSasha Levin static void handle_debug(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
403e1063726SSasha Levin {
404e1063726SSasha Levin 	int i;
405e1063726SSasha Levin 	struct debug_cmd_params *params;
406e1063726SSasha Levin 	u32 dbg_type;
407e1063726SSasha Levin 	u32 vcpu;
408e1063726SSasha Levin 
409e1063726SSasha Levin 	if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
410e1063726SSasha Levin 		return;
411e1063726SSasha Levin 
412e1063726SSasha Levin 	params = (void *)msg;
413e1063726SSasha Levin 	dbg_type = params->dbg_type;
414e1063726SSasha Levin 	vcpu = params->cpu;
415e1063726SSasha Levin 
416e1063726SSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ)
417e1063726SSasha Levin 		serial8250__inject_sysrq(kvm, params->sysrq);
418e1063726SSasha Levin 
419e1063726SSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
420e1063726SSasha Levin 		if ((int)vcpu >= kvm->nrcpus)
421e1063726SSasha Levin 			return;
422e1063726SSasha Levin 
423e1063726SSasha Levin 		kvm->cpus[vcpu]->needs_nmi = 1;
424e1063726SSasha Levin 		pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1);
425e1063726SSasha Levin 	}
426e1063726SSasha Levin 
427e1063726SSasha Levin 	if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
428e1063726SSasha Levin 		return;
429e1063726SSasha Levin 
430e1063726SSasha Levin 	for (i = 0; i < kvm->nrcpus; i++) {
431e1063726SSasha Levin 		struct kvm_cpu *cpu = kvm->cpus[i];
432e1063726SSasha Levin 
433e1063726SSasha Levin 		if (!cpu)
434e1063726SSasha Levin 			continue;
435e1063726SSasha Levin 
436e1063726SSasha Levin 		printout_done = 0;
437e1063726SSasha Levin 
438e1063726SSasha Levin 		kvm_cpu__set_debug_fd(fd);
439e1063726SSasha Levin 		pthread_kill(cpu->thread, SIGUSR1);
440e1063726SSasha Levin 		/*
441e1063726SSasha Levin 		 * Wait for the vCPU to dump state before signalling
442e1063726SSasha Levin 		 * the next thread. Since this is debug code it does
443e1063726SSasha Levin 		 * not matter that we are burning CPU time a bit:
444e1063726SSasha Levin 		 */
445e1063726SSasha Levin 		while (!printout_done)
446e1063726SSasha Levin 			sleep(0);
447e1063726SSasha Levin 	}
448e1063726SSasha Levin 
449e1063726SSasha Levin 	close(fd);
450e1063726SSasha Levin 
451e1063726SSasha Levin 	serial8250__inject_sysrq(kvm, 'p');
452e1063726SSasha Levin }
453e1063726SSasha Levin 
454e1063726SSasha Levin int kvm_ipc__init(struct kvm *kvm)
4554b1addaeSSasha Levin {
456e21e8ff3SYang Bai 	int ret;
457e1063726SSasha Levin 	int sock = kvm__create_socket(kvm);
45821b3c2c0SSasha Levin 	struct epoll_event ev = {0};
4594b1addaeSSasha Levin 
4604b1addaeSSasha Levin 	server_fd = sock;
4614b1addaeSSasha Levin 
4624b1addaeSSasha Levin 	epoll_fd = epoll_create(KVM_IPC_MAX_MSGS);
463e21e8ff3SYang Bai 	if (epoll_fd < 0) {
464211370d6SMichael Ellerman 		perror("epoll_create");
465e21e8ff3SYang Bai 		ret = epoll_fd;
466e21e8ff3SYang Bai 		goto err;
467e21e8ff3SYang Bai 	}
4684b1addaeSSasha Levin 
46947f72b90SSasha Levin 	ev.events = EPOLLIN | EPOLLET;
4704b1addaeSSasha Levin 	ev.data.fd = sock;
471e21e8ff3SYang Bai 	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev) < 0) {
472211370d6SMichael Ellerman 		pr_err("Failed adding socket to epoll");
473e21e8ff3SYang Bai 		ret = -EFAULT;
474e21e8ff3SYang Bai 		goto err_epoll;
475e21e8ff3SYang Bai 	}
4764b1addaeSSasha Levin 
477c733c80bSSasha Levin 	stop_fd = eventfd(0, 0);
478e21e8ff3SYang Bai 	if (stop_fd < 0) {
479211370d6SMichael Ellerman 		perror("eventfd");
480e21e8ff3SYang Bai 		ret = stop_fd;
481e21e8ff3SYang Bai 		goto err_epoll;
482e21e8ff3SYang Bai 	}
483e21e8ff3SYang Bai 
48447f72b90SSasha Levin 	ev.events = EPOLLIN | EPOLLET;
485c733c80bSSasha Levin 	ev.data.fd = stop_fd;
486e21e8ff3SYang Bai 	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, stop_fd, &ev) < 0) {
487e21e8ff3SYang Bai 		pr_err("Failed adding stop event to epoll");
488e21e8ff3SYang Bai 		ret = -EFAULT;
489e21e8ff3SYang Bai 		goto err_stop;
490e21e8ff3SYang Bai 	}
491c733c80bSSasha Levin 
492e1063726SSasha Levin 	if (pthread_create(&thread, NULL, kvm_ipc__thread, kvm) != 0) {
493e21e8ff3SYang Bai 		pr_err("Failed starting IPC thread");
494e21e8ff3SYang Bai 		ret = -EFAULT;
495e21e8ff3SYang Bai 		goto err_stop;
496e21e8ff3SYang Bai 	}
4974b1addaeSSasha Levin 
498e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_PID, kvm__pid);
499e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
500e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
501e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
502e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
503e1063726SSasha Levin 	kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
504e1063726SSasha Levin 	signal(SIGUSR1, handle_sigusr1);
505e1063726SSasha Levin 
5064b1addaeSSasha Levin 	return 0;
507e21e8ff3SYang Bai 
508e21e8ff3SYang Bai err_stop:
509e21e8ff3SYang Bai 	close(stop_fd);
510e21e8ff3SYang Bai err_epoll:
511e21e8ff3SYang Bai 	close(epoll_fd);
512e21e8ff3SYang Bai err:
513e21e8ff3SYang Bai 	return ret;
5144b1addaeSSasha Levin }
51549a8afd1SSasha Levin base_init(kvm_ipc__init);
516c733c80bSSasha Levin 
517e1063726SSasha Levin int kvm_ipc__exit(struct kvm *kvm)
518c733c80bSSasha Levin {
519c733c80bSSasha Levin 	u64 val = 1;
520c733c80bSSasha Levin 	int ret;
521c733c80bSSasha Levin 
522c733c80bSSasha Levin 	ret = write(stop_fd, &val, sizeof(val));
523c733c80bSSasha Levin 	if (ret < 0)
524c733c80bSSasha Levin 		return ret;
525c733c80bSSasha Levin 
526c733c80bSSasha Levin 	close(server_fd);
527c733c80bSSasha Levin 	close(epoll_fd);
528c733c80bSSasha Levin 
529e1063726SSasha Levin 	kvm__remove_socket(kvm->cfg.guest_name);
530e1063726SSasha Levin 
531c733c80bSSasha Levin 	return ret;
532c733c80bSSasha Levin }
53349a8afd1SSasha Levin base_exit(kvm_ipc__exit);
534