xref: /kvmtool/builtin-run.c (revision 5f22512429e0af50042d31b80ba63fed2783271d)
1ece09f8fSPekka Enberg #include "kvm/builtin-run.h"
2ece09f8fSPekka Enberg 
3c8675741SSasha Levin #include "kvm/builtin-setup.h"
4ece09f8fSPekka Enberg #include "kvm/virtio-balloon.h"
5ece09f8fSPekka Enberg #include "kvm/virtio-console.h"
6ece09f8fSPekka Enberg #include "kvm/parse-options.h"
7ece09f8fSPekka Enberg #include "kvm/8250-serial.h"
8ece09f8fSPekka Enberg #include "kvm/framebuffer.h"
9ece09f8fSPekka Enberg #include "kvm/disk-image.h"
10ece09f8fSPekka Enberg #include "kvm/threadpool.h"
11a67da3beSAsias He #include "kvm/virtio-scsi.h"
12ece09f8fSPekka Enberg #include "kvm/virtio-blk.h"
13ece09f8fSPekka Enberg #include "kvm/virtio-net.h"
14ece09f8fSPekka Enberg #include "kvm/virtio-rng.h"
15ece09f8fSPekka Enberg #include "kvm/ioeventfd.h"
16ece09f8fSPekka Enberg #include "kvm/virtio-9p.h"
17ece09f8fSPekka Enberg #include "kvm/barrier.h"
18ece09f8fSPekka Enberg #include "kvm/kvm-cpu.h"
19ece09f8fSPekka Enberg #include "kvm/ioport.h"
20ece09f8fSPekka Enberg #include "kvm/symbol.h"
21ece09f8fSPekka Enberg #include "kvm/i8042.h"
22ece09f8fSPekka Enberg #include "kvm/mutex.h"
23ece09f8fSPekka Enberg #include "kvm/term.h"
24ece09f8fSPekka Enberg #include "kvm/util.h"
25ec52d504SLai Jiangshan #include "kvm/strbuf.h"
26ece09f8fSPekka Enberg #include "kvm/vesa.h"
27ece09f8fSPekka Enberg #include "kvm/irq.h"
28ece09f8fSPekka Enberg #include "kvm/kvm.h"
29ece09f8fSPekka Enberg #include "kvm/pci.h"
30ece09f8fSPekka Enberg #include "kvm/rtc.h"
31ece09f8fSPekka Enberg #include "kvm/sdl.h"
32ece09f8fSPekka Enberg #include "kvm/vnc.h"
33e6694207SSasha Levin #include "kvm/guest_compat.h"
3495d13a52SSasha Levin #include "kvm/pci-shmem.h"
354b1addaeSSasha Levin #include "kvm/kvm-ipc.h"
364b1c6f6eSSasha Levin #include "kvm/builtin-debug.h"
37ece09f8fSPekka Enberg 
38ece09f8fSPekka Enberg #include <linux/types.h>
3948d9e01aSSasha Levin #include <linux/err.h>
40ece09f8fSPekka Enberg 
418329f30bSPekka Enberg #include <sys/utsname.h>
428329f30bSPekka Enberg #include <sys/types.h>
438329f30bSPekka Enberg #include <sys/stat.h>
44ece09f8fSPekka Enberg #include <termios.h>
45ece09f8fSPekka Enberg #include <signal.h>
46ece09f8fSPekka Enberg #include <stdlib.h>
47ece09f8fSPekka Enberg #include <string.h>
48ece09f8fSPekka Enberg #include <unistd.h>
4926c853e4SPrasad Joshi #include <ctype.h>
50ece09f8fSPekka Enberg #include <stdio.h>
51f967c427SPrasad Joshi 
52f967c427SPrasad Joshi #define MB_SHIFT		(20)
5395d13a52SSasha Levin #define KB_SHIFT		(10)
5495d13a52SSasha Levin #define GB_SHIFT		(30)
55f967c427SPrasad Joshi 
564298ddadSSasha Levin struct kvm *kvm;
57656be1b8SSasha Levin __thread struct kvm_cpu *current_kvm_cpu;
58f967c427SPrasad Joshi 
593c29e2aaSSasha Levin static int  kvm_run_wrapper;
60f967c427SPrasad Joshi 
61ed036f03SCyrill Gorcunov bool do_debug_print = false;
62ed036f03SCyrill Gorcunov 
63890364f8SCyrill Gorcunov static int vidmode = -1;
64d77a9efaSCyrill Gorcunov 
65afc2c7c0SAsias He extern char _binary_guest_init_start;
66afc2c7c0SAsias He extern char _binary_guest_init_size;
67afc2c7c0SAsias He 
68f967c427SPrasad Joshi static const char * const run_usage[] = {
698d2ff5daSWanlong Gao 	"lkvm run [<options>] [<kernel image>]",
70f967c427SPrasad Joshi 	NULL
71f967c427SPrasad Joshi };
72f967c427SPrasad Joshi 
733c29e2aaSSasha Levin enum {
74e0747665SSasha Levin 	KVM_RUN_DEFAULT,
753c29e2aaSSasha Levin 	KVM_RUN_SANDBOX,
763c29e2aaSSasha Levin };
773c29e2aaSSasha Levin 
78a33979d8SSasha Levin static int img_name_parser(const struct option *opt, const char *arg, int unset)
79a33979d8SSasha Levin {
8082d65b5eSSasha Levin 	char path[PATH_MAX];
815236b505SAsias He 	struct stat st;
823b55dcdeSSasha Levin 	struct kvm *kvm = opt->ptr;
8359aa2d30SSasha Levin 
8459aa2d30SSasha Levin 	if (stat(arg, &st) == 0 &&
8559aa2d30SSasha Levin 	    S_ISDIR(st.st_mode)) {
8659aa2d30SSasha Levin 		char tmp[PATH_MAX];
8759aa2d30SSasha Levin 
8847621338SSasha Levin 		if (kvm->cfg.using_rootfs)
892c908af9SLai Jiangshan 			die("Please use only one rootfs directory atmost");
902c908af9SLai Jiangshan 
9159aa2d30SSasha Levin 		if (realpath(arg, tmp) == 0 ||
92c7838fbdSSasha Levin 		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
9359aa2d30SSasha Levin 			die("Unable to initialize virtio 9p");
9447621338SSasha Levin 		kvm->cfg.using_rootfs = 1;
9559aa2d30SSasha Levin 		return 0;
9659aa2d30SSasha Levin 	}
97a33979d8SSasha Levin 
989667701cSPekka Enberg 	snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
9982d65b5eSSasha Levin 
10082d65b5eSSasha Levin 	if (stat(path, &st) == 0 &&
10182d65b5eSSasha Levin 	    S_ISDIR(st.st_mode)) {
10282d65b5eSSasha Levin 		char tmp[PATH_MAX];
10382d65b5eSSasha Levin 
10447621338SSasha Levin 		if (kvm->cfg.using_rootfs)
1052c908af9SLai Jiangshan 			die("Please use only one rootfs directory atmost");
1062c908af9SLai Jiangshan 
10782d65b5eSSasha Levin 		if (realpath(path, tmp) == 0 ||
10882d65b5eSSasha Levin 		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
10982d65b5eSSasha Levin 			die("Unable to initialize virtio 9p");
11082d65b5eSSasha Levin 		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
11182d65b5eSSasha Levin 			die("Unable to initialize virtio 9p");
11269c88b95SSasha Levin 		kvm_setup_resolv(arg);
11347621338SSasha Levin 		kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1;
11447621338SSasha Levin 		kvm->cfg.custom_rootfs_name = arg;
11582d65b5eSSasha Levin 		return 0;
11682d65b5eSSasha Levin 	}
11782d65b5eSSasha Levin 
1183b55dcdeSSasha Levin 	return disk_img_name_parser(opt, arg, unset);
119a67da3beSAsias He }
120a67da3beSAsias He 
1213b55dcdeSSasha Levin void kvm_run_set_wrapper_sandbox(void)
1223b55dcdeSSasha Levin {
1233b55dcdeSSasha Levin 	kvm_run_wrapper = KVM_RUN_SANDBOX;
124a33979d8SSasha Levin }
125a33979d8SSasha Levin 
126b4422bf3SAneesh Kumar K.V static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset)
127b4422bf3SAneesh Kumar K.V {
128b4422bf3SAneesh Kumar K.V 	char *tag_name;
129b4422bf3SAneesh Kumar K.V 	char tmp[PATH_MAX];
130b4422bf3SAneesh Kumar K.V 
131b4422bf3SAneesh Kumar K.V 	/*
132b4422bf3SAneesh Kumar K.V 	 * 9p dir can be of the form dirname,tag_name or
133b4422bf3SAneesh Kumar K.V 	 * just dirname. In the later case we use the
134b4422bf3SAneesh Kumar K.V 	 * default tag name
135b4422bf3SAneesh Kumar K.V 	 */
136b4422bf3SAneesh Kumar K.V 	tag_name = strstr(arg, ",");
137b4422bf3SAneesh Kumar K.V 	if (tag_name) {
138b4422bf3SAneesh Kumar K.V 		*tag_name = '\0';
139b4422bf3SAneesh Kumar K.V 		tag_name++;
140b4422bf3SAneesh Kumar K.V 	}
14154f6802dSPekka Enberg 	if (realpath(arg, tmp)) {
142c7838fbdSSasha Levin 		if (virtio_9p__register(kvm, tmp, tag_name) < 0)
14354f6802dSPekka Enberg 			die("Unable to initialize virtio 9p");
14454f6802dSPekka Enberg 	} else
145b4422bf3SAneesh Kumar K.V 		die("Failed resolving 9p path");
146b4422bf3SAneesh Kumar K.V 	return 0;
147b4422bf3SAneesh Kumar K.V }
148b4422bf3SAneesh Kumar K.V 
1493b55dcdeSSasha Levin #define BUILD_OPTIONS(name, cfg, kvm)					\
150b816364aSSasha Levin 	struct option name[] = {					\
151b816364aSSasha Levin 	OPT_GROUP("Basic options:"),					\
152b816364aSSasha Levin 	OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name",	\
153b816364aSSasha Levin 			"A name for the guest"),			\
15400ebbe96SSasha Levin 	OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"),	\
155b816364aSSasha Levin 	OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory size\
156b816364aSSasha Levin 		in MiB."),						\
157b816364aSSasha Levin 	OPT_CALLBACK('\0', "shmem", NULL,				\
158b816364aSSasha Levin 		     "[pci:]<addr>:<size>[:handle=<handle>][:create]",	\
159b816364aSSasha Levin 		     "Share host shmem with guest via pci device",	\
1601dc24dccSSasha Levin 		     shmem_parser, NULL),				\
1611dc24dccSSasha Levin 	OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk 	\
1621dc24dccSSasha Levin 			image or rootfs directory", img_name_parser,	\
1633b55dcdeSSasha Levin 			kvm),						\
164b816364aSSasha Levin 	OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio	\
165b816364aSSasha Levin 			balloon"),					\
166b816364aSSasha Levin 	OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\
167b816364aSSasha Levin 	OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\
168b816364aSSasha Levin 	OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio Random\
169b816364aSSasha Levin 			Number Generator"),				\
170b816364aSSasha Levin 	OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name",		\
171b816364aSSasha Levin 		     "Enable virtio 9p to share files between host and	\
1721dc24dccSSasha Levin 		     guest", virtio_9p_rootdir_parser, NULL),		\
173b816364aSSasha Levin 	OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or	\
174b816364aSSasha Levin 			hv", "Console to use"),				\
175b816364aSSasha Levin 	OPT_STRING('\0', "dev", &(cfg)->dev, "device_file",		\
176b816364aSSasha Levin 			"KVM device file"),				\
177b816364aSSasha Levin 	OPT_CALLBACK('\0', "tty", NULL, "tty id",			\
178b816364aSSasha Levin 		     "Remap guest TTY into a pty on the host",		\
1791dc24dccSSasha Levin 		     tty_parser, NULL),					\
180b816364aSSasha Levin 	OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script",		\
181b816364aSSasha Levin 			"Run this script when booting into custom	\
182b816364aSSasha Levin 			rootfs"),					\
183b816364aSSasha Levin 	OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path",	\
184b816364aSSasha Levin 			"Hugetlbfs path"),				\
185b816364aSSasha Levin 									\
186b816364aSSasha Levin 	OPT_GROUP("Kernel options:"),					\
187b816364aSSasha Levin 	OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel",	\
188b816364aSSasha Levin 			"Kernel to boot in virtual machine"),		\
189b816364aSSasha Levin 	OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd",	\
190b816364aSSasha Levin 			"Initial RAM disk image"),			\
191b816364aSSasha Levin 	OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params",	\
192b816364aSSasha Levin 			"Kernel command line arguments"),		\
193b816364aSSasha Levin 	OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\
194b816364aSSasha Levin 			"Firmware image to boot in virtual machine"),	\
195b816364aSSasha Levin 									\
196b816364aSSasha Levin 	OPT_GROUP("Networking options:"),				\
197b816364aSSasha Levin 	OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",	\
198b816364aSSasha Levin 		     "Create a new guest NIC",				\
199*5f225124SSasha Levin 		     netdev_parser, NULL, kvm),				\
200b816364aSSasha Levin 	OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\
201b816364aSSasha Levin 			in rootfs mode"),				\
202b816364aSSasha Levin 									\
203b816364aSSasha Levin 	OPT_GROUP("BIOS options:"),					\
204b816364aSSasha Levin 	OPT_INTEGER('\0', "vidmode", &vidmode,				\
205b816364aSSasha Levin 		    "Video mode"),					\
206b816364aSSasha Levin 									\
207b816364aSSasha Levin 	OPT_GROUP("Debug options:"),					\
208b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug", &do_debug_print,			\
209b816364aSSasha Levin 			"Enable debug messages"),			\
210b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step,	\
211b816364aSSasha Levin 			"Enable single stepping"),			\
2125765977dSSasha Levin 	OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug,		\
213b816364aSSasha Levin 			"Enable ioport debugging"),			\
214e830cce7SSasha Levin 	OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug,		\
215b816364aSSasha Levin 			"Enable MMIO debugging"),			\
2163b55dcdeSSasha Levin 	OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay,	\
217b816364aSSasha Levin 			"Delay IO by millisecond"),			\
218b816364aSSasha Levin 	OPT_END()							\
219f967c427SPrasad Joshi 	};
220f967c427SPrasad Joshi 
221b5b501ccSIngo Molnar /*
222b5b501ccSIngo Molnar  * Serialize debug printout so that the output of multiple vcpus does not
223b5b501ccSIngo Molnar  * get mixed up:
224b5b501ccSIngo Molnar  */
225cffeab25SIngo Molnar static int printout_done;
226b5b501ccSIngo Molnar 
22743119af7SPekka Enberg static void handle_sigusr1(int sig)
22843119af7SPekka Enberg {
22943119af7SPekka Enberg 	struct kvm_cpu *cpu = current_kvm_cpu;
230b7d2f013SSasha Levin 	int fd = kvm_cpu__get_debug_fd();
23143119af7SPekka Enberg 
2324b1c6f6eSSasha Levin 	if (!cpu || cpu->needs_nmi)
23343119af7SPekka Enberg 		return;
23443119af7SPekka Enberg 
235b7d2f013SSasha Levin 	dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
23643119af7SPekka Enberg 	kvm_cpu__show_registers(cpu);
23743119af7SPekka Enberg 	kvm_cpu__show_code(cpu);
23843119af7SPekka Enberg 	kvm_cpu__show_page_tables(cpu);
239b5b501ccSIngo Molnar 	fflush(stdout);
240cffeab25SIngo Molnar 	printout_done = 1;
241cffeab25SIngo Molnar 	mb();
24243119af7SPekka Enberg }
24343119af7SPekka Enberg 
244d94e22b9SSasha Levin /* Pause/resume the guest using SIGUSR2 */
245d94e22b9SSasha Levin static int is_paused;
246d94e22b9SSasha Levin 
2474b1addaeSSasha Levin static void handle_pause(int fd, u32 type, u32 len, u8 *msg)
248d94e22b9SSasha Levin {
2495aa502e4SLai Jiangshan 	if (WARN_ON(len))
2505aa502e4SLai Jiangshan 		return;
2515aa502e4SLai Jiangshan 
2527021c50bSAsias He 	if (type == KVM_IPC_RESUME && is_paused) {
2537021c50bSAsias He 		kvm->vm_state = KVM_VMSTATE_RUNNING;
254d94e22b9SSasha Levin 		kvm__continue();
2557021c50bSAsias He 	} else if (type == KVM_IPC_PAUSE && !is_paused) {
2567021c50bSAsias He 		kvm->vm_state = KVM_VMSTATE_PAUSED;
257eb8dad9dSSasha Levin 		ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL);
258d94e22b9SSasha Levin 		kvm__pause();
2597021c50bSAsias He 	} else {
26002317b74SSasha Levin 		return;
2615aa502e4SLai Jiangshan 	}
262d94e22b9SSasha Levin 
263d94e22b9SSasha Levin 	is_paused = !is_paused;
264d94e22b9SSasha Levin }
265d94e22b9SSasha Levin 
2667021c50bSAsias He static void handle_vmstate(int fd, u32 type, u32 len, u8 *msg)
2677021c50bSAsias He {
2687021c50bSAsias He 	int r = 0;
2697021c50bSAsias He 
2707021c50bSAsias He 	if (type == KVM_IPC_VMSTATE)
2717021c50bSAsias He 		r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
2727021c50bSAsias He 
2737021c50bSAsias He 	if (r < 0)
2747021c50bSAsias He 		pr_warning("Failed sending VMSTATE");
2757021c50bSAsias He }
2767021c50bSAsias He 
2774b1addaeSSasha Levin static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
2789e854d1aSPekka Enberg {
2799e854d1aSPekka Enberg 	int i;
280a59cdf44SLai Jiangshan 	struct debug_cmd_params *params;
281a59cdf44SLai Jiangshan 	u32 dbg_type;
282a59cdf44SLai Jiangshan 	u32 vcpu;
283a59cdf44SLai Jiangshan 
284a59cdf44SLai Jiangshan 	if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
285a59cdf44SLai Jiangshan 		return;
286a59cdf44SLai Jiangshan 
287a59cdf44SLai Jiangshan 	params = (void *)msg;
288a59cdf44SLai Jiangshan 	dbg_type = params->dbg_type;
289a59cdf44SLai Jiangshan 	vcpu = params->cpu;
2904b1c6f6eSSasha Levin 
291226e727bSSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ)
292226e727bSSasha Levin 		serial8250__inject_sysrq(kvm, params->sysrq);
293226e727bSSasha Levin 
2944b1c6f6eSSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
2957070414aSSasha Levin 		if ((int)vcpu >= kvm->nrcpus)
2964b1c6f6eSSasha Levin 			return;
2974b1c6f6eSSasha Levin 
298df4239fbSSasha Levin 		kvm->cpus[vcpu]->needs_nmi = 1;
299df4239fbSSasha Levin 		pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1);
3004b1c6f6eSSasha Levin 	}
3014b1c6f6eSSasha Levin 
3024b1c6f6eSSasha Levin 	if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
3034b1c6f6eSSasha Levin 		return;
3049e854d1aSPekka Enberg 
30500ebbe96SSasha Levin 	for (i = 0; i < kvm->nrcpus; i++) {
306df4239fbSSasha Levin 		struct kvm_cpu *cpu = kvm->cpus[i];
3079e854d1aSPekka Enberg 
30843119af7SPekka Enberg 		if (!cpu)
30943119af7SPekka Enberg 			continue;
31043119af7SPekka Enberg 
311cffeab25SIngo Molnar 		printout_done = 0;
312b7d2f013SSasha Levin 
313b7d2f013SSasha Levin 		kvm_cpu__set_debug_fd(fd);
31443119af7SPekka Enberg 		pthread_kill(cpu->thread, SIGUSR1);
315cffeab25SIngo Molnar 		/*
316cffeab25SIngo Molnar 		 * Wait for the vCPU to dump state before signalling
317cffeab25SIngo Molnar 		 * the next thread. Since this is debug code it does
318cffeab25SIngo Molnar 		 * not matter that we are burning CPU time a bit:
319cffeab25SIngo Molnar 		 */
320cffeab25SIngo Molnar 		while (!printout_done)
321cffeab25SIngo Molnar 			mb();
3229e854d1aSPekka Enberg 	}
3239e854d1aSPekka Enberg 
324b7d2f013SSasha Levin 	close(fd);
325b7d2f013SSasha Levin 
326226e727bSSasha Levin 	serial8250__inject_sysrq(kvm, 'p');
3279e854d1aSPekka Enberg }
3289e854d1aSPekka Enberg 
3299e854d1aSPekka Enberg static void handle_sigalrm(int sig)
3309e854d1aSPekka Enberg {
3310b69bdefSMatt Evans 	kvm__arch_periodic_poll(kvm);
3329e854d1aSPekka Enberg }
3339e854d1aSPekka Enberg 
3344b1addaeSSasha Levin static void handle_stop(int fd, u32 type, u32 len, u8 *msg)
335daf4cb5aSSasha Levin {
336e333e41aSLai Jiangshan 	if (WARN_ON(type != KVM_IPC_STOP || len))
337e333e41aSLai Jiangshan 		return;
338e333e41aSLai Jiangshan 
339df4239fbSSasha Levin 	kvm_cpu__reboot(kvm);
340daf4cb5aSSasha Levin }
341daf4cb5aSSasha Levin 
3425ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg)
3435ee154d1SPekka Enberg {
344d77a9efaSCyrill Gorcunov 	current_kvm_cpu		= arg;
3455ee154d1SPekka Enberg 
346d77a9efaSCyrill Gorcunov 	if (kvm_cpu__start(current_kvm_cpu))
3475ee154d1SPekka Enberg 		goto panic_kvm;
3485ee154d1SPekka Enberg 
3495ee154d1SPekka Enberg 	return (void *) (intptr_t) 0;
3505ee154d1SPekka Enberg 
3515ee154d1SPekka Enberg panic_kvm:
3523fdf659dSSasha Levin 	fprintf(stderr, "KVM exit reason: %u (\"%s\")\n",
353d77a9efaSCyrill Gorcunov 		current_kvm_cpu->kvm_run->exit_reason,
354d77a9efaSCyrill Gorcunov 		kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]);
355d77a9efaSCyrill Gorcunov 	if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
3565ee154d1SPekka Enberg 		fprintf(stderr, "KVM exit code: 0x%Lu\n",
357d77a9efaSCyrill Gorcunov 			current_kvm_cpu->kvm_run->hw.hardware_exit_reason);
3588e5accedSPekka Enberg 
359b7d2f013SSasha Levin 	kvm_cpu__set_debug_fd(STDOUT_FILENO);
360d77a9efaSCyrill Gorcunov 	kvm_cpu__show_registers(current_kvm_cpu);
361d77a9efaSCyrill Gorcunov 	kvm_cpu__show_code(current_kvm_cpu);
362d77a9efaSCyrill Gorcunov 	kvm_cpu__show_page_tables(current_kvm_cpu);
3635ee154d1SPekka Enberg 
3645ee154d1SPekka Enberg 	return (void *) (intptr_t) 1;
3655ee154d1SPekka Enberg }
3665ee154d1SPekka Enberg 
367e08c0896SPrasad Joshi static char kernel[PATH_MAX];
368b0b42ba0SPekka Enberg 
369b0b42ba0SPekka Enberg static const char *host_kernels[] = {
370e08c0896SPrasad Joshi 	"/boot/vmlinuz",
371e08c0896SPrasad Joshi 	"/boot/bzImage",
372e08c0896SPrasad Joshi 	NULL
373e08c0896SPrasad Joshi };
374b0b42ba0SPekka Enberg 
375b0b42ba0SPekka Enberg static const char *default_kernels[] = {
376e08c0896SPrasad Joshi 	"./bzImage",
377b03af790SKonstantin Khlebnikov 	"arch/" BUILD_ARCH "/boot/bzImage",
378af7b0868SMatt Evans 	"../../arch/" BUILD_ARCH "/boot/bzImage",
379e08c0896SPrasad Joshi 	NULL
380e08c0896SPrasad Joshi };
3818329f30bSPekka Enberg 
382b0b42ba0SPekka Enberg static const char *default_vmlinux[] = {
383b03af790SKonstantin Khlebnikov 	"vmlinux",
384b0b42ba0SPekka Enberg 	"../../../vmlinux",
385b0b42ba0SPekka Enberg 	"../../vmlinux",
386b0b42ba0SPekka Enberg 	NULL
387b0b42ba0SPekka Enberg };
388b0b42ba0SPekka Enberg 
389e08c0896SPrasad Joshi static void kernel_usage_with_options(void)
3908329f30bSPekka Enberg {
391e08c0896SPrasad Joshi 	const char **k;
3928329f30bSPekka Enberg 	struct utsname uts;
393e08c0896SPrasad Joshi 
394e08c0896SPrasad Joshi 	fprintf(stderr, "Fatal: could not find default kernel image in:\n");
39565182f37SPrasad Joshi 	k = &default_kernels[0];
396e08c0896SPrasad Joshi 	while (*k) {
397e08c0896SPrasad Joshi 		fprintf(stderr, "\t%s\n", *k);
398e08c0896SPrasad Joshi 		k++;
399e08c0896SPrasad Joshi 	}
400e08c0896SPrasad Joshi 
401e08c0896SPrasad Joshi 	if (uname(&uts) < 0)
402e08c0896SPrasad Joshi 		return;
403e08c0896SPrasad Joshi 
404e08c0896SPrasad Joshi 	k = &host_kernels[0];
405e08c0896SPrasad Joshi 	while (*k) {
406e08c0896SPrasad Joshi 		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
407e08c0896SPrasad Joshi 			return;
408e08c0896SPrasad Joshi 		fprintf(stderr, "\t%s\n", kernel);
409e08c0896SPrasad Joshi 		k++;
410e08c0896SPrasad Joshi 	}
411ee8b1456SWanlong Gao 	fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n",
412ee8b1456SWanlong Gao 		KVM_BINARY_NAME);
413e08c0896SPrasad Joshi }
414e08c0896SPrasad Joshi 
41560ded003SPekka Enberg static u64 host_ram_size(void)
41660ded003SPekka Enberg {
41760ded003SPekka Enberg 	long page_size;
41860ded003SPekka Enberg 	long nr_pages;
41960ded003SPekka Enberg 
42060ded003SPekka Enberg 	nr_pages	= sysconf(_SC_PHYS_PAGES);
421d63c5ce6SPekka Enberg 	if (nr_pages < 0) {
4224542f276SCyrill Gorcunov 		pr_warning("sysconf(_SC_PHYS_PAGES) failed");
423d63c5ce6SPekka Enberg 		return 0;
424d63c5ce6SPekka Enberg 	}
42560ded003SPekka Enberg 
42660ded003SPekka Enberg 	page_size	= sysconf(_SC_PAGE_SIZE);
427d63c5ce6SPekka Enberg 	if (page_size < 0) {
4284542f276SCyrill Gorcunov 		pr_warning("sysconf(_SC_PAGE_SIZE) failed");
429d63c5ce6SPekka Enberg 		return 0;
430d63c5ce6SPekka Enberg 	}
43160ded003SPekka Enberg 
43260ded003SPekka Enberg 	return (nr_pages * page_size) >> MB_SHIFT;
43360ded003SPekka Enberg }
43460ded003SPekka Enberg 
43518bd8c3bSPekka Enberg /*
43618bd8c3bSPekka Enberg  * If user didn't specify how much memory it wants to allocate for the guest,
43718bd8c3bSPekka Enberg  * avoid filling the whole host RAM.
43818bd8c3bSPekka Enberg  */
43918bd8c3bSPekka Enberg #define RAM_SIZE_RATIO		0.8
44018bd8c3bSPekka Enberg 
441fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus)
442fd834defSPekka Enberg {
44306761c76SPekka Enberg 	u64 available;
44406761c76SPekka Enberg 	u64 ram_size;
445fd834defSPekka Enberg 
446fd834defSPekka Enberg 	ram_size	= 64 * (nr_cpus + 3);
447fd834defSPekka Enberg 
44860ded003SPekka Enberg 	available	= host_ram_size() * RAM_SIZE_RATIO;
449d63c5ce6SPekka Enberg 	if (!available)
450d63c5ce6SPekka Enberg 		available = MIN_RAM_SIZE_MB;
451fd834defSPekka Enberg 
452fd834defSPekka Enberg 	if (ram_size > available)
453fd834defSPekka Enberg 		ram_size	= available;
454fd834defSPekka Enberg 
455fd834defSPekka Enberg 	return ram_size;
456fd834defSPekka Enberg }
457fd834defSPekka Enberg 
458e08c0896SPrasad Joshi static const char *find_kernel(void)
459e08c0896SPrasad Joshi {
460e08c0896SPrasad Joshi 	const char **k;
4618329f30bSPekka Enberg 	struct stat st;
462e08c0896SPrasad Joshi 	struct utsname uts;
463e08c0896SPrasad Joshi 
46465182f37SPrasad Joshi 	k = &default_kernels[0];
465e08c0896SPrasad Joshi 	while (*k) {
466e08c0896SPrasad Joshi 		if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) {
467e08c0896SPrasad Joshi 			k++;
468e08c0896SPrasad Joshi 			continue;
469e08c0896SPrasad Joshi 		}
470e08c0896SPrasad Joshi 		strncpy(kernel, *k, PATH_MAX);
471e08c0896SPrasad Joshi 		return kernel;
472e08c0896SPrasad Joshi 	}
4738329f30bSPekka Enberg 
4748329f30bSPekka Enberg 	if (uname(&uts) < 0)
4758329f30bSPekka Enberg 		return NULL;
4768329f30bSPekka Enberg 
477e08c0896SPrasad Joshi 	k = &host_kernels[0];
478e08c0896SPrasad Joshi 	while (*k) {
479e08c0896SPrasad Joshi 		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
4808329f30bSPekka Enberg 			return NULL;
4818329f30bSPekka Enberg 
482e08c0896SPrasad Joshi 		if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) {
483e08c0896SPrasad Joshi 			k++;
484e08c0896SPrasad Joshi 			continue;
485e08c0896SPrasad Joshi 		}
486e08c0896SPrasad Joshi 		return kernel;
4878329f30bSPekka Enberg 
488e08c0896SPrasad Joshi 	}
4898329f30bSPekka Enberg 	return NULL;
4908329f30bSPekka Enberg }
4918329f30bSPekka Enberg 
492b0b42ba0SPekka Enberg static const char *find_vmlinux(void)
493b0b42ba0SPekka Enberg {
494b0b42ba0SPekka Enberg 	const char **vmlinux;
495b0b42ba0SPekka Enberg 
496b0b42ba0SPekka Enberg 	vmlinux = &default_vmlinux[0];
497b0b42ba0SPekka Enberg 	while (*vmlinux) {
498b0b42ba0SPekka Enberg 		struct stat st;
499b0b42ba0SPekka Enberg 
500b0b42ba0SPekka Enberg 		if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) {
501b0b42ba0SPekka Enberg 			vmlinux++;
502b0b42ba0SPekka Enberg 			continue;
503b0b42ba0SPekka Enberg 		}
504b0b42ba0SPekka Enberg 		return *vmlinux;
505b0b42ba0SPekka Enberg 	}
506b0b42ba0SPekka Enberg 	return NULL;
507b0b42ba0SPekka Enberg }
508b0b42ba0SPekka Enberg 
509f6677a1dSAmerigo Wang void kvm_run_help(void)
510f6677a1dSAmerigo Wang {
5113b55dcdeSSasha Levin 	BUILD_OPTIONS(options, &kvm->cfg, kvm);
512f6677a1dSAmerigo Wang 	usage_with_options(run_usage, options);
513f6677a1dSAmerigo Wang }
514f6677a1dSAmerigo Wang 
515afc2c7c0SAsias He static int kvm_setup_guest_init(void)
5169cec19c8SSasha Levin {
51747621338SSasha Levin 	const char *rootfs = kvm->cfg.custom_rootfs_name;
518afc2c7c0SAsias He 	char tmp[PATH_MAX];
519afc2c7c0SAsias He 	size_t size;
520afc2c7c0SAsias He 	int fd, ret;
521afc2c7c0SAsias He 	char *data;
5229cec19c8SSasha Levin 
523afc2c7c0SAsias He 	/* Setup /virt/init */
524afc2c7c0SAsias He 	size = (size_t)&_binary_guest_init_size;
525afc2c7c0SAsias He 	data = (char *)&_binary_guest_init_start;
526afc2c7c0SAsias He 	snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs);
527afc2c7c0SAsias He 	remove(tmp);
528afc2c7c0SAsias He 	fd = open(tmp, O_CREAT | O_WRONLY, 0755);
529afc2c7c0SAsias He 	if (fd < 0)
530afc2c7c0SAsias He 		die("Fail to setup %s", tmp);
531afc2c7c0SAsias He 	ret = xwrite(fd, data, size);
532afc2c7c0SAsias He 	if (ret < 0)
533afc2c7c0SAsias He 		die("Fail to setup %s", tmp);
534afc2c7c0SAsias He 	close(fd);
5359cec19c8SSasha Levin 
536afc2c7c0SAsias He 	return 0;
5379cec19c8SSasha Levin }
5389cec19c8SSasha Levin 
539d50fe489SSasha Levin static int kvm_run_set_sandbox(void)
540d50fe489SSasha Levin {
54147621338SSasha Levin 	const char *guestfs_name = kvm->cfg.custom_rootfs_name;
542d50fe489SSasha Levin 	char path[PATH_MAX], script[PATH_MAX], *tmp;
543d50fe489SSasha Levin 
544d50fe489SSasha Levin 	snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name);
545d50fe489SSasha Levin 
546d50fe489SSasha Levin 	remove(path);
547d50fe489SSasha Levin 
54847621338SSasha Levin 	if (kvm->cfg.sandbox == NULL)
549d50fe489SSasha Levin 		return 0;
550d50fe489SSasha Levin 
55147621338SSasha Levin 	tmp = realpath(kvm->cfg.sandbox, NULL);
552d50fe489SSasha Levin 	if (tmp == NULL)
553d50fe489SSasha Levin 		return -ENOMEM;
554d50fe489SSasha Levin 
555d50fe489SSasha Levin 	snprintf(script, PATH_MAX, "/host/%s", tmp);
556d50fe489SSasha Levin 	free(tmp);
557d50fe489SSasha Levin 
558d50fe489SSasha Levin 	return symlink(script, path);
559d50fe489SSasha Levin }
560d50fe489SSasha Levin 
5615173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg)
5625173b4afSLai Jiangshan {
5635173b4afSLai Jiangshan 	const char *single_quote;
5645173b4afSLai Jiangshan 
5655173b4afSLai Jiangshan 	if (!*arg) { /* zero length string */
5665173b4afSLai Jiangshan 		if (write(fd, "''", 2) <= 0)
5675173b4afSLai Jiangshan 			die("Failed writing sandbox script");
5685173b4afSLai Jiangshan 		return;
5695173b4afSLai Jiangshan 	}
5705173b4afSLai Jiangshan 
5715173b4afSLai Jiangshan 	while (*arg) {
5725173b4afSLai Jiangshan 		single_quote = strchrnul(arg, '\'');
5735173b4afSLai Jiangshan 
5745173b4afSLai Jiangshan 		/* write non-single-quote string as #('string') */
5755173b4afSLai Jiangshan 		if (arg != single_quote) {
5765173b4afSLai Jiangshan 			if (write(fd, "'", 1) <= 0 ||
5775173b4afSLai Jiangshan 			    write(fd, arg, single_quote - arg) <= 0 ||
5785173b4afSLai Jiangshan 			    write(fd, "'", 1) <= 0)
5795173b4afSLai Jiangshan 				die("Failed writing sandbox script");
5805173b4afSLai Jiangshan 		}
5815173b4afSLai Jiangshan 
5825173b4afSLai Jiangshan 		/* write single quote as #("'") */
5835173b4afSLai Jiangshan 		if (*single_quote) {
5845173b4afSLai Jiangshan 			if (write(fd, "\"'\"", 3) <= 0)
5855173b4afSLai Jiangshan 				die("Failed writing sandbox script");
5865173b4afSLai Jiangshan 		} else
5875173b4afSLai Jiangshan 			break;
5885173b4afSLai Jiangshan 
5895173b4afSLai Jiangshan 		arg = single_quote + 1;
5905173b4afSLai Jiangshan 	}
5915173b4afSLai Jiangshan }
5925173b4afSLai Jiangshan 
5935cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len)
5945cd19aa0SPekka Enberg {
5955cd19aa0SPekka Enberg 	struct stat st;
596c2c742d9SPekka Enberg 	int err;
5975cd19aa0SPekka Enberg 
598c2c742d9SPekka Enberg 	err = stat(src, &st);
5995cd19aa0SPekka Enberg 
600c2c742d9SPekka Enberg 	if (!err && S_ISREG(st.st_mode)) {
6015cd19aa0SPekka Enberg 		char resolved_path[PATH_MAX];
6025cd19aa0SPekka Enberg 
603de3f75c9SPekka Enberg 		if (!realpath(src, resolved_path))
604de3f75c9SPekka Enberg 			die("Unable to resolve program %s: %s\n", src, strerror(errno));
6055cd19aa0SPekka Enberg 
6065cd19aa0SPekka Enberg 		snprintf(dst, len, "/host%s", resolved_path);
6075cd19aa0SPekka Enberg 	} else
6085cd19aa0SPekka Enberg 		strncpy(dst, src, len);
6095cd19aa0SPekka Enberg }
6105cd19aa0SPekka Enberg 
6113c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc)
6123c29e2aaSSasha Levin {
6133c29e2aaSSasha Levin 	const char script_hdr[] = "#! /bin/bash\n\n";
6145cd19aa0SPekka Enberg 	char program[PATH_MAX];
6153c29e2aaSSasha Levin 	int fd;
6163c29e2aaSSasha Levin 
61747621338SSasha Levin 	remove(kvm->cfg.sandbox);
6183c29e2aaSSasha Levin 
61947621338SSasha Levin 	fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777);
6203c29e2aaSSasha Levin 	if (fd < 0)
6213c29e2aaSSasha Levin 		die("Failed creating sandbox script");
6223c29e2aaSSasha Levin 
6233c29e2aaSSasha Levin 	if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0)
6243c29e2aaSSasha Levin 		die("Failed writing sandbox script");
6253c29e2aaSSasha Levin 
6265cd19aa0SPekka Enberg 	resolve_program(argv[0], program, PATH_MAX);
6275cd19aa0SPekka Enberg 	kvm_write_sandbox_cmd_exactly(fd, program);
6285cd19aa0SPekka Enberg 
6295cd19aa0SPekka Enberg 	argv++;
6305cd19aa0SPekka Enberg 	argc--;
6315cd19aa0SPekka Enberg 
6323c29e2aaSSasha Levin 	while (argc) {
6333c29e2aaSSasha Levin 		if (write(fd, " ", 1) <= 0)
6343c29e2aaSSasha Levin 			die("Failed writing sandbox script");
6355cd19aa0SPekka Enberg 
6365cd19aa0SPekka Enberg 		kvm_write_sandbox_cmd_exactly(fd, argv[0]);
6373c29e2aaSSasha Levin 		argv++;
6383c29e2aaSSasha Levin 		argc--;
6393c29e2aaSSasha Levin 	}
6403c29e2aaSSasha Levin 	if (write(fd, "\n", 1) <= 0)
6413c29e2aaSSasha Levin 		die("Failed writing sandbox script");
6423c29e2aaSSasha Levin 
6433c29e2aaSSasha Levin 	close(fd);
6443c29e2aaSSasha Levin }
6453c29e2aaSSasha Levin 
646e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv)
647f967c427SPrasad Joshi {
6482d96f6b6SSasha Levin 	static char real_cmdline[2048], default_name[20];
649aba1efa5SPekka Enberg 	struct framebuffer *fb = NULL;
650384922b3SPekka Enberg 	unsigned int nr_online_cpus;
651*5f225124SSasha Levin 	int r;
65247621338SSasha Levin 
65347621338SSasha Levin 	kvm = kvm__new();
65447621338SSasha Levin 	if (IS_ERR(kvm))
65547621338SSasha Levin 		return PTR_ERR(kvm);
656f967c427SPrasad Joshi 
6575ee154d1SPekka Enberg 	signal(SIGALRM, handle_sigalrm);
6584b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
65943119af7SPekka Enberg 	signal(SIGUSR1, handle_sigusr1);
6604b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
6614b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
6624b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
6637021c50bSAsias He 	kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
664f967c427SPrasad Joshi 
665cfd63bbbSSasha Levin 	nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
66647621338SSasha Levin 	kvm->cfg.custom_rootfs_name = "default";
667cfd63bbbSSasha Levin 
668f967c427SPrasad Joshi 	while (argc != 0) {
6693b55dcdeSSasha Levin 		BUILD_OPTIONS(options, &kvm->cfg, kvm);
670f967c427SPrasad Joshi 		argc = parse_options(argc, argv, options, run_usage,
6711a007c82SSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION |
6721a007c82SSasha Levin 				PARSE_OPT_KEEP_DASHDASH);
673f967c427SPrasad Joshi 		if (argc != 0) {
6741a007c82SSasha Levin 			/* Cusrom options, should have been handled elsewhere */
6753c29e2aaSSasha Levin 			if (strcmp(argv[0], "--") == 0) {
6763c29e2aaSSasha Levin 				if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
67747621338SSasha Levin 					kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
6783c29e2aaSSasha Levin 					kvm_run_write_sandbox_cmd(argv+1, argc-1);
6791a007c82SSasha Levin 					break;
6803c29e2aaSSasha Levin 				}
6813c29e2aaSSasha Levin 			}
6821a007c82SSasha Levin 
68347621338SSasha Levin 			if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) ||
68447621338SSasha Levin 				(kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) {
685f967c427SPrasad Joshi 				fprintf(stderr, "Cannot handle parameter: "
686f967c427SPrasad Joshi 						"%s\n", argv[0]);
687f967c427SPrasad Joshi 				usage_with_options(run_usage, options);
68847621338SSasha Levin 				free(kvm);
689e120b624SPaul Neumann 				return -EINVAL;
690f967c427SPrasad Joshi 			}
691e0747665SSasha Levin 			if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
692e0747665SSasha Levin 				/*
693e0747665SSasha Levin 				 * first unhandled parameter is treated as
694e0747665SSasha Levin 				 * sandbox command
695e0747665SSasha Levin 				 */
69647621338SSasha Levin 				kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
697e0747665SSasha Levin 				kvm_run_write_sandbox_cmd(argv, argc);
698e0747665SSasha Levin 			} else {
699e0747665SSasha Levin 				/*
700e0747665SSasha Levin 				 * first unhandled parameter is treated as a kernel
701e0747665SSasha Levin 				 * image
702f967c427SPrasad Joshi 				 */
70347621338SSasha Levin 				kvm->cfg.kernel_filename = argv[0];
704e0747665SSasha Levin 			}
705f967c427SPrasad Joshi 			argv++;
706f967c427SPrasad Joshi 			argc--;
707f967c427SPrasad Joshi 		}
708f967c427SPrasad Joshi 
709f967c427SPrasad Joshi 	}
710f967c427SPrasad Joshi 
7113b55dcdeSSasha Levin 	kvm->nr_disks = kvm->cfg.image_count;
7123b55dcdeSSasha Levin 
71347621338SSasha Levin 	if (!kvm->cfg.kernel_filename)
71447621338SSasha Levin 		kvm->cfg.kernel_filename = find_kernel();
7158329f30bSPekka Enberg 
71647621338SSasha Levin 	if (!kvm->cfg.kernel_filename) {
717e08c0896SPrasad Joshi 		kernel_usage_with_options();
718e120b624SPaul Neumann 		return -EINVAL;
7198329f30bSPekka Enberg 	}
7208329f30bSPekka Enberg 
72147621338SSasha Levin 	kvm->cfg.vmlinux_filename = find_vmlinux();
722b0b42ba0SPekka Enberg 
72300ebbe96SSasha Levin 	if (kvm->cfg.nrcpus == 0)
72400ebbe96SSasha Levin 		kvm->cfg.nrcpus = nr_online_cpus;
725d77a9efaSCyrill Gorcunov 
72647621338SSasha Levin 	if (!kvm->cfg.ram_size)
72700ebbe96SSasha Levin 		kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus);
728fd834defSPekka Enberg 
72947621338SSasha Levin 	if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB)
73047621338SSasha Levin 		die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB);
731a2a002f9SIngo Molnar 
73247621338SSasha Levin 	if (kvm->cfg.ram_size > host_ram_size())
73347621338SSasha Levin 		pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size());
73460ded003SPekka Enberg 
73547621338SSasha Levin 	kvm->cfg.ram_size <<= MB_SHIFT;
736f967c427SPrasad Joshi 
73747621338SSasha Levin 	if (!kvm->cfg.dev)
73847621338SSasha Levin 		kvm->cfg.dev = DEFAULT_KVM_DEV;
739f967c427SPrasad Joshi 
74047621338SSasha Levin 	if (!kvm->cfg.console)
74147621338SSasha Levin 		kvm->cfg.console = DEFAULT_CONSOLE;
7429aa4a0ebSAsias He 
74347621338SSasha Levin 	if (!strncmp(kvm->cfg.console, "virtio", 6))
7442651ea58SSasha Levin 		kvm->cfg.active_console  = CONSOLE_VIRTIO;
74547621338SSasha Levin 	else if (!strncmp(kvm->cfg.console, "serial", 6))
7462651ea58SSasha Levin 		kvm->cfg.active_console  = CONSOLE_8250;
74747621338SSasha Levin 	else if (!strncmp(kvm->cfg.console, "hv", 2))
7482651ea58SSasha Levin 		kvm->cfg.active_console = CONSOLE_HV;
7493bbc49b6SMatt Evans 	else
7503bbc49b6SMatt Evans 		pr_warning("No console!");
751f967c427SPrasad Joshi 
75247621338SSasha Levin 	if (!kvm->cfg.host_ip)
75347621338SSasha Levin 		kvm->cfg.host_ip = DEFAULT_HOST_ADDR;
7544d67c820SSasha Levin 
75547621338SSasha Levin 	if (!kvm->cfg.guest_ip)
75647621338SSasha Levin 		kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR;
757bb8ffd2fSAsias He 
75847621338SSasha Levin 	if (!kvm->cfg.guest_mac)
75947621338SSasha Levin 		kvm->cfg.guest_mac = DEFAULT_GUEST_MAC;
760a4e724ddSSasha Levin 
76147621338SSasha Levin 	if (!kvm->cfg.host_mac)
76247621338SSasha Levin 		kvm->cfg.host_mac = DEFAULT_HOST_MAC;
763d7098b9bSAsias He 
76447621338SSasha Levin 	if (!kvm->cfg.script)
76547621338SSasha Levin 		kvm->cfg.script = DEFAULT_SCRIPT;
76673b7d038SAmos Kong 
767dca745e4SSasha Levin 	r = term_init(kvm);
768dca745e4SSasha Levin 	if (r < 0) {
769dca745e4SSasha Levin 		pr_err("term_init() failed with error %d\n", r);
770dca745e4SSasha Levin 		goto fail;
771dca745e4SSasha Levin 	}
772f967c427SPrasad Joshi 
77347621338SSasha Levin 	if (!kvm->cfg.guest_name) {
77447621338SSasha Levin 		if (kvm->cfg.custom_rootfs) {
77547621338SSasha Levin 			kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name;
776587a4d17SLai Jiangshan 		} else {
7772d96f6b6SSasha Levin 			sprintf(default_name, "guest-%u", getpid());
77847621338SSasha Levin 			kvm->cfg.guest_name = default_name;
7792d96f6b6SSasha Levin 		}
780587a4d17SLai Jiangshan 	}
7812d96f6b6SSasha Levin 
78247621338SSasha Levin 	r = kvm__init(kvm);
78347621338SSasha Levin 	if (r)
784d648dbf5SCyrill Gorcunov 		goto fail;
785f967c427SPrasad Joshi 
786ea6eeb1cSSasha Levin 	r = ioeventfd__init(kvm);
787ea6eeb1cSSasha Levin 	if (r < 0) {
788ea6eeb1cSSasha Levin 		pr_err("ioeventfd__init() failed with error %d\n", r);
789ea6eeb1cSSasha Levin 		goto fail;
790ea6eeb1cSSasha Levin 	}
79137f3d50eSSasha Levin 
792df4239fbSSasha Levin 	r = kvm_cpu__init(kvm);
793df4239fbSSasha Levin 	if (r < 0) {
794df4239fbSSasha Levin 		pr_err("kvm_cpu__init() failed with error %d\n", r);
795df4239fbSSasha Levin 		goto fail;
796384922b3SPekka Enberg 	}
797384922b3SPekka Enberg 
798e3c4f8aaSSasha Levin 	r = irq__init(kvm);
799e3c4f8aaSSasha Levin 	if (r < 0) {
800e3c4f8aaSSasha Levin 		pr_err("irq__init() failed with error %d\n", r);
801e3c4f8aaSSasha Levin 		goto fail;
802e3c4f8aaSSasha Levin 	}
80319e6c8b8SMatt Evans 
8046d987703SSasha Levin 	r = pci__init(kvm);
8056d987703SSasha Levin 	if (r < 0) {
8066d987703SSasha Levin 		pr_err("pci__init() failed with error %d\n", r);
8076d987703SSasha Levin 		goto fail;
8086d987703SSasha Levin 	}
809b91be965SMatt Evans 
8107af40b91SSasha Levin 	r = ioport__init(kvm);
8117af40b91SSasha Levin 	if (r < 0) {
8127af40b91SSasha Levin 		pr_err("ioport__init() failed with error %d\n", r);
8137af40b91SSasha Levin 		goto fail;
8147af40b91SSasha Levin 	}
8157af40b91SSasha Levin 
816890364f8SCyrill Gorcunov 	/*
817890364f8SCyrill Gorcunov 	 * vidmode should be either specified
818890364f8SCyrill Gorcunov 	 * either set by default
819890364f8SCyrill Gorcunov 	 */
82047621338SSasha Levin 	if (kvm->cfg.vnc || kvm->cfg.sdl) {
821890364f8SCyrill Gorcunov 		if (vidmode == -1)
822890364f8SCyrill Gorcunov 			vidmode = 0x312;
82348d9e01aSSasha Levin 	} else {
824890364f8SCyrill Gorcunov 		vidmode = 0;
82548d9e01aSSasha Levin 	}
826890364f8SCyrill Gorcunov 
82726c853e4SPrasad Joshi 	memset(real_cmdline, 0, sizeof(real_cmdline));
82847621338SSasha Levin 	kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl);
8298e704a7aSMatt Evans 
8308e704a7aSMatt Evans 	if (strlen(real_cmdline) > 0)
831d74181ccSSasha Levin 		strcat(real_cmdline, " ");
8328e704a7aSMatt Evans 
83347621338SSasha Levin 	if (kvm->cfg.kernel_cmdline)
83447621338SSasha Levin 		strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline));
83526c853e4SPrasad Joshi 
83647621338SSasha Levin 	if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) {
837c8675741SSasha Levin 		char tmp[PATH_MAX];
8386df1471eSPekka Enberg 
83947621338SSasha Levin 		kvm_setup_create_new(kvm->cfg.custom_rootfs_name);
84047621338SSasha Levin 		kvm_setup_resolv(kvm->cfg.custom_rootfs_name);
841c8675741SSasha Levin 
8429667701cSPekka Enberg 		snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default");
843c8675741SSasha Levin 		if (virtio_9p__register(kvm, tmp, "/dev/root") < 0)
844c8675741SSasha Levin 			die("Unable to initialize virtio 9p");
845c8675741SSasha Levin 		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
846c8675741SSasha Levin 			die("Unable to initialize virtio 9p");
84747621338SSasha Levin 		kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1;
84826c853e4SPrasad Joshi 	}
84926c853e4SPrasad Joshi 
85047621338SSasha Levin 	if (kvm->cfg.using_rootfs) {
851ff42603fSSasha Levin 		strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p");
85247621338SSasha Levin 		if (kvm->cfg.custom_rootfs) {
853d50fe489SSasha Levin 			kvm_run_set_sandbox();
854d50fe489SSasha Levin 
855a8e6b4b9SSasha Levin 			strcat(real_cmdline, " init=/virt/init");
856d50fe489SSasha Levin 
85747621338SSasha Levin 			if (!kvm->cfg.no_dhcp)
858a8e6b4b9SSasha Levin 				strcat(real_cmdline, "  ip=dhcp");
859afc2c7c0SAsias He 			if (kvm_setup_guest_init())
860afc2c7c0SAsias He 				die("Failed to setup init for guest.");
861a8e6b4b9SSasha Levin 		}
86282d65b5eSSasha Levin 	} else if (!strstr(real_cmdline, "root=")) {
863ff42603fSSasha Levin 		strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline));
86482d65b5eSSasha Levin 	}
86559aa2d30SSasha Levin 
8663b55dcdeSSasha Levin 	r = disk_image__init(kvm);
8673b55dcdeSSasha Levin 	if (r < 0) {
8683b55dcdeSSasha Levin 		pr_err("disk_image__init() failed with error %d\n", r);
8699f9207c5SSasha Levin 		goto fail;
8709f9207c5SSasha Levin 	}
871c1ed214eSPrasad Joshi 
872ee8b1456SWanlong Gao 	printf("  # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
87300ebbe96SSasha Levin 		kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name);
874471c6facSPekka Enberg 
87547621338SSasha Levin 	if (!kvm->cfg.firmware_filename) {
87647621338SSasha Levin 		if (!kvm__load_kernel(kvm, kvm->cfg.kernel_filename,
87747621338SSasha Levin 				kvm->cfg.initrd_filename, real_cmdline, vidmode))
87847621338SSasha Levin 			die("unable to load kernel %s", kvm->cfg.kernel_filename);
879f967c427SPrasad Joshi 
88047621338SSasha Levin 		kvm->vmlinux = kvm->cfg.vmlinux_filename;
881807b77b9SCyrill Gorcunov 		r = symbol_init(kvm);
882b56f1728SCyrill Gorcunov 		if (r < 0)
883c4b716ecSPekka Enberg 			pr_debug("symbol_init() failed with error %d\n", r);
8845ad8db5eSPekka Enberg 	}
885b0b42ba0SPekka Enberg 
886af7b0868SMatt Evans 	ioport__setup_arch();
887ac38f433SPekka Enberg 
88820c39545SSasha Levin 	r = rtc__init(kvm);
88920c39545SSasha Levin 	if (r < 0) {
89020c39545SSasha Levin 		pr_err("rtc__init() failed with error %d\n", r);
89120c39545SSasha Levin 		goto fail;
89220c39545SSasha Levin 	}
89364136c1cSPekka Enberg 
89420715a22SSasha Levin 	r = serial8250__init(kvm);
89520715a22SSasha Levin 	if (r < 0) {
89620715a22SSasha Levin 		pr_err("serial__init() failed with error %d\n", r);
89720715a22SSasha Levin 		goto fail;
89820715a22SSasha Levin 	}
899f967c427SPrasad Joshi 
9009f9207c5SSasha Levin 	r = virtio_blk__init(kvm);
9019f9207c5SSasha Levin 	if (r < 0) {
9029f9207c5SSasha Levin 		pr_err("virtio_blk__init() failed with error %d\n", r);
9039f9207c5SSasha Levin 		goto fail;
9049f9207c5SSasha Levin 	}
9059f9207c5SSasha Levin 
906a67da3beSAsias He 	r = virtio_scsi_init(kvm);
907a67da3beSAsias He 	if (r < 0) {
908a67da3beSAsias He 		pr_err("virtio_scsi_init() failed with error %d\n", r);
909a67da3beSAsias He 		goto fail;
910a67da3beSAsias He 	}
911a67da3beSAsias He 
912a3fa3f86SSasha Levin 	r = virtio_console__init(kvm);
913a3fa3f86SSasha Levin 	if (r < 0) {
914a3fa3f86SSasha Levin 		pr_err("virtio_console__init() failed with error %d\n", r);
915a3fa3f86SSasha Levin 		goto fail;
916a3fa3f86SSasha Levin 	}
917f967c427SPrasad Joshi 
918f16653adSSasha Levin 	r = virtio_rng__init(kvm);
919f16653adSSasha Levin 	if (r < 0) {
920f16653adSSasha Levin 		pr_err("virtio_rng__init() failed with error %d\n", r);
921f16653adSSasha Levin 		goto fail;
922f16653adSSasha Levin 	}
92353eca082SSasha Levin 
924d06db2fdSSasha Levin 	r = virtio_bln__init(kvm);
925d06db2fdSSasha Levin 	if (r < 0) {
926d06db2fdSSasha Levin 		pr_err("virtio_rng__init() failed with error %d\n", r);
927d06db2fdSSasha Levin 		goto fail;
928d06db2fdSSasha Levin 	}
92982d2f21eSSasha Levin 
93047621338SSasha Levin 	if (!kvm->cfg.network)
93147621338SSasha Levin 		kvm->cfg.network = DEFAULT_NETWORK;
9324f56d42cSAsias He 
933c7838fbdSSasha Levin 	virtio_9p__init(kvm);
934c7838fbdSSasha Levin 
935*5f225124SSasha Levin 	r = virtio_net__init(kvm);
936*5f225124SSasha Levin 	if (r < 0) {
937*5f225124SSasha Levin 		pr_err("virtio_net__init() failed with error %d\n", r);
938*5f225124SSasha Levin 		goto fail;
939bdfcfca6SSasha Levin 	}
9404f56d42cSAsias He 
941839051d9SSasha Levin 	kvm__init_ram(kvm);
942839051d9SSasha Levin 
94357d7832bSMatt Evans #ifdef CONFIG_X86
944714e5b7fSSasha Levin 	kbd__init(kvm);
94557d7832bSMatt Evans #endif
946714e5b7fSSasha Levin 
9478cec93dbSSasha Levin 	r = pci_shmem__init(kvm);
9488cec93dbSSasha Levin 	if (r < 0) {
9498cec93dbSSasha Levin 		pr_err("pci_shmem__init() failed with error %d\n", r);
9508cec93dbSSasha Levin 		goto fail;
9518cec93dbSSasha Levin 	}
95295d13a52SSasha Levin 
95347621338SSasha Levin 	if (kvm->cfg.vnc || kvm->cfg.sdl) {
9543f838fecSPekka Enberg 		fb = vesa__init(kvm);
95548d9e01aSSasha Levin 		if (IS_ERR(fb)) {
95648d9e01aSSasha Levin 			pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
95748d9e01aSSasha Levin 			goto fail;
95848d9e01aSSasha Levin 		}
9593f838fecSPekka Enberg 	}
9603f838fecSPekka Enberg 
96147621338SSasha Levin 	if (kvm->cfg.vnc && fb) {
96248d9e01aSSasha Levin 		r = vnc__init(fb);
96348d9e01aSSasha Levin 		if (r < 0) {
96448d9e01aSSasha Levin 			pr_err("vnc__init() failed with error %d\n", r);
96548d9e01aSSasha Levin 			goto fail;
96648d9e01aSSasha Levin 		}
96748d9e01aSSasha Levin 	}
96848d9e01aSSasha Levin 
96947621338SSasha Levin 	if (kvm->cfg.sdl && fb) {
9703f838fecSPekka Enberg 		sdl__init(fb);
97148d9e01aSSasha Levin 		if (r < 0) {
97248d9e01aSSasha Levin 			pr_err("sdl__init() failed with error %d\n", r);
97348d9e01aSSasha Levin 			goto fail;
97448d9e01aSSasha Levin 		}
9753f838fecSPekka Enberg 	}
976aba1efa5SPekka Enberg 
977ba46fe53SSasha Levin 	r = fb__init(kvm);
97848d9e01aSSasha Levin 	if (r < 0) {
97948d9e01aSSasha Levin 		pr_err("fb__init() failed with error %d\n", r);
98048d9e01aSSasha Levin 		goto fail;
98148d9e01aSSasha Levin 	}
982aba1efa5SPekka Enberg 
983df4239fbSSasha Levin 	/*
984df4239fbSSasha Levin 	 * Device init all done; firmware init must
98525af47eeSMatt Evans 	 * come after this (it may set up device trees etc.)
98625af47eeSMatt Evans 	 */
98725af47eeSMatt Evans 
988b4532ca9SSasha Levin 	r = kvm_timer__init(kvm);
989b4532ca9SSasha Levin 	if (r < 0) {
990b4532ca9SSasha Levin 		pr_err("kvm_timer__init() failed with error %d\n", r);
991b4532ca9SSasha Levin 		goto fail;
992b4532ca9SSasha Levin 	}
99325af47eeSMatt Evans 
99447621338SSasha Levin 	if (kvm->cfg.firmware_filename) {
99547621338SSasha Levin 		if (!kvm__load_firmware(kvm, kvm->cfg.firmware_filename))
99647621338SSasha Levin 			die("unable to load firmware image %s: %s", kvm->cfg.firmware_filename, strerror(errno));
9975ad8db5eSPekka Enberg 	} else {
998e1e46fe6SSasha Levin 		kvm__arch_setup_firmware(kvm);
9991add9f73SSasha Levin 		if (r < 0) {
10001add9f73SSasha Levin 			pr_err("kvm__arch_setup_firmware() failed with error %d\n", r);
10011add9f73SSasha Levin 			goto fail;
10021add9f73SSasha Levin 		}
10035ad8db5eSPekka Enberg 	}
100425af47eeSMatt Evans 
1005f6a3c571SSasha Levin 	r = thread_pool__init(kvm);
1006f6a3c571SSasha Levin 	if (r < 0) {
1007f6a3c571SSasha Levin 		pr_err("thread_pool__init() failed with error %d\n", r);
1008f6a3c571SSasha Levin 		goto fail;
1009f6a3c571SSasha Levin 	}
1010f6a3c571SSasha Levin 
10114932d174SSasha Levin fail:
10124932d174SSasha Levin 	return r;
1013e1e46fe6SSasha Levin }
1014e1e46fe6SSasha Levin 
1015e1e46fe6SSasha Levin static int kvm_cmd_run_work(void)
1016e1e46fe6SSasha Levin {
1017df4239fbSSasha Levin 	int i;
1018e1e46fe6SSasha Levin 	void *ret = NULL;
1019e1e46fe6SSasha Levin 
102000ebbe96SSasha Levin 	for (i = 0; i < kvm->nrcpus; i++) {
1021df4239fbSSasha Levin 		if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0)
10225ee154d1SPekka Enberg 			die("unable to create KVM VCPU thread");
10235ee154d1SPekka Enberg 	}
10245ee154d1SPekka Enberg 
102549e5227dSSasha Levin 	/* Only VCPU #0 is going to exit by itself when shutting down */
1026df4239fbSSasha Levin 	return pthread_join(kvm->cpus[0]->thread, &ret);
1027e1e46fe6SSasha Levin }
1028e1e46fe6SSasha Levin 
10294932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret)
1030e1e46fe6SSasha Levin {
10314932d174SSasha Levin 	int r = 0;
10324932d174SSasha Levin 
1033e6694207SSasha Levin 	compat__print_all_messages();
1034e6694207SSasha Levin 
1035df4239fbSSasha Levin 	r = kvm_cpu__exit(kvm);
1036df4239fbSSasha Levin 	if (r < 0)
1037df4239fbSSasha Levin 		pr_warning("kvm_cpu__exit() failed with error %d\n", r);
1038df4239fbSSasha Levin 
1039807b77b9SCyrill Gorcunov 	r = symbol_exit(kvm);
10404932d174SSasha Levin 	if (r < 0)
1041807b77b9SCyrill Gorcunov 		pr_warning("symbol_exit() failed with error %d\n", r);
10424932d174SSasha Levin 
1043e3c4f8aaSSasha Levin 	r = irq__exit(kvm);
1044e3c4f8aaSSasha Levin 	if (r < 0)
1045e3c4f8aaSSasha Levin 		pr_warning("irq__exit() failed with error %d\n", r);
1046e3c4f8aaSSasha Levin 
1047b4532ca9SSasha Levin 	r = kvm_timer__exit(kvm);
1048b4532ca9SSasha Levin 	if (r < 0)
1049b4532ca9SSasha Levin 		pr_warning("kvm_timer__exit() failed with error %d\n", r);
1050b4532ca9SSasha Levin 
1051ba46fe53SSasha Levin 	r = fb__exit(kvm);
1052ba46fe53SSasha Levin 	if (r < 0)
1053b4532ca9SSasha Levin 		pr_warning("kvm_timer__exit() failed with error %d\n", r);
1054aba1efa5SPekka Enberg 
1055*5f225124SSasha Levin 	r = virtio_net__exit(kvm);
1056*5f225124SSasha Levin 	if (r < 0)
1057*5f225124SSasha Levin 		pr_warning("virtio_net__exit() failed with error %d\n", r);
1058*5f225124SSasha Levin 
1059a67da3beSAsias He 	r = virtio_scsi_exit(kvm);
1060a67da3beSAsias He 	if (r < 0)
1061a67da3beSAsias He 		pr_warning("virtio_scsi_exit() failed with error %d\n", r);
1062a67da3beSAsias He 
10639f9207c5SSasha Levin 	r = virtio_blk__exit(kvm);
10649f9207c5SSasha Levin 	if (r < 0)
10659f9207c5SSasha Levin 		pr_warning("virtio_blk__exit() failed with error %d\n", r);
10669f9207c5SSasha Levin 
1067495fbd4eSSasha Levin 	r = virtio_rng__exit(kvm);
1068495fbd4eSSasha Levin 	if (r < 0)
1069495fbd4eSSasha Levin 		pr_warning("virtio_rng__exit() failed with error %d\n", r);
1070a0a1e3c2SPrasad Joshi 
1071d06db2fdSSasha Levin 	r = virtio_bln__exit(kvm);
1072d06db2fdSSasha Levin 	if (r < 0)
1073d06db2fdSSasha Levin 		pr_warning("virtio_bln__exit() failed with error %d\n", r);
1074d06db2fdSSasha Levin 
1075a3fa3f86SSasha Levin 	r = virtio_console__exit(kvm);
1076a3fa3f86SSasha Levin 	if (r < 0)
1077a3fa3f86SSasha Levin 		pr_warning("virtio_console__exit() failed with error %d\n", r);
1078a3fa3f86SSasha Levin 
10798cec93dbSSasha Levin 	r = pci_shmem__exit(kvm);
10808cec93dbSSasha Levin 	if (r < 0)
10818cec93dbSSasha Levin 		pr_warning("pci_shmem__exit() failed with error %d\n", r);
10828cec93dbSSasha Levin 
10833b55dcdeSSasha Levin 	r = disk_image__exit(kvm);
10849f9207c5SSasha Levin 	if (r < 0)
10853b55dcdeSSasha Levin 		pr_warning("disk_image__exit() failed with error %d\n", r);
10867af40b91SSasha Levin 
108720715a22SSasha Levin 	r = serial8250__exit(kvm);
108820715a22SSasha Levin 	if (r < 0)
108920715a22SSasha Levin 		pr_warning("serial8250__exit() failed with error %d\n", r);
109020715a22SSasha Levin 
109120c39545SSasha Levin 	r = rtc__exit(kvm);
109220c39545SSasha Levin 	if (r < 0)
109320c39545SSasha Levin 		pr_warning("rtc__exit() failed with error %d\n", r);
109420c39545SSasha Levin 
10951add9f73SSasha Levin 	r = kvm__arch_free_firmware(kvm);
10961add9f73SSasha Levin 	if (r < 0)
10971add9f73SSasha Levin 		pr_warning("kvm__arch_free_firmware() failed with error %d\n", r);
10981add9f73SSasha Levin 
10997af40b91SSasha Levin 	r = ioport__exit(kvm);
11007af40b91SSasha Levin 	if (r < 0)
11017af40b91SSasha Levin 		pr_warning("ioport__exit() failed with error %d\n", r);
11027af40b91SSasha Levin 
1103ea6eeb1cSSasha Levin 	r = ioeventfd__exit(kvm);
1104ea6eeb1cSSasha Levin 	if (r < 0)
1105ea6eeb1cSSasha Levin 		pr_warning("ioeventfd__exit() failed with error %d\n", r);
1106ea6eeb1cSSasha Levin 
11076d987703SSasha Levin 	r = pci__exit(kvm);
11086d987703SSasha Levin 	if (r < 0)
11096d987703SSasha Levin 		pr_warning("pci__exit() failed with error %d\n", r);
11106d987703SSasha Levin 
1111dca745e4SSasha Levin 	r = term_exit(kvm);
1112dca745e4SSasha Levin 	if (r < 0)
1113dca745e4SSasha Levin 		pr_warning("pci__exit() failed with error %d\n", r);
1114dca745e4SSasha Levin 
1115f6a3c571SSasha Levin 	r = thread_pool__exit(kvm);
1116f6a3c571SSasha Levin 	if (r < 0)
1117f6a3c571SSasha Levin 		pr_warning("thread_pool__exit() failed with error %d\n", r);
1118f6a3c571SSasha Levin 
1119495fbd4eSSasha Levin 	r = kvm__exit(kvm);
1120495fbd4eSSasha Levin 	if (r < 0)
1121495fbd4eSSasha Levin 		pr_warning("pci__exit() failed with error %d\n", r);
1122f967c427SPrasad Joshi 
1123e1e46fe6SSasha Levin 	if (guest_ret == 0)
1124f967c427SPrasad Joshi 		printf("\n  # KVM session ended normally.\n");
1125e1e46fe6SSasha Levin }
1126e1e46fe6SSasha Levin 
1127e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix)
1128e1e46fe6SSasha Levin {
11294932d174SSasha Levin 	int r, ret = -EFAULT;
1130e1e46fe6SSasha Levin 
1131e1e46fe6SSasha Levin 	r = kvm_cmd_run_init(argc, argv);
1132e1e46fe6SSasha Levin 	if (r < 0)
1133e1e46fe6SSasha Levin 		return r;
1134e1e46fe6SSasha Levin 
1135e1e46fe6SSasha Levin 	ret = kvm_cmd_run_work();
1136e1e46fe6SSasha Levin 	kvm_cmd_run_exit(ret);
1137e1e46fe6SSasha Levin 
1138e1e46fe6SSasha Levin 	return ret;
1139f967c427SPrasad Joshi }
1140