xref: /kvmtool/builtin-run.c (revision b816364a4a22603a13b8a34d63542eb0765103a1)
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 DEFAULT_KVM_DEV		"/dev/kvm"
539aa4a0ebSAsias He #define DEFAULT_CONSOLE		"serial"
54bd30e200SAsias He #define DEFAULT_NETWORK		"user"
55745c7231SAsias He #define DEFAULT_HOST_ADDR	"192.168.33.1"
56bb8ffd2fSAsias He #define DEFAULT_GUEST_ADDR	"192.168.33.15"
577c88c87eSSasha Levin #define DEFAULT_GUEST_MAC	"02:15:15:15:15:15"
587c88c87eSSasha Levin #define DEFAULT_HOST_MAC	"02:01:01:01:01:01"
5973b7d038SAmos Kong #define DEFAULT_SCRIPT		"none"
603c29e2aaSSasha Levin const char *DEFAULT_SANDBOX_FILENAME = "guest/sandbox.sh";
61f967c427SPrasad Joshi 
62f967c427SPrasad Joshi #define MB_SHIFT		(20)
6395d13a52SSasha Levin #define KB_SHIFT		(10)
6495d13a52SSasha Levin #define GB_SHIFT		(30)
65a2a002f9SIngo Molnar #define MIN_RAM_SIZE_MB		(64ULL)
66f967c427SPrasad Joshi #define MIN_RAM_SIZE_BYTE	(MIN_RAM_SIZE_MB << MB_SHIFT)
67f967c427SPrasad Joshi 
684298ddadSSasha Levin struct kvm *kvm;
69e2077857SMatt Evans struct kvm_cpu **kvm_cpus;
70656be1b8SSasha Levin __thread struct kvm_cpu *current_kvm_cpu;
71f967c427SPrasad Joshi 
72b54cb31cSSasha Levin struct kvm_config {
73b54cb31cSSasha Levin 	struct disk_image_params disk_image[MAX_DISK_IMAGES];
74b54cb31cSSasha Levin 	u64 ram_size;
75b54cb31cSSasha Levin 	u8  image_count;
76b54cb31cSSasha Levin 	u8 num_net_devices;
77b54cb31cSSasha Levin 	bool virtio_rng;
78b54cb31cSSasha Levin 	const char *kernel_cmdline;
79b54cb31cSSasha Levin 	const char *kernel_filename;
80b54cb31cSSasha Levin 	const char *vmlinux_filename;
81b54cb31cSSasha Levin 	const char *initrd_filename;
82b54cb31cSSasha Levin 	const char *firmware_filename;
83b54cb31cSSasha Levin 	const char *console;
84b54cb31cSSasha Levin 	const char *dev;
85b54cb31cSSasha Levin 	const char *network;
86b54cb31cSSasha Levin 	const char *host_ip;
87b54cb31cSSasha Levin 	const char *guest_ip;
88b54cb31cSSasha Levin 	const char *guest_mac;
89b54cb31cSSasha Levin 	const char *host_mac;
90b54cb31cSSasha Levin 	const char *script;
91b54cb31cSSasha Levin 	const char *guest_name;
92b54cb31cSSasha Levin 	const char *sandbox;
93b54cb31cSSasha Levin 	const char *hugetlbfs_path;
94b54cb31cSSasha Levin 	const char *custom_rootfs_name;
95b54cb31cSSasha Levin 	struct virtio_net_params *net_params;
96b54cb31cSSasha Levin 	bool single_step;
97b54cb31cSSasha Levin 	bool vnc;
98b54cb31cSSasha Levin 	bool sdl;
99b54cb31cSSasha Levin 	bool balloon;
100b54cb31cSSasha Levin 	bool using_rootfs;
101b54cb31cSSasha Levin 	bool custom_rootfs;
102b54cb31cSSasha Levin 	bool no_net;
103b54cb31cSSasha Levin 	bool no_dhcp;
104b54cb31cSSasha Levin } cfg;
105b54cb31cSSasha Levin 
106f967c427SPrasad Joshi extern bool ioport_debug;
107d562e086SCyrill Gorcunov extern bool mmio_debug;
1083c29e2aaSSasha Levin static int  kvm_run_wrapper;
109f967c427SPrasad Joshi extern int  active_console;
110aa400b00SPrasad Joshi extern int  debug_iodelay;
111f967c427SPrasad Joshi 
112ed036f03SCyrill Gorcunov bool do_debug_print = false;
113ed036f03SCyrill Gorcunov 
114cfd63bbbSSasha Levin static int nrcpus;
115890364f8SCyrill Gorcunov static int vidmode = -1;
116d77a9efaSCyrill Gorcunov 
117afc2c7c0SAsias He extern char _binary_guest_init_start;
118afc2c7c0SAsias He extern char _binary_guest_init_size;
119afc2c7c0SAsias He 
120f967c427SPrasad Joshi static const char * const run_usage[] = {
1218d2ff5daSWanlong Gao 	"lkvm run [<options>] [<kernel image>]",
122f967c427SPrasad Joshi 	NULL
123f967c427SPrasad Joshi };
124f967c427SPrasad Joshi 
1253c29e2aaSSasha Levin enum {
126e0747665SSasha Levin 	KVM_RUN_DEFAULT,
1273c29e2aaSSasha Levin 	KVM_RUN_SANDBOX,
1283c29e2aaSSasha Levin };
1293c29e2aaSSasha Levin 
1303c29e2aaSSasha Levin void kvm_run_set_wrapper_sandbox(void)
1313c29e2aaSSasha Levin {
1323c29e2aaSSasha Levin 	kvm_run_wrapper = KVM_RUN_SANDBOX;
1333c29e2aaSSasha Levin }
1343c29e2aaSSasha Levin 
135a33979d8SSasha Levin static int img_name_parser(const struct option *opt, const char *arg, int unset)
136a33979d8SSasha Levin {
13782d65b5eSSasha Levin 	char path[PATH_MAX];
1385236b505SAsias He 	const char *cur;
1395236b505SAsias He 	struct stat st;
1405236b505SAsias He 	char *sep;
14159aa2d30SSasha Levin 
14259aa2d30SSasha Levin 	if (stat(arg, &st) == 0 &&
14359aa2d30SSasha Levin 	    S_ISDIR(st.st_mode)) {
14459aa2d30SSasha Levin 		char tmp[PATH_MAX];
14559aa2d30SSasha Levin 
146b54cb31cSSasha Levin 		if (cfg.using_rootfs)
1472c908af9SLai Jiangshan 			die("Please use only one rootfs directory atmost");
1482c908af9SLai Jiangshan 
14959aa2d30SSasha Levin 		if (realpath(arg, tmp) == 0 ||
150c7838fbdSSasha Levin 		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
15159aa2d30SSasha Levin 			die("Unable to initialize virtio 9p");
152b54cb31cSSasha Levin 		cfg.using_rootfs = 1;
15359aa2d30SSasha Levin 		return 0;
15459aa2d30SSasha Levin 	}
155a33979d8SSasha Levin 
1569667701cSPekka Enberg 	snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
15782d65b5eSSasha Levin 
15882d65b5eSSasha Levin 	if (stat(path, &st) == 0 &&
15982d65b5eSSasha Levin 	    S_ISDIR(st.st_mode)) {
16082d65b5eSSasha Levin 		char tmp[PATH_MAX];
16182d65b5eSSasha Levin 
162b54cb31cSSasha Levin 		if (cfg.using_rootfs)
1632c908af9SLai Jiangshan 			die("Please use only one rootfs directory atmost");
1642c908af9SLai Jiangshan 
16582d65b5eSSasha Levin 		if (realpath(path, tmp) == 0 ||
16682d65b5eSSasha Levin 		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
16782d65b5eSSasha Levin 			die("Unable to initialize virtio 9p");
16882d65b5eSSasha Levin 		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
16982d65b5eSSasha Levin 			die("Unable to initialize virtio 9p");
17069c88b95SSasha Levin 		kvm_setup_resolv(arg);
171b54cb31cSSasha Levin 		cfg.using_rootfs = cfg.custom_rootfs = 1;
172b54cb31cSSasha Levin 		cfg.custom_rootfs_name = arg;
17382d65b5eSSasha Levin 		return 0;
17482d65b5eSSasha Levin 	}
17582d65b5eSSasha Levin 
176b54cb31cSSasha Levin 	if (cfg.image_count >= MAX_DISK_IMAGES)
177a33979d8SSasha Levin 		die("Currently only 4 images are supported");
178a33979d8SSasha Levin 
179b54cb31cSSasha Levin 	cfg.disk_image[cfg.image_count].filename = arg;
1805236b505SAsias He 	cur = arg;
181a67da3beSAsias He 
182a67da3beSAsias He 	if (strncmp(arg, "scsi:", 5) == 0) {
183a67da3beSAsias He 		sep = strstr(arg, ":");
184a67da3beSAsias He 		if (sep)
185b54cb31cSSasha Levin 			cfg.disk_image[cfg.image_count].wwpn = sep + 1;
186a67da3beSAsias He 		sep = strstr(sep + 1, ":");
187a67da3beSAsias He 		if (sep) {
188a67da3beSAsias He 			*sep = 0;
189b54cb31cSSasha Levin 			cfg.disk_image[cfg.image_count].tpgt = sep + 1;
190a67da3beSAsias He 		}
191a67da3beSAsias He 		cur = sep + 1;
192a67da3beSAsias He 	}
193a67da3beSAsias He 
1945236b505SAsias He 	do {
1955236b505SAsias He 		sep = strstr(cur, ",");
196a33979d8SSasha Levin 		if (sep) {
1975236b505SAsias He 			if (strncmp(sep + 1, "ro", 2) == 0)
198b54cb31cSSasha Levin 				cfg.disk_image[cfg.image_count].readonly = true;
1995236b505SAsias He 			else if (strncmp(sep + 1, "direct", 6) == 0)
200b54cb31cSSasha Levin 				cfg.disk_image[cfg.image_count].direct = true;
201a33979d8SSasha Levin 			*sep = 0;
2025236b505SAsias He 			cur = sep + 1;
203a33979d8SSasha Levin 		}
2045236b505SAsias He 	} while (sep);
205a33979d8SSasha Levin 
206b54cb31cSSasha Levin 	cfg.image_count++;
207a33979d8SSasha Levin 
208a33979d8SSasha Levin 	return 0;
209a33979d8SSasha Levin }
210a33979d8SSasha Levin 
211b4422bf3SAneesh Kumar K.V static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset)
212b4422bf3SAneesh Kumar K.V {
213b4422bf3SAneesh Kumar K.V 	char *tag_name;
214b4422bf3SAneesh Kumar K.V 	char tmp[PATH_MAX];
215b4422bf3SAneesh Kumar K.V 
216b4422bf3SAneesh Kumar K.V 	/*
217b4422bf3SAneesh Kumar K.V 	 * 9p dir can be of the form dirname,tag_name or
218b4422bf3SAneesh Kumar K.V 	 * just dirname. In the later case we use the
219b4422bf3SAneesh Kumar K.V 	 * default tag name
220b4422bf3SAneesh Kumar K.V 	 */
221b4422bf3SAneesh Kumar K.V 	tag_name = strstr(arg, ",");
222b4422bf3SAneesh Kumar K.V 	if (tag_name) {
223b4422bf3SAneesh Kumar K.V 		*tag_name = '\0';
224b4422bf3SAneesh Kumar K.V 		tag_name++;
225b4422bf3SAneesh Kumar K.V 	}
22654f6802dSPekka Enberg 	if (realpath(arg, tmp)) {
227c7838fbdSSasha Levin 		if (virtio_9p__register(kvm, tmp, tag_name) < 0)
22854f6802dSPekka Enberg 			die("Unable to initialize virtio 9p");
22954f6802dSPekka Enberg 	} else
230b4422bf3SAneesh Kumar K.V 		die("Failed resolving 9p path");
231b4422bf3SAneesh Kumar K.V 	return 0;
232b4422bf3SAneesh Kumar K.V }
233b4422bf3SAneesh Kumar K.V 
2341add4b76SSasha Levin static int tty_parser(const struct option *opt, const char *arg, int unset)
2351add4b76SSasha Levin {
2361add4b76SSasha Levin 	int tty = atoi(arg);
2371add4b76SSasha Levin 
2381add4b76SSasha Levin 	term_set_tty(tty);
2391add4b76SSasha Levin 
2401add4b76SSasha Levin 	return 0;
2411add4b76SSasha Levin }
2421add4b76SSasha Levin 
2439a6d73f1SSasha Levin static inline void str_to_mac(const char *str, char *mac)
2449a6d73f1SSasha Levin {
2459a6d73f1SSasha Levin 	sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
2469a6d73f1SSasha Levin 		mac, mac+1, mac+2, mac+3, mac+4, mac+5);
2479a6d73f1SSasha Levin }
2489a6d73f1SSasha Levin static int set_net_param(struct virtio_net_params *p, const char *param,
2499a6d73f1SSasha Levin 				const char *val)
2509a6d73f1SSasha Levin {
2519a6d73f1SSasha Levin 	if (strcmp(param, "guest_mac") == 0) {
2529a6d73f1SSasha Levin 		str_to_mac(val, p->guest_mac);
2539a6d73f1SSasha Levin 	} else if (strcmp(param, "mode") == 0) {
2549a6d73f1SSasha Levin 		if (!strncmp(val, "user", 4)) {
2559a6d73f1SSasha Levin 			int i;
2569a6d73f1SSasha Levin 
257b54cb31cSSasha Levin 			for (i = 0; i < cfg.num_net_devices; i++)
258b54cb31cSSasha Levin 				if (cfg.net_params[i].mode == NET_MODE_USER)
2599a6d73f1SSasha Levin 					die("Only one usermode network device allowed at a time");
2609a6d73f1SSasha Levin 			p->mode = NET_MODE_USER;
2619a6d73f1SSasha Levin 		} else if (!strncmp(val, "tap", 3)) {
2629a6d73f1SSasha Levin 			p->mode = NET_MODE_TAP;
2639a6d73f1SSasha Levin 		} else if (!strncmp(val, "none", 4)) {
264b54cb31cSSasha Levin 			cfg.no_net = 1;
2659a6d73f1SSasha Levin 			return -1;
2669a6d73f1SSasha Levin 		} else
267b54cb31cSSasha Levin 			die("Unknown network mode %s, please use user, tap or none", cfg.network);
2689a6d73f1SSasha Levin 	} else if (strcmp(param, "script") == 0) {
2699a6d73f1SSasha Levin 		p->script = strdup(val);
2709a6d73f1SSasha Levin 	} else if (strcmp(param, "guest_ip") == 0) {
2719a6d73f1SSasha Levin 		p->guest_ip = strdup(val);
2729a6d73f1SSasha Levin 	} else if (strcmp(param, "host_ip") == 0) {
2739a6d73f1SSasha Levin 		p->host_ip = strdup(val);
27469205aa1SAsias He 	} else if (strcmp(param, "trans") == 0) {
27569205aa1SAsias He 		p->trans = strdup(val);
2769ed67cdcSSasha Levin 	} else if (strcmp(param, "vhost") == 0) {
2779ed67cdcSSasha Levin 		p->vhost = atoi(val);
278f19edd1eSSasha Levin 	} else if (strcmp(param, "fd") == 0) {
279f19edd1eSSasha Levin 		p->fd = atoi(val);
28021aa628eSMichael Ellerman 	} else
28121aa628eSMichael Ellerman 		die("Unknown network parameter %s", param);
2829a6d73f1SSasha Levin 
2839a6d73f1SSasha Levin 	return 0;
2849a6d73f1SSasha Levin }
2859a6d73f1SSasha Levin 
2869a6d73f1SSasha Levin static int netdev_parser(const struct option *opt, const char *arg, int unset)
2879a6d73f1SSasha Levin {
2889a6d73f1SSasha Levin 	struct virtio_net_params p;
2899a6d73f1SSasha Levin 	char *buf = NULL, *cmd = NULL, *cur = NULL;
2909a6d73f1SSasha Levin 	bool on_cmd = true;
2919a6d73f1SSasha Levin 
2929a6d73f1SSasha Levin 	if (arg) {
2939a6d73f1SSasha Levin 		buf = strdup(arg);
2949a6d73f1SSasha Levin 		if (buf == NULL)
2959a6d73f1SSasha Levin 			die("Failed allocating new net buffer");
2969a6d73f1SSasha Levin 		cur = strtok(buf, ",=");
2979a6d73f1SSasha Levin 	}
2989a6d73f1SSasha Levin 
2999a6d73f1SSasha Levin 	p = (struct virtio_net_params) {
3009a6d73f1SSasha Levin 		.guest_ip	= DEFAULT_GUEST_ADDR,
3019a6d73f1SSasha Levin 		.host_ip	= DEFAULT_HOST_ADDR,
3029a6d73f1SSasha Levin 		.script		= DEFAULT_SCRIPT,
3039a6d73f1SSasha Levin 		.mode		= NET_MODE_TAP,
3049a6d73f1SSasha Levin 	};
3059a6d73f1SSasha Levin 
3069a6d73f1SSasha Levin 	str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac);
307b54cb31cSSasha Levin 	p.guest_mac[5] += cfg.num_net_devices;
3089a6d73f1SSasha Levin 
3099a6d73f1SSasha Levin 	while (cur) {
3109a6d73f1SSasha Levin 		if (on_cmd) {
3119a6d73f1SSasha Levin 			cmd = cur;
3129a6d73f1SSasha Levin 		} else {
3139a6d73f1SSasha Levin 			if (set_net_param(&p, cmd, cur) < 0)
3149a6d73f1SSasha Levin 				goto done;
3159a6d73f1SSasha Levin 		}
3169a6d73f1SSasha Levin 		on_cmd = !on_cmd;
3179a6d73f1SSasha Levin 
3189a6d73f1SSasha Levin 		cur = strtok(NULL, ",=");
3199a6d73f1SSasha Levin 	};
3209a6d73f1SSasha Levin 
321b54cb31cSSasha Levin 	cfg.num_net_devices++;
3229a6d73f1SSasha Levin 
323b54cb31cSSasha Levin 	cfg.net_params = realloc(cfg.net_params, cfg.num_net_devices * sizeof(*cfg.net_params));
324b54cb31cSSasha Levin 	if (cfg.net_params == NULL)
3259a6d73f1SSasha Levin 		die("Failed adding new network device");
3269a6d73f1SSasha Levin 
327b54cb31cSSasha Levin 	cfg.net_params[cfg.num_net_devices - 1] = p;
3289a6d73f1SSasha Levin 
3299a6d73f1SSasha Levin done:
3309a6d73f1SSasha Levin 	free(buf);
3319a6d73f1SSasha Levin 	return 0;
3329a6d73f1SSasha Levin }
3339a6d73f1SSasha Levin 
33495d13a52SSasha Levin static int shmem_parser(const struct option *opt, const char *arg, int unset)
33595d13a52SSasha Levin {
33672f1ad6dSSasha Levin 	const u64 default_size = SHMEM_DEFAULT_SIZE;
33772f1ad6dSSasha Levin 	const u64 default_phys_addr = SHMEM_DEFAULT_ADDR;
33895d13a52SSasha Levin 	const char *default_handle = SHMEM_DEFAULT_HANDLE;
33995d13a52SSasha Levin 	struct shmem_info *si = malloc(sizeof(struct shmem_info));
34072f1ad6dSSasha Levin 	u64 phys_addr;
34172f1ad6dSSasha Levin 	u64 size;
34295d13a52SSasha Levin 	char *handle = NULL;
34395d13a52SSasha Levin 	int create = 0;
34495d13a52SSasha Levin 	const char *p = arg;
34595d13a52SSasha Levin 	char *next;
34695d13a52SSasha Levin 	int base = 10;
34795d13a52SSasha Levin 	int verbose = 0;
34895d13a52SSasha Levin 
34995d13a52SSasha Levin 	const int skip_pci = strlen("pci:");
35095d13a52SSasha Levin 	if (verbose)
35195d13a52SSasha Levin 		pr_info("shmem_parser(%p,%s,%d)", opt, arg, unset);
35295d13a52SSasha Levin 	/* parse out optional addr family */
35395d13a52SSasha Levin 	if (strcasestr(p, "pci:")) {
35495d13a52SSasha Levin 		p += skip_pci;
35595d13a52SSasha Levin 	} else if (strcasestr(p, "mem:")) {
35695d13a52SSasha Levin 		die("I can't add to E820 map yet.\n");
35795d13a52SSasha Levin 	}
35895d13a52SSasha Levin 	/* parse out physical addr */
35995d13a52SSasha Levin 	base = 10;
36095d13a52SSasha Levin 	if (strcasestr(p, "0x"))
36195d13a52SSasha Levin 		base = 16;
36295d13a52SSasha Levin 	phys_addr = strtoll(p, &next, base);
36395d13a52SSasha Levin 	if (next == p && phys_addr == 0) {
36495d13a52SSasha Levin 		pr_info("shmem: no physical addr specified, using default.");
36595d13a52SSasha Levin 		phys_addr = default_phys_addr;
36695d13a52SSasha Levin 	}
36795d13a52SSasha Levin 	if (*next != ':' && *next != '\0')
36895d13a52SSasha Levin 		die("shmem: unexpected chars after phys addr.\n");
36995d13a52SSasha Levin 	if (*next == '\0')
37095d13a52SSasha Levin 		p = next;
37195d13a52SSasha Levin 	else
37295d13a52SSasha Levin 		p = next + 1;
37395d13a52SSasha Levin 	/* parse out size */
37495d13a52SSasha Levin 	base = 10;
37595d13a52SSasha Levin 	if (strcasestr(p, "0x"))
37695d13a52SSasha Levin 		base = 16;
37795d13a52SSasha Levin 	size = strtoll(p, &next, base);
37895d13a52SSasha Levin 	if (next == p && size == 0) {
37995d13a52SSasha Levin 		pr_info("shmem: no size specified, using default.");
38095d13a52SSasha Levin 		size = default_size;
38195d13a52SSasha Levin 	}
38295d13a52SSasha Levin 	/* look for [KMGkmg][Bb]*  uses base 2. */
38395d13a52SSasha Levin 	int skip_B = 0;
38495d13a52SSasha Levin 	if (strspn(next, "KMGkmg")) {	/* might have a prefix */
38595d13a52SSasha Levin 		if (*(next + 1) == 'B' || *(next + 1) == 'b')
38695d13a52SSasha Levin 			skip_B = 1;
38795d13a52SSasha Levin 		switch (*next) {
38895d13a52SSasha Levin 		case 'K':
38995d13a52SSasha Levin 		case 'k':
39095d13a52SSasha Levin 			size = size << KB_SHIFT;
39195d13a52SSasha Levin 			break;
39295d13a52SSasha Levin 		case 'M':
39395d13a52SSasha Levin 		case 'm':
39495d13a52SSasha Levin 			size = size << MB_SHIFT;
39595d13a52SSasha Levin 			break;
39695d13a52SSasha Levin 		case 'G':
39795d13a52SSasha Levin 		case 'g':
39895d13a52SSasha Levin 			size = size << GB_SHIFT;
39995d13a52SSasha Levin 			break;
40095d13a52SSasha Levin 		default:
40195d13a52SSasha Levin 			die("shmem: bug in detecting size prefix.");
40295d13a52SSasha Levin 			break;
40395d13a52SSasha Levin 		}
40495d13a52SSasha Levin 		next += 1 + skip_B;
40595d13a52SSasha Levin 	}
40695d13a52SSasha Levin 	if (*next != ':' && *next != '\0') {
40795d13a52SSasha Levin 		die("shmem: unexpected chars after phys size. <%c><%c>\n",
40895d13a52SSasha Levin 		    *next, *p);
40995d13a52SSasha Levin 	}
41095d13a52SSasha Levin 	if (*next == '\0')
41195d13a52SSasha Levin 		p = next;
41295d13a52SSasha Levin 	else
41395d13a52SSasha Levin 		p = next + 1;
41495d13a52SSasha Levin 	/* parse out optional shmem handle */
41595d13a52SSasha Levin 	const int skip_handle = strlen("handle=");
41695d13a52SSasha Levin 	next = strcasestr(p, "handle=");
41795d13a52SSasha Levin 	if (*p && next) {
41895d13a52SSasha Levin 		if (p != next)
41995d13a52SSasha Levin 			die("unexpected chars before handle\n");
42095d13a52SSasha Levin 		p += skip_handle;
42195d13a52SSasha Levin 		next = strchrnul(p, ':');
42295d13a52SSasha Levin 		if (next - p) {
42395d13a52SSasha Levin 			handle = malloc(next - p + 1);
42495d13a52SSasha Levin 			strncpy(handle, p, next - p);
42595d13a52SSasha Levin 			handle[next - p] = '\0';	/* just in case. */
42695d13a52SSasha Levin 		}
42795d13a52SSasha Levin 		if (*next == '\0')
42895d13a52SSasha Levin 			p = next;
42995d13a52SSasha Levin 		else
43095d13a52SSasha Levin 			p = next + 1;
43195d13a52SSasha Levin 	}
43295d13a52SSasha Levin 	/* parse optional create flag to see if we should create shm seg. */
43395d13a52SSasha Levin 	if (*p && strcasestr(p, "create")) {
43495d13a52SSasha Levin 		create = 1;
43595d13a52SSasha Levin 		p += strlen("create");
43695d13a52SSasha Levin 	}
43795d13a52SSasha Levin 	if (*p != '\0')
43895d13a52SSasha Levin 		die("shmem: unexpected trailing chars\n");
43995d13a52SSasha Levin 	if (handle == NULL) {
44095d13a52SSasha Levin 		handle = malloc(strlen(default_handle) + 1);
44195d13a52SSasha Levin 		strcpy(handle, default_handle);
44295d13a52SSasha Levin 	}
44395d13a52SSasha Levin 	if (verbose) {
44472f1ad6dSSasha Levin 		pr_info("shmem: phys_addr = %llx", phys_addr);
44572f1ad6dSSasha Levin 		pr_info("shmem: size      = %llx", size);
44695d13a52SSasha Levin 		pr_info("shmem: handle    = %s", handle);
44795d13a52SSasha Levin 		pr_info("shmem: create    = %d", create);
44895d13a52SSasha Levin 	}
44995d13a52SSasha Levin 
45095d13a52SSasha Levin 	si->phys_addr = phys_addr;
45195d13a52SSasha Levin 	si->size = size;
45295d13a52SSasha Levin 	si->handle = handle;
45395d13a52SSasha Levin 	si->create = create;
45495d13a52SSasha Levin 	pci_shmem__register_mem(si);	/* ownership of si, etc. passed on. */
45595d13a52SSasha Levin 	return 0;
45695d13a52SSasha Levin }
457b4422bf3SAneesh Kumar K.V 
458*b816364aSSasha Levin #define BUILD_OPTIONS(name, cfg)					\
459*b816364aSSasha Levin 	struct option name[] = {					\
460*b816364aSSasha Levin 	OPT_GROUP("Basic options:"),					\
461*b816364aSSasha Levin 	OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name",	\
462*b816364aSSasha Levin 			"A name for the guest"),			\
463*b816364aSSasha Levin 	OPT_INTEGER('c', "cpus", &nrcpus, "Number of CPUs"),		\
464*b816364aSSasha Levin 	OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory size\
465*b816364aSSasha Levin 		in MiB."),						\
466*b816364aSSasha Levin 	OPT_CALLBACK('\0', "shmem", NULL,				\
467*b816364aSSasha Levin 		     "[pci:]<addr>:<size>[:handle=<handle>][:create]",	\
468*b816364aSSasha Levin 		     "Share host shmem with guest via pci device",	\
469*b816364aSSasha Levin 		     shmem_parser),					\
470*b816364aSSasha Levin 	OPT_CALLBACK('d', "disk", NULL, "image or rootfs_dir", "Disk	\
471*b816364aSSasha Levin 			image or rootfs directory", img_name_parser),	\
472*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio	\
473*b816364aSSasha Levin 			balloon"),					\
474*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\
475*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\
476*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio Random\
477*b816364aSSasha Levin 			Number Generator"),				\
478*b816364aSSasha Levin 	OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name",		\
479*b816364aSSasha Levin 		     "Enable virtio 9p to share files between host and	\
480*b816364aSSasha Levin 		     guest", virtio_9p_rootdir_parser),			\
481*b816364aSSasha Levin 	OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or	\
482*b816364aSSasha Levin 			hv", "Console to use"),				\
483*b816364aSSasha Levin 	OPT_STRING('\0', "dev", &(cfg)->dev, "device_file",		\
484*b816364aSSasha Levin 			"KVM device file"),				\
485*b816364aSSasha Levin 	OPT_CALLBACK('\0', "tty", NULL, "tty id",			\
486*b816364aSSasha Levin 		     "Remap guest TTY into a pty on the host",		\
487*b816364aSSasha Levin 		     tty_parser),					\
488*b816364aSSasha Levin 	OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script",		\
489*b816364aSSasha Levin 			"Run this script when booting into custom	\
490*b816364aSSasha Levin 			rootfs"),					\
491*b816364aSSasha Levin 	OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path",	\
492*b816364aSSasha Levin 			"Hugetlbfs path"),				\
493*b816364aSSasha Levin 									\
494*b816364aSSasha Levin 	OPT_GROUP("Kernel options:"),					\
495*b816364aSSasha Levin 	OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel",	\
496*b816364aSSasha Levin 			"Kernel to boot in virtual machine"),		\
497*b816364aSSasha Levin 	OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd",	\
498*b816364aSSasha Levin 			"Initial RAM disk image"),			\
499*b816364aSSasha Levin 	OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params",	\
500*b816364aSSasha Levin 			"Kernel command line arguments"),		\
501*b816364aSSasha Levin 	OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\
502*b816364aSSasha Levin 			"Firmware image to boot in virtual machine"),	\
503*b816364aSSasha Levin 									\
504*b816364aSSasha Levin 	OPT_GROUP("Networking options:"),				\
505*b816364aSSasha Levin 	OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",	\
506*b816364aSSasha Levin 		     "Create a new guest NIC",				\
507*b816364aSSasha Levin 		     netdev_parser, NULL),				\
508*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\
509*b816364aSSasha Levin 			in rootfs mode"),				\
510*b816364aSSasha Levin 									\
511*b816364aSSasha Levin 	OPT_GROUP("BIOS options:"),					\
512*b816364aSSasha Levin 	OPT_INTEGER('\0', "vidmode", &vidmode,				\
513*b816364aSSasha Levin 		    "Video mode"),					\
514*b816364aSSasha Levin 									\
515*b816364aSSasha Levin 	OPT_GROUP("Debug options:"),					\
516*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug", &do_debug_print,			\
517*b816364aSSasha Levin 			"Enable debug messages"),			\
518*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step,	\
519*b816364aSSasha Levin 			"Enable single stepping"),			\
520*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug-ioport", &ioport_debug,		\
521*b816364aSSasha Levin 			"Enable ioport debugging"),			\
522*b816364aSSasha Levin 	OPT_BOOLEAN('\0', "debug-mmio", &mmio_debug,			\
523*b816364aSSasha Levin 			"Enable MMIO debugging"),			\
524*b816364aSSasha Levin 	OPT_INTEGER('\0', "debug-iodelay", &debug_iodelay,		\
525*b816364aSSasha Levin 			"Delay IO by millisecond"),			\
526*b816364aSSasha Levin 	OPT_END()							\
527f967c427SPrasad Joshi 	};
528f967c427SPrasad Joshi 
529b5b501ccSIngo Molnar /*
530b5b501ccSIngo Molnar  * Serialize debug printout so that the output of multiple vcpus does not
531b5b501ccSIngo Molnar  * get mixed up:
532b5b501ccSIngo Molnar  */
533cffeab25SIngo Molnar static int printout_done;
534b5b501ccSIngo Molnar 
53543119af7SPekka Enberg static void handle_sigusr1(int sig)
53643119af7SPekka Enberg {
53743119af7SPekka Enberg 	struct kvm_cpu *cpu = current_kvm_cpu;
538b7d2f013SSasha Levin 	int fd = kvm_cpu__get_debug_fd();
53943119af7SPekka Enberg 
5404b1c6f6eSSasha Levin 	if (!cpu || cpu->needs_nmi)
54143119af7SPekka Enberg 		return;
54243119af7SPekka Enberg 
543b7d2f013SSasha Levin 	dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
54443119af7SPekka Enberg 	kvm_cpu__show_registers(cpu);
54543119af7SPekka Enberg 	kvm_cpu__show_code(cpu);
54643119af7SPekka Enberg 	kvm_cpu__show_page_tables(cpu);
547b5b501ccSIngo Molnar 	fflush(stdout);
548cffeab25SIngo Molnar 	printout_done = 1;
549cffeab25SIngo Molnar 	mb();
55043119af7SPekka Enberg }
55143119af7SPekka Enberg 
552d94e22b9SSasha Levin /* Pause/resume the guest using SIGUSR2 */
553d94e22b9SSasha Levin static int is_paused;
554d94e22b9SSasha Levin 
5554b1addaeSSasha Levin static void handle_pause(int fd, u32 type, u32 len, u8 *msg)
556d94e22b9SSasha Levin {
5575aa502e4SLai Jiangshan 	if (WARN_ON(len))
5585aa502e4SLai Jiangshan 		return;
5595aa502e4SLai Jiangshan 
5607021c50bSAsias He 	if (type == KVM_IPC_RESUME && is_paused) {
5617021c50bSAsias He 		kvm->vm_state = KVM_VMSTATE_RUNNING;
562d94e22b9SSasha Levin 		kvm__continue();
5637021c50bSAsias He 	} else if (type == KVM_IPC_PAUSE && !is_paused) {
5647021c50bSAsias He 		kvm->vm_state = KVM_VMSTATE_PAUSED;
565eb8dad9dSSasha Levin 		ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL);
566d94e22b9SSasha Levin 		kvm__pause();
5677021c50bSAsias He 	} else {
56802317b74SSasha Levin 		return;
5695aa502e4SLai Jiangshan 	}
570d94e22b9SSasha Levin 
571d94e22b9SSasha Levin 	is_paused = !is_paused;
572d94e22b9SSasha Levin }
573d94e22b9SSasha Levin 
5747021c50bSAsias He static void handle_vmstate(int fd, u32 type, u32 len, u8 *msg)
5757021c50bSAsias He {
5767021c50bSAsias He 	int r = 0;
5777021c50bSAsias He 
5787021c50bSAsias He 	if (type == KVM_IPC_VMSTATE)
5797021c50bSAsias He 		r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
5807021c50bSAsias He 
5817021c50bSAsias He 	if (r < 0)
5827021c50bSAsias He 		pr_warning("Failed sending VMSTATE");
5837021c50bSAsias He }
5847021c50bSAsias He 
5854b1addaeSSasha Levin static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
5869e854d1aSPekka Enberg {
5879e854d1aSPekka Enberg 	int i;
588a59cdf44SLai Jiangshan 	struct debug_cmd_params *params;
589a59cdf44SLai Jiangshan 	u32 dbg_type;
590a59cdf44SLai Jiangshan 	u32 vcpu;
591a59cdf44SLai Jiangshan 
592a59cdf44SLai Jiangshan 	if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
593a59cdf44SLai Jiangshan 		return;
594a59cdf44SLai Jiangshan 
595a59cdf44SLai Jiangshan 	params = (void *)msg;
596a59cdf44SLai Jiangshan 	dbg_type = params->dbg_type;
597a59cdf44SLai Jiangshan 	vcpu = params->cpu;
5984b1c6f6eSSasha Levin 
599226e727bSSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ)
600226e727bSSasha Levin 		serial8250__inject_sysrq(kvm, params->sysrq);
601226e727bSSasha Levin 
6024b1c6f6eSSasha Levin 	if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
6037070414aSSasha Levin 		if ((int)vcpu >= kvm->nrcpus)
6044b1c6f6eSSasha Levin 			return;
6054b1c6f6eSSasha Levin 
6064b1c6f6eSSasha Levin 		kvm_cpus[vcpu]->needs_nmi = 1;
6074b1c6f6eSSasha Levin 		pthread_kill(kvm_cpus[vcpu]->thread, SIGUSR1);
6084b1c6f6eSSasha Levin 	}
6094b1c6f6eSSasha Levin 
6104b1c6f6eSSasha Levin 	if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
6114b1c6f6eSSasha Levin 		return;
6129e854d1aSPekka Enberg 
6139e854d1aSPekka Enberg 	for (i = 0; i < nrcpus; i++) {
6149e854d1aSPekka Enberg 		struct kvm_cpu *cpu = kvm_cpus[i];
6159e854d1aSPekka Enberg 
61643119af7SPekka Enberg 		if (!cpu)
61743119af7SPekka Enberg 			continue;
61843119af7SPekka Enberg 
619cffeab25SIngo Molnar 		printout_done = 0;
620b7d2f013SSasha Levin 
621b7d2f013SSasha Levin 		kvm_cpu__set_debug_fd(fd);
62243119af7SPekka Enberg 		pthread_kill(cpu->thread, SIGUSR1);
623cffeab25SIngo Molnar 		/*
624cffeab25SIngo Molnar 		 * Wait for the vCPU to dump state before signalling
625cffeab25SIngo Molnar 		 * the next thread. Since this is debug code it does
626cffeab25SIngo Molnar 		 * not matter that we are burning CPU time a bit:
627cffeab25SIngo Molnar 		 */
628cffeab25SIngo Molnar 		while (!printout_done)
629cffeab25SIngo Molnar 			mb();
6309e854d1aSPekka Enberg 	}
6319e854d1aSPekka Enberg 
632b7d2f013SSasha Levin 	close(fd);
633b7d2f013SSasha Levin 
634226e727bSSasha Levin 	serial8250__inject_sysrq(kvm, 'p');
6359e854d1aSPekka Enberg }
6369e854d1aSPekka Enberg 
6379e854d1aSPekka Enberg static void handle_sigalrm(int sig)
6389e854d1aSPekka Enberg {
6390b69bdefSMatt Evans 	kvm__arch_periodic_poll(kvm);
6409e854d1aSPekka Enberg }
6419e854d1aSPekka Enberg 
6424b1addaeSSasha Levin static void handle_stop(int fd, u32 type, u32 len, u8 *msg)
643daf4cb5aSSasha Levin {
644e333e41aSLai Jiangshan 	if (WARN_ON(type != KVM_IPC_STOP || len))
645e333e41aSLai Jiangshan 		return;
646e333e41aSLai Jiangshan 
647daf4cb5aSSasha Levin 	kvm_cpu__reboot();
648daf4cb5aSSasha Levin }
649daf4cb5aSSasha Levin 
6505ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg)
6515ee154d1SPekka Enberg {
652d77a9efaSCyrill Gorcunov 	current_kvm_cpu		= arg;
6535ee154d1SPekka Enberg 
654d77a9efaSCyrill Gorcunov 	if (kvm_cpu__start(current_kvm_cpu))
6555ee154d1SPekka Enberg 		goto panic_kvm;
6565ee154d1SPekka Enberg 
6575ee154d1SPekka Enberg 	return (void *) (intptr_t) 0;
6585ee154d1SPekka Enberg 
6595ee154d1SPekka Enberg panic_kvm:
6603fdf659dSSasha Levin 	fprintf(stderr, "KVM exit reason: %u (\"%s\")\n",
661d77a9efaSCyrill Gorcunov 		current_kvm_cpu->kvm_run->exit_reason,
662d77a9efaSCyrill Gorcunov 		kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]);
663d77a9efaSCyrill Gorcunov 	if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
6645ee154d1SPekka Enberg 		fprintf(stderr, "KVM exit code: 0x%Lu\n",
665d77a9efaSCyrill Gorcunov 			current_kvm_cpu->kvm_run->hw.hardware_exit_reason);
6668e5accedSPekka Enberg 
667b7d2f013SSasha Levin 	kvm_cpu__set_debug_fd(STDOUT_FILENO);
668d77a9efaSCyrill Gorcunov 	kvm_cpu__show_registers(current_kvm_cpu);
669d77a9efaSCyrill Gorcunov 	kvm_cpu__show_code(current_kvm_cpu);
670d77a9efaSCyrill Gorcunov 	kvm_cpu__show_page_tables(current_kvm_cpu);
6715ee154d1SPekka Enberg 
6725ee154d1SPekka Enberg 	return (void *) (intptr_t) 1;
6735ee154d1SPekka Enberg }
6745ee154d1SPekka Enberg 
675e08c0896SPrasad Joshi static char kernel[PATH_MAX];
676b0b42ba0SPekka Enberg 
677b0b42ba0SPekka Enberg static const char *host_kernels[] = {
678e08c0896SPrasad Joshi 	"/boot/vmlinuz",
679e08c0896SPrasad Joshi 	"/boot/bzImage",
680e08c0896SPrasad Joshi 	NULL
681e08c0896SPrasad Joshi };
682b0b42ba0SPekka Enberg 
683b0b42ba0SPekka Enberg static const char *default_kernels[] = {
684e08c0896SPrasad Joshi 	"./bzImage",
685b03af790SKonstantin Khlebnikov 	"arch/" BUILD_ARCH "/boot/bzImage",
686af7b0868SMatt Evans 	"../../arch/" BUILD_ARCH "/boot/bzImage",
687e08c0896SPrasad Joshi 	NULL
688e08c0896SPrasad Joshi };
6898329f30bSPekka Enberg 
690b0b42ba0SPekka Enberg static const char *default_vmlinux[] = {
691b03af790SKonstantin Khlebnikov 	"vmlinux",
692b0b42ba0SPekka Enberg 	"../../../vmlinux",
693b0b42ba0SPekka Enberg 	"../../vmlinux",
694b0b42ba0SPekka Enberg 	NULL
695b0b42ba0SPekka Enberg };
696b0b42ba0SPekka Enberg 
697e08c0896SPrasad Joshi static void kernel_usage_with_options(void)
6988329f30bSPekka Enberg {
699e08c0896SPrasad Joshi 	const char **k;
7008329f30bSPekka Enberg 	struct utsname uts;
701e08c0896SPrasad Joshi 
702e08c0896SPrasad Joshi 	fprintf(stderr, "Fatal: could not find default kernel image in:\n");
70365182f37SPrasad Joshi 	k = &default_kernels[0];
704e08c0896SPrasad Joshi 	while (*k) {
705e08c0896SPrasad Joshi 		fprintf(stderr, "\t%s\n", *k);
706e08c0896SPrasad Joshi 		k++;
707e08c0896SPrasad Joshi 	}
708e08c0896SPrasad Joshi 
709e08c0896SPrasad Joshi 	if (uname(&uts) < 0)
710e08c0896SPrasad Joshi 		return;
711e08c0896SPrasad Joshi 
712e08c0896SPrasad Joshi 	k = &host_kernels[0];
713e08c0896SPrasad Joshi 	while (*k) {
714e08c0896SPrasad Joshi 		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
715e08c0896SPrasad Joshi 			return;
716e08c0896SPrasad Joshi 		fprintf(stderr, "\t%s\n", kernel);
717e08c0896SPrasad Joshi 		k++;
718e08c0896SPrasad Joshi 	}
719ee8b1456SWanlong Gao 	fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n",
720ee8b1456SWanlong Gao 		KVM_BINARY_NAME);
721e08c0896SPrasad Joshi }
722e08c0896SPrasad Joshi 
72360ded003SPekka Enberg static u64 host_ram_size(void)
72460ded003SPekka Enberg {
72560ded003SPekka Enberg 	long page_size;
72660ded003SPekka Enberg 	long nr_pages;
72760ded003SPekka Enberg 
72860ded003SPekka Enberg 	nr_pages	= sysconf(_SC_PHYS_PAGES);
729d63c5ce6SPekka Enberg 	if (nr_pages < 0) {
7304542f276SCyrill Gorcunov 		pr_warning("sysconf(_SC_PHYS_PAGES) failed");
731d63c5ce6SPekka Enberg 		return 0;
732d63c5ce6SPekka Enberg 	}
73360ded003SPekka Enberg 
73460ded003SPekka Enberg 	page_size	= sysconf(_SC_PAGE_SIZE);
735d63c5ce6SPekka Enberg 	if (page_size < 0) {
7364542f276SCyrill Gorcunov 		pr_warning("sysconf(_SC_PAGE_SIZE) failed");
737d63c5ce6SPekka Enberg 		return 0;
738d63c5ce6SPekka Enberg 	}
73960ded003SPekka Enberg 
74060ded003SPekka Enberg 	return (nr_pages * page_size) >> MB_SHIFT;
74160ded003SPekka Enberg }
74260ded003SPekka Enberg 
74318bd8c3bSPekka Enberg /*
74418bd8c3bSPekka Enberg  * If user didn't specify how much memory it wants to allocate for the guest,
74518bd8c3bSPekka Enberg  * avoid filling the whole host RAM.
74618bd8c3bSPekka Enberg  */
74718bd8c3bSPekka Enberg #define RAM_SIZE_RATIO		0.8
74818bd8c3bSPekka Enberg 
749fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus)
750fd834defSPekka Enberg {
75106761c76SPekka Enberg 	u64 available;
75206761c76SPekka Enberg 	u64 ram_size;
753fd834defSPekka Enberg 
754fd834defSPekka Enberg 	ram_size	= 64 * (nr_cpus + 3);
755fd834defSPekka Enberg 
75660ded003SPekka Enberg 	available	= host_ram_size() * RAM_SIZE_RATIO;
757d63c5ce6SPekka Enberg 	if (!available)
758d63c5ce6SPekka Enberg 		available = MIN_RAM_SIZE_MB;
759fd834defSPekka Enberg 
760fd834defSPekka Enberg 	if (ram_size > available)
761fd834defSPekka Enberg 		ram_size	= available;
762fd834defSPekka Enberg 
763fd834defSPekka Enberg 	return ram_size;
764fd834defSPekka Enberg }
765fd834defSPekka Enberg 
766e08c0896SPrasad Joshi static const char *find_kernel(void)
767e08c0896SPrasad Joshi {
768e08c0896SPrasad Joshi 	const char **k;
7698329f30bSPekka Enberg 	struct stat st;
770e08c0896SPrasad Joshi 	struct utsname uts;
771e08c0896SPrasad Joshi 
77265182f37SPrasad Joshi 	k = &default_kernels[0];
773e08c0896SPrasad Joshi 	while (*k) {
774e08c0896SPrasad Joshi 		if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) {
775e08c0896SPrasad Joshi 			k++;
776e08c0896SPrasad Joshi 			continue;
777e08c0896SPrasad Joshi 		}
778e08c0896SPrasad Joshi 		strncpy(kernel, *k, PATH_MAX);
779e08c0896SPrasad Joshi 		return kernel;
780e08c0896SPrasad Joshi 	}
7818329f30bSPekka Enberg 
7828329f30bSPekka Enberg 	if (uname(&uts) < 0)
7838329f30bSPekka Enberg 		return NULL;
7848329f30bSPekka Enberg 
785e08c0896SPrasad Joshi 	k = &host_kernels[0];
786e08c0896SPrasad Joshi 	while (*k) {
787e08c0896SPrasad Joshi 		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
7888329f30bSPekka Enberg 			return NULL;
7898329f30bSPekka Enberg 
790e08c0896SPrasad Joshi 		if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) {
791e08c0896SPrasad Joshi 			k++;
792e08c0896SPrasad Joshi 			continue;
793e08c0896SPrasad Joshi 		}
794e08c0896SPrasad Joshi 		return kernel;
7958329f30bSPekka Enberg 
796e08c0896SPrasad Joshi 	}
7978329f30bSPekka Enberg 	return NULL;
7988329f30bSPekka Enberg }
7998329f30bSPekka Enberg 
800b0b42ba0SPekka Enberg static const char *find_vmlinux(void)
801b0b42ba0SPekka Enberg {
802b0b42ba0SPekka Enberg 	const char **vmlinux;
803b0b42ba0SPekka Enberg 
804b0b42ba0SPekka Enberg 	vmlinux = &default_vmlinux[0];
805b0b42ba0SPekka Enberg 	while (*vmlinux) {
806b0b42ba0SPekka Enberg 		struct stat st;
807b0b42ba0SPekka Enberg 
808b0b42ba0SPekka Enberg 		if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) {
809b0b42ba0SPekka Enberg 			vmlinux++;
810b0b42ba0SPekka Enberg 			continue;
811b0b42ba0SPekka Enberg 		}
812b0b42ba0SPekka Enberg 		return *vmlinux;
813b0b42ba0SPekka Enberg 	}
814b0b42ba0SPekka Enberg 	return NULL;
815b0b42ba0SPekka Enberg }
816b0b42ba0SPekka Enberg 
817f6677a1dSAmerigo Wang void kvm_run_help(void)
818f6677a1dSAmerigo Wang {
819*b816364aSSasha Levin 	BUILD_OPTIONS(options, &cfg);
820f6677a1dSAmerigo Wang 	usage_with_options(run_usage, options);
821f6677a1dSAmerigo Wang }
822f6677a1dSAmerigo Wang 
823afc2c7c0SAsias He static int kvm_setup_guest_init(void)
8249cec19c8SSasha Levin {
825b54cb31cSSasha Levin 	const char *rootfs = cfg.custom_rootfs_name;
826afc2c7c0SAsias He 	char tmp[PATH_MAX];
827afc2c7c0SAsias He 	size_t size;
828afc2c7c0SAsias He 	int fd, ret;
829afc2c7c0SAsias He 	char *data;
8309cec19c8SSasha Levin 
831afc2c7c0SAsias He 	/* Setup /virt/init */
832afc2c7c0SAsias He 	size = (size_t)&_binary_guest_init_size;
833afc2c7c0SAsias He 	data = (char *)&_binary_guest_init_start;
834afc2c7c0SAsias He 	snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs);
835afc2c7c0SAsias He 	remove(tmp);
836afc2c7c0SAsias He 	fd = open(tmp, O_CREAT | O_WRONLY, 0755);
837afc2c7c0SAsias He 	if (fd < 0)
838afc2c7c0SAsias He 		die("Fail to setup %s", tmp);
839afc2c7c0SAsias He 	ret = xwrite(fd, data, size);
840afc2c7c0SAsias He 	if (ret < 0)
841afc2c7c0SAsias He 		die("Fail to setup %s", tmp);
842afc2c7c0SAsias He 	close(fd);
8439cec19c8SSasha Levin 
844afc2c7c0SAsias He 	return 0;
8459cec19c8SSasha Levin }
8469cec19c8SSasha Levin 
847d50fe489SSasha Levin static int kvm_run_set_sandbox(void)
848d50fe489SSasha Levin {
849b54cb31cSSasha Levin 	const char *guestfs_name = cfg.custom_rootfs_name;
850d50fe489SSasha Levin 	char path[PATH_MAX], script[PATH_MAX], *tmp;
851d50fe489SSasha Levin 
852d50fe489SSasha Levin 	snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name);
853d50fe489SSasha Levin 
854d50fe489SSasha Levin 	remove(path);
855d50fe489SSasha Levin 
856b54cb31cSSasha Levin 	if (cfg.sandbox == NULL)
857d50fe489SSasha Levin 		return 0;
858d50fe489SSasha Levin 
859b54cb31cSSasha Levin 	tmp = realpath(cfg.sandbox, NULL);
860d50fe489SSasha Levin 	if (tmp == NULL)
861d50fe489SSasha Levin 		return -ENOMEM;
862d50fe489SSasha Levin 
863d50fe489SSasha Levin 	snprintf(script, PATH_MAX, "/host/%s", tmp);
864d50fe489SSasha Levin 	free(tmp);
865d50fe489SSasha Levin 
866d50fe489SSasha Levin 	return symlink(script, path);
867d50fe489SSasha Levin }
868d50fe489SSasha Levin 
8695173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg)
8705173b4afSLai Jiangshan {
8715173b4afSLai Jiangshan 	const char *single_quote;
8725173b4afSLai Jiangshan 
8735173b4afSLai Jiangshan 	if (!*arg) { /* zero length string */
8745173b4afSLai Jiangshan 		if (write(fd, "''", 2) <= 0)
8755173b4afSLai Jiangshan 			die("Failed writing sandbox script");
8765173b4afSLai Jiangshan 		return;
8775173b4afSLai Jiangshan 	}
8785173b4afSLai Jiangshan 
8795173b4afSLai Jiangshan 	while (*arg) {
8805173b4afSLai Jiangshan 		single_quote = strchrnul(arg, '\'');
8815173b4afSLai Jiangshan 
8825173b4afSLai Jiangshan 		/* write non-single-quote string as #('string') */
8835173b4afSLai Jiangshan 		if (arg != single_quote) {
8845173b4afSLai Jiangshan 			if (write(fd, "'", 1) <= 0 ||
8855173b4afSLai Jiangshan 			    write(fd, arg, single_quote - arg) <= 0 ||
8865173b4afSLai Jiangshan 			    write(fd, "'", 1) <= 0)
8875173b4afSLai Jiangshan 				die("Failed writing sandbox script");
8885173b4afSLai Jiangshan 		}
8895173b4afSLai Jiangshan 
8905173b4afSLai Jiangshan 		/* write single quote as #("'") */
8915173b4afSLai Jiangshan 		if (*single_quote) {
8925173b4afSLai Jiangshan 			if (write(fd, "\"'\"", 3) <= 0)
8935173b4afSLai Jiangshan 				die("Failed writing sandbox script");
8945173b4afSLai Jiangshan 		} else
8955173b4afSLai Jiangshan 			break;
8965173b4afSLai Jiangshan 
8975173b4afSLai Jiangshan 		arg = single_quote + 1;
8985173b4afSLai Jiangshan 	}
8995173b4afSLai Jiangshan }
9005173b4afSLai Jiangshan 
9015cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len)
9025cd19aa0SPekka Enberg {
9035cd19aa0SPekka Enberg 	struct stat st;
904c2c742d9SPekka Enberg 	int err;
9055cd19aa0SPekka Enberg 
906c2c742d9SPekka Enberg 	err = stat(src, &st);
9075cd19aa0SPekka Enberg 
908c2c742d9SPekka Enberg 	if (!err && S_ISREG(st.st_mode)) {
9095cd19aa0SPekka Enberg 		char resolved_path[PATH_MAX];
9105cd19aa0SPekka Enberg 
911de3f75c9SPekka Enberg 		if (!realpath(src, resolved_path))
912de3f75c9SPekka Enberg 			die("Unable to resolve program %s: %s\n", src, strerror(errno));
9135cd19aa0SPekka Enberg 
9145cd19aa0SPekka Enberg 		snprintf(dst, len, "/host%s", resolved_path);
9155cd19aa0SPekka Enberg 	} else
9165cd19aa0SPekka Enberg 		strncpy(dst, src, len);
9175cd19aa0SPekka Enberg }
9185cd19aa0SPekka Enberg 
9193c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc)
9203c29e2aaSSasha Levin {
9213c29e2aaSSasha Levin 	const char script_hdr[] = "#! /bin/bash\n\n";
9225cd19aa0SPekka Enberg 	char program[PATH_MAX];
9233c29e2aaSSasha Levin 	int fd;
9243c29e2aaSSasha Levin 
925b54cb31cSSasha Levin 	remove(cfg.sandbox);
9263c29e2aaSSasha Levin 
927b54cb31cSSasha Levin 	fd = open(cfg.sandbox, O_RDWR | O_CREAT, 0777);
9283c29e2aaSSasha Levin 	if (fd < 0)
9293c29e2aaSSasha Levin 		die("Failed creating sandbox script");
9303c29e2aaSSasha Levin 
9313c29e2aaSSasha Levin 	if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0)
9323c29e2aaSSasha Levin 		die("Failed writing sandbox script");
9333c29e2aaSSasha Levin 
9345cd19aa0SPekka Enberg 	resolve_program(argv[0], program, PATH_MAX);
9355cd19aa0SPekka Enberg 	kvm_write_sandbox_cmd_exactly(fd, program);
9365cd19aa0SPekka Enberg 
9375cd19aa0SPekka Enberg 	argv++;
9385cd19aa0SPekka Enberg 	argc--;
9395cd19aa0SPekka Enberg 
9403c29e2aaSSasha Levin 	while (argc) {
9413c29e2aaSSasha Levin 		if (write(fd, " ", 1) <= 0)
9423c29e2aaSSasha Levin 			die("Failed writing sandbox script");
9435cd19aa0SPekka Enberg 
9445cd19aa0SPekka Enberg 		kvm_write_sandbox_cmd_exactly(fd, argv[0]);
9453c29e2aaSSasha Levin 		argv++;
9463c29e2aaSSasha Levin 		argc--;
9473c29e2aaSSasha Levin 	}
9483c29e2aaSSasha Levin 	if (write(fd, "\n", 1) <= 0)
9493c29e2aaSSasha Levin 		die("Failed writing sandbox script");
9503c29e2aaSSasha Levin 
9513c29e2aaSSasha Levin 	close(fd);
9523c29e2aaSSasha Levin }
9533c29e2aaSSasha Levin 
954e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv)
955f967c427SPrasad Joshi {
9562d96f6b6SSasha Levin 	static char real_cmdline[2048], default_name[20];
957aba1efa5SPekka Enberg 	struct framebuffer *fb = NULL;
958384922b3SPekka Enberg 	unsigned int nr_online_cpus;
9598259b8ccSSasha Levin 	int max_cpus, recommended_cpus;
9604932d174SSasha Levin 	int i, r;
961*b816364aSSasha Levin 	BUILD_OPTIONS(options, &cfg);
962f967c427SPrasad Joshi 
9635ee154d1SPekka Enberg 	signal(SIGALRM, handle_sigalrm);
9644b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
96543119af7SPekka Enberg 	signal(SIGUSR1, handle_sigusr1);
9664b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
9674b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
9684b1addaeSSasha Levin 	kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
9697021c50bSAsias He 	kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
970f967c427SPrasad Joshi 
971cfd63bbbSSasha Levin 	nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
972b54cb31cSSasha Levin 	cfg.custom_rootfs_name = "default";
973cfd63bbbSSasha Levin 
974f967c427SPrasad Joshi 	while (argc != 0) {
975f967c427SPrasad Joshi 		argc = parse_options(argc, argv, options, run_usage,
9761a007c82SSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION |
9771a007c82SSasha Levin 				PARSE_OPT_KEEP_DASHDASH);
978f967c427SPrasad Joshi 		if (argc != 0) {
9791a007c82SSasha Levin 			/* Cusrom options, should have been handled elsewhere */
9803c29e2aaSSasha Levin 			if (strcmp(argv[0], "--") == 0) {
9813c29e2aaSSasha Levin 				if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
982b54cb31cSSasha Levin 					cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
9833c29e2aaSSasha Levin 					kvm_run_write_sandbox_cmd(argv+1, argc-1);
9841a007c82SSasha Levin 					break;
9853c29e2aaSSasha Levin 				}
9863c29e2aaSSasha Levin 			}
9871a007c82SSasha Levin 
988b54cb31cSSasha Levin 			if ((kvm_run_wrapper == KVM_RUN_DEFAULT && cfg.kernel_filename) ||
989b54cb31cSSasha Levin 				(kvm_run_wrapper == KVM_RUN_SANDBOX && cfg.sandbox)) {
990f967c427SPrasad Joshi 				fprintf(stderr, "Cannot handle parameter: "
991f967c427SPrasad Joshi 						"%s\n", argv[0]);
992f967c427SPrasad Joshi 				usage_with_options(run_usage, options);
993e120b624SPaul Neumann 				return -EINVAL;
994f967c427SPrasad Joshi 			}
995e0747665SSasha Levin 			if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
996e0747665SSasha Levin 				/*
997e0747665SSasha Levin 				 * first unhandled parameter is treated as
998e0747665SSasha Levin 				 * sandbox command
999e0747665SSasha Levin 				 */
1000b54cb31cSSasha Levin 				cfg.sandbox = DEFAULT_SANDBOX_FILENAME;
1001e0747665SSasha Levin 				kvm_run_write_sandbox_cmd(argv, argc);
1002e0747665SSasha Levin 			} else {
1003e0747665SSasha Levin 				/*
1004e0747665SSasha Levin 				 * first unhandled parameter is treated as a kernel
1005e0747665SSasha Levin 				 * image
1006f967c427SPrasad Joshi 				 */
1007b54cb31cSSasha Levin 				cfg.kernel_filename = argv[0];
1008e0747665SSasha Levin 			}
1009f967c427SPrasad Joshi 			argv++;
1010f967c427SPrasad Joshi 			argc--;
1011f967c427SPrasad Joshi 		}
1012f967c427SPrasad Joshi 
1013f967c427SPrasad Joshi 	}
1014f967c427SPrasad Joshi 
1015b54cb31cSSasha Levin 	if (!cfg.kernel_filename)
1016b54cb31cSSasha Levin 		cfg.kernel_filename = find_kernel();
10178329f30bSPekka Enberg 
1018b54cb31cSSasha Levin 	if (!cfg.kernel_filename) {
1019e08c0896SPrasad Joshi 		kernel_usage_with_options();
1020e120b624SPaul Neumann 		return -EINVAL;
10218329f30bSPekka Enberg 	}
10228329f30bSPekka Enberg 
1023b54cb31cSSasha Levin 	cfg.vmlinux_filename = find_vmlinux();
1024b0b42ba0SPekka Enberg 
1025cfd63bbbSSasha Levin 	if (nrcpus == 0)
1026cfd63bbbSSasha Levin 		nrcpus = nr_online_cpus;
1027d77a9efaSCyrill Gorcunov 
1028b54cb31cSSasha Levin 	if (!cfg.ram_size)
1029b54cb31cSSasha Levin 		cfg.ram_size = get_ram_size(nrcpus);
1030fd834defSPekka Enberg 
1031b54cb31cSSasha Levin 	if (cfg.ram_size < MIN_RAM_SIZE_MB)
1032b54cb31cSSasha Levin 		die("Not enough memory specified: %lluMB (min %lluMB)", cfg.ram_size, MIN_RAM_SIZE_MB);
1033a2a002f9SIngo Molnar 
1034b54cb31cSSasha Levin 	if (cfg.ram_size > host_ram_size())
1035b54cb31cSSasha Levin 		pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", cfg.ram_size, host_ram_size());
103660ded003SPekka Enberg 
1037b54cb31cSSasha Levin 	cfg.ram_size <<= MB_SHIFT;
1038f967c427SPrasad Joshi 
1039b54cb31cSSasha Levin 	if (!cfg.dev)
1040b54cb31cSSasha Levin 		cfg.dev = DEFAULT_KVM_DEV;
1041f967c427SPrasad Joshi 
1042b54cb31cSSasha Levin 	if (!cfg.console)
1043b54cb31cSSasha Levin 		cfg.console = DEFAULT_CONSOLE;
10449aa4a0ebSAsias He 
1045b54cb31cSSasha Levin 	if (!strncmp(cfg.console, "virtio", 6))
1046f967c427SPrasad Joshi 		active_console  = CONSOLE_VIRTIO;
1047b54cb31cSSasha Levin 	else if (!strncmp(cfg.console, "serial", 6))
10489aa4a0ebSAsias He 		active_console  = CONSOLE_8250;
1049b54cb31cSSasha Levin 	else if (!strncmp(cfg.console, "hv", 2))
10503bbc49b6SMatt Evans 		active_console = CONSOLE_HV;
10513bbc49b6SMatt Evans 	else
10523bbc49b6SMatt Evans 		pr_warning("No console!");
1053f967c427SPrasad Joshi 
1054b54cb31cSSasha Levin 	if (!cfg.host_ip)
1055b54cb31cSSasha Levin 		cfg.host_ip = DEFAULT_HOST_ADDR;
10564d67c820SSasha Levin 
1057b54cb31cSSasha Levin 	if (!cfg.guest_ip)
1058b54cb31cSSasha Levin 		cfg.guest_ip = DEFAULT_GUEST_ADDR;
1059bb8ffd2fSAsias He 
1060b54cb31cSSasha Levin 	if (!cfg.guest_mac)
1061b54cb31cSSasha Levin 		cfg.guest_mac = DEFAULT_GUEST_MAC;
1062a4e724ddSSasha Levin 
1063b54cb31cSSasha Levin 	if (!cfg.host_mac)
1064b54cb31cSSasha Levin 		cfg.host_mac = DEFAULT_HOST_MAC;
1065d7098b9bSAsias He 
1066b54cb31cSSasha Levin 	if (!cfg.script)
1067b54cb31cSSasha Levin 		cfg.script = DEFAULT_SCRIPT;
106873b7d038SAmos Kong 
1069f967c427SPrasad Joshi 	term_init();
1070f967c427SPrasad Joshi 
1071b54cb31cSSasha Levin 	if (!cfg.guest_name) {
1072b54cb31cSSasha Levin 		if (cfg.custom_rootfs) {
1073b54cb31cSSasha Levin 			cfg.guest_name = cfg.custom_rootfs_name;
1074587a4d17SLai Jiangshan 		} else {
10752d96f6b6SSasha Levin 			sprintf(default_name, "guest-%u", getpid());
1076b54cb31cSSasha Levin 			cfg.guest_name = default_name;
10772d96f6b6SSasha Levin 		}
1078587a4d17SLai Jiangshan 	}
10792d96f6b6SSasha Levin 
1080b54cb31cSSasha Levin 	kvm = kvm__init(cfg.dev, cfg.hugetlbfs_path, cfg.ram_size, cfg.guest_name);
1081d648dbf5SCyrill Gorcunov 	if (IS_ERR(kvm)) {
1082d648dbf5SCyrill Gorcunov 		r = PTR_ERR(kvm);
1083d648dbf5SCyrill Gorcunov 		goto fail;
1084d648dbf5SCyrill Gorcunov 	}
1085f967c427SPrasad Joshi 
1086b54cb31cSSasha Levin 	kvm->single_step = cfg.single_step;
10876d6a4d41SPekka Enberg 
1088ea6eeb1cSSasha Levin 	r = ioeventfd__init(kvm);
1089ea6eeb1cSSasha Levin 	if (r < 0) {
1090ea6eeb1cSSasha Levin 		pr_err("ioeventfd__init() failed with error %d\n", r);
1091ea6eeb1cSSasha Levin 		goto fail;
1092ea6eeb1cSSasha Levin 	}
109337f3d50eSSasha Levin 
1094384922b3SPekka Enberg 	max_cpus = kvm__max_cpus(kvm);
10958259b8ccSSasha Levin 	recommended_cpus = kvm__recommended_cpus(kvm);
1096384922b3SPekka Enberg 
1097384922b3SPekka Enberg 	if (nrcpus > max_cpus) {
1098384922b3SPekka Enberg 		printf("  # Limit the number of CPUs to %d\n", max_cpus);
109990c05188SMatt Evans 		nrcpus = max_cpus;
11008259b8ccSSasha Levin 	} else if (nrcpus > recommended_cpus) {
11018259b8ccSSasha Levin 		printf("  # Warning: The maximum recommended amount of VCPUs"
11028259b8ccSSasha Levin 			" is %d\n", recommended_cpus);
1103384922b3SPekka Enberg 	}
1104384922b3SPekka Enberg 
11050c7c14a7SCyrill Gorcunov 	kvm->nrcpus = nrcpus;
11060c7c14a7SCyrill Gorcunov 
1107e2077857SMatt Evans 	/* Alloc one pointer too many, so array ends up 0-terminated */
1108e2077857SMatt Evans 	kvm_cpus = calloc(nrcpus + 1, sizeof(void *));
1109e2077857SMatt Evans 	if (!kvm_cpus)
1110e2077857SMatt Evans 		die("Couldn't allocate array for %d CPUs", nrcpus);
1111e2077857SMatt Evans 
1112e3c4f8aaSSasha Levin 	r = irq__init(kvm);
1113e3c4f8aaSSasha Levin 	if (r < 0) {
1114e3c4f8aaSSasha Levin 		pr_err("irq__init() failed with error %d\n", r);
1115e3c4f8aaSSasha Levin 		goto fail;
1116e3c4f8aaSSasha Levin 	}
111719e6c8b8SMatt Evans 
11186d987703SSasha Levin 	r = pci__init(kvm);
11196d987703SSasha Levin 	if (r < 0) {
11206d987703SSasha Levin 		pr_err("pci__init() failed with error %d\n", r);
11216d987703SSasha Levin 		goto fail;
11226d987703SSasha Levin 	}
1123b91be965SMatt Evans 
11247af40b91SSasha Levin 	r = ioport__init(kvm);
11257af40b91SSasha Levin 	if (r < 0) {
11267af40b91SSasha Levin 		pr_err("ioport__init() failed with error %d\n", r);
11277af40b91SSasha Levin 		goto fail;
11287af40b91SSasha Levin 	}
11297af40b91SSasha Levin 
1130890364f8SCyrill Gorcunov 	/*
1131890364f8SCyrill Gorcunov 	 * vidmode should be either specified
1132890364f8SCyrill Gorcunov 	 * either set by default
1133890364f8SCyrill Gorcunov 	 */
1134b54cb31cSSasha Levin 	if (cfg.vnc || cfg.sdl) {
1135890364f8SCyrill Gorcunov 		if (vidmode == -1)
1136890364f8SCyrill Gorcunov 			vidmode = 0x312;
113748d9e01aSSasha Levin 	} else {
1138890364f8SCyrill Gorcunov 		vidmode = 0;
113948d9e01aSSasha Levin 	}
1140890364f8SCyrill Gorcunov 
114126c853e4SPrasad Joshi 	memset(real_cmdline, 0, sizeof(real_cmdline));
1142b54cb31cSSasha Levin 	kvm__arch_set_cmdline(real_cmdline, cfg.vnc || cfg.sdl);
11438e704a7aSMatt Evans 
11448e704a7aSMatt Evans 	if (strlen(real_cmdline) > 0)
1145d74181ccSSasha Levin 		strcat(real_cmdline, " ");
11468e704a7aSMatt Evans 
1147b54cb31cSSasha Levin 	if (cfg.kernel_cmdline)
1148b54cb31cSSasha Levin 		strlcat(real_cmdline, cfg.kernel_cmdline, sizeof(real_cmdline));
114926c853e4SPrasad Joshi 
1150b54cb31cSSasha Levin 	if (!cfg.using_rootfs && !cfg.disk_image[0].filename && !cfg.initrd_filename) {
1151c8675741SSasha Levin 		char tmp[PATH_MAX];
11526df1471eSPekka Enberg 
1153b54cb31cSSasha Levin 		kvm_setup_create_new(cfg.custom_rootfs_name);
1154b54cb31cSSasha Levin 		kvm_setup_resolv(cfg.custom_rootfs_name);
1155c8675741SSasha Levin 
11569667701cSPekka Enberg 		snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default");
1157c8675741SSasha Levin 		if (virtio_9p__register(kvm, tmp, "/dev/root") < 0)
1158c8675741SSasha Levin 			die("Unable to initialize virtio 9p");
1159c8675741SSasha Levin 		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
1160c8675741SSasha Levin 			die("Unable to initialize virtio 9p");
1161b54cb31cSSasha Levin 		cfg.using_rootfs = cfg.custom_rootfs = 1;
116226c853e4SPrasad Joshi 	}
116326c853e4SPrasad Joshi 
1164b54cb31cSSasha Levin 	if (cfg.using_rootfs) {
1165ff42603fSSasha Levin 		strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p");
1166b54cb31cSSasha Levin 		if (cfg.custom_rootfs) {
1167d50fe489SSasha Levin 			kvm_run_set_sandbox();
1168d50fe489SSasha Levin 
1169a8e6b4b9SSasha Levin 			strcat(real_cmdline, " init=/virt/init");
1170d50fe489SSasha Levin 
1171b54cb31cSSasha Levin 			if (!cfg.no_dhcp)
1172a8e6b4b9SSasha Levin 				strcat(real_cmdline, "  ip=dhcp");
1173afc2c7c0SAsias He 			if (kvm_setup_guest_init())
1174afc2c7c0SAsias He 				die("Failed to setup init for guest.");
1175a8e6b4b9SSasha Levin 		}
117682d65b5eSSasha Levin 	} else if (!strstr(real_cmdline, "root=")) {
1177ff42603fSSasha Levin 		strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline));
117882d65b5eSSasha Levin 	}
117959aa2d30SSasha Levin 
1180b54cb31cSSasha Levin 	if (cfg.image_count) {
1181b54cb31cSSasha Levin 		kvm->nr_disks = cfg.image_count;
1182b54cb31cSSasha Levin 		kvm->disks = disk_image__open_all((struct disk_image_params *)&cfg.disk_image, cfg.image_count);
11839f9207c5SSasha Levin 		if (IS_ERR(kvm->disks)) {
11849f9207c5SSasha Levin 			r = PTR_ERR(kvm->disks);
11859f9207c5SSasha Levin 			pr_err("disk_image__open_all() failed with error %ld\n",
11869f9207c5SSasha Levin 					PTR_ERR(kvm->disks));
11879f9207c5SSasha Levin 			goto fail;
11889f9207c5SSasha Levin 		}
1189f967c427SPrasad Joshi 	}
1190c1ed214eSPrasad Joshi 
1191ee8b1456SWanlong Gao 	printf("  # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
1192b54cb31cSSasha Levin 		cfg.kernel_filename, cfg.ram_size / 1024 / 1024, nrcpus, cfg.guest_name);
1193471c6facSPekka Enberg 
1194b54cb31cSSasha Levin 	if (!cfg.firmware_filename) {
1195b54cb31cSSasha Levin 		if (!kvm__load_kernel(kvm, cfg.kernel_filename,
1196b54cb31cSSasha Levin 				cfg.initrd_filename, real_cmdline, vidmode))
1197b54cb31cSSasha Levin 			die("unable to load kernel %s", cfg.kernel_filename);
1198f967c427SPrasad Joshi 
1199b54cb31cSSasha Levin 		kvm->vmlinux = cfg.vmlinux_filename;
1200807b77b9SCyrill Gorcunov 		r = symbol_init(kvm);
1201b56f1728SCyrill Gorcunov 		if (r < 0)
1202c4b716ecSPekka Enberg 			pr_debug("symbol_init() failed with error %d\n", r);
12035ad8db5eSPekka Enberg 	}
1204b0b42ba0SPekka Enberg 
1205af7b0868SMatt Evans 	ioport__setup_arch();
1206ac38f433SPekka Enberg 
120720c39545SSasha Levin 	r = rtc__init(kvm);
120820c39545SSasha Levin 	if (r < 0) {
120920c39545SSasha Levin 		pr_err("rtc__init() failed with error %d\n", r);
121020c39545SSasha Levin 		goto fail;
121120c39545SSasha Levin 	}
121264136c1cSPekka Enberg 
121320715a22SSasha Levin 	r = serial8250__init(kvm);
121420715a22SSasha Levin 	if (r < 0) {
121520715a22SSasha Levin 		pr_err("serial__init() failed with error %d\n", r);
121620715a22SSasha Levin 		goto fail;
121720715a22SSasha Levin 	}
1218f967c427SPrasad Joshi 
12199f9207c5SSasha Levin 	r = virtio_blk__init(kvm);
12209f9207c5SSasha Levin 	if (r < 0) {
12219f9207c5SSasha Levin 		pr_err("virtio_blk__init() failed with error %d\n", r);
12229f9207c5SSasha Levin 		goto fail;
12239f9207c5SSasha Levin 	}
12249f9207c5SSasha Levin 
1225a67da3beSAsias He 	r = virtio_scsi_init(kvm);
1226a67da3beSAsias He 	if (r < 0) {
1227a67da3beSAsias He 		pr_err("virtio_scsi_init() failed with error %d\n", r);
1228a67da3beSAsias He 		goto fail;
1229a67da3beSAsias He 	}
1230a67da3beSAsias He 
1231a67da3beSAsias He 
12321621292eSSasha Levin 	if (active_console == CONSOLE_VIRTIO)
1233f967c427SPrasad Joshi 		virtio_console__init(kvm);
1234f967c427SPrasad Joshi 
1235b54cb31cSSasha Levin 	if (cfg.virtio_rng)
123653eca082SSasha Levin 		virtio_rng__init(kvm);
123753eca082SSasha Levin 
1238b54cb31cSSasha Levin 	if (cfg.balloon)
123982d2f21eSSasha Levin 		virtio_bln__init(kvm);
124082d2f21eSSasha Levin 
1241b54cb31cSSasha Levin 	if (!cfg.network)
1242b54cb31cSSasha Levin 		cfg.network = DEFAULT_NETWORK;
12434f56d42cSAsias He 
1244c7838fbdSSasha Levin 	virtio_9p__init(kvm);
1245c7838fbdSSasha Levin 
1246b54cb31cSSasha Levin 	for (i = 0; i < cfg.num_net_devices; i++) {
1247b54cb31cSSasha Levin 		cfg.net_params[i].kvm = kvm;
1248b54cb31cSSasha Levin 		virtio_net__init(&cfg.net_params[i]);
12499a6d73f1SSasha Levin 	}
1250a4e724ddSSasha Levin 
1251b54cb31cSSasha Levin 	if (cfg.num_net_devices == 0 && cfg.no_net == 0) {
12529a6d73f1SSasha Levin 		struct virtio_net_params net_params;
12539a6d73f1SSasha Levin 
12549a6d73f1SSasha Levin 		net_params = (struct virtio_net_params) {
1255b54cb31cSSasha Levin 			.guest_ip	= cfg.guest_ip,
1256b54cb31cSSasha Levin 			.host_ip	= cfg.host_ip,
12579a6d73f1SSasha Levin 			.kvm		= kvm,
1258b54cb31cSSasha Levin 			.script		= cfg.script,
12599a6d73f1SSasha Levin 			.mode		= NET_MODE_USER,
12609a6d73f1SSasha Levin 		};
1261b54cb31cSSasha Levin 		str_to_mac(cfg.guest_mac, net_params.guest_mac);
1262b54cb31cSSasha Levin 		str_to_mac(cfg.host_mac, net_params.host_mac);
12639a6d73f1SSasha Levin 
1264bdfcfca6SSasha Levin 		virtio_net__init(&net_params);
1265bdfcfca6SSasha Levin 	}
12664f56d42cSAsias He 
1267839051d9SSasha Levin 	kvm__init_ram(kvm);
1268839051d9SSasha Levin 
126957d7832bSMatt Evans #ifdef CONFIG_X86
1270714e5b7fSSasha Levin 	kbd__init(kvm);
127157d7832bSMatt Evans #endif
1272714e5b7fSSasha Levin 
127395d13a52SSasha Levin 	pci_shmem__init(kvm);
127495d13a52SSasha Levin 
1275b54cb31cSSasha Levin 	if (cfg.vnc || cfg.sdl) {
12763f838fecSPekka Enberg 		fb = vesa__init(kvm);
127748d9e01aSSasha Levin 		if (IS_ERR(fb)) {
127848d9e01aSSasha Levin 			pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
127948d9e01aSSasha Levin 			goto fail;
128048d9e01aSSasha Levin 		}
12813f838fecSPekka Enberg 	}
12823f838fecSPekka Enberg 
1283b54cb31cSSasha Levin 	if (cfg.vnc && fb) {
128448d9e01aSSasha Levin 		r = vnc__init(fb);
128548d9e01aSSasha Levin 		if (r < 0) {
128648d9e01aSSasha Levin 			pr_err("vnc__init() failed with error %d\n", r);
128748d9e01aSSasha Levin 			goto fail;
128848d9e01aSSasha Levin 		}
128948d9e01aSSasha Levin 	}
129048d9e01aSSasha Levin 
1291b54cb31cSSasha Levin 	if (cfg.sdl && fb) {
12923f838fecSPekka Enberg 		sdl__init(fb);
129348d9e01aSSasha Levin 		if (r < 0) {
129448d9e01aSSasha Levin 			pr_err("sdl__init() failed with error %d\n", r);
129548d9e01aSSasha Levin 			goto fail;
129648d9e01aSSasha Levin 		}
12973f838fecSPekka Enberg 	}
1298aba1efa5SPekka Enberg 
129948d9e01aSSasha Levin 	r = fb__start();
130048d9e01aSSasha Levin 	if (r < 0) {
130148d9e01aSSasha Levin 		pr_err("fb__init() failed with error %d\n", r);
130248d9e01aSSasha Levin 		goto fail;
130348d9e01aSSasha Levin 	}
1304aba1efa5SPekka Enberg 
130525af47eeSMatt Evans 	/* Device init all done; firmware init must
130625af47eeSMatt Evans 	 * come after this (it may set up device trees etc.)
130725af47eeSMatt Evans 	 */
130825af47eeSMatt Evans 
130925af47eeSMatt Evans 	kvm__start_timer(kvm);
131025af47eeSMatt Evans 
1311b54cb31cSSasha Levin 	if (cfg.firmware_filename) {
1312b54cb31cSSasha Levin 		if (!kvm__load_firmware(kvm, cfg.firmware_filename))
1313b54cb31cSSasha Levin 			die("unable to load firmware image %s: %s", cfg.firmware_filename, strerror(errno));
13145ad8db5eSPekka Enberg 	} else {
1315e1e46fe6SSasha Levin 		kvm__arch_setup_firmware(kvm);
13161add9f73SSasha Levin 		if (r < 0) {
13171add9f73SSasha Levin 			pr_err("kvm__arch_setup_firmware() failed with error %d\n", r);
13181add9f73SSasha Levin 			goto fail;
13191add9f73SSasha Levin 		}
13205ad8db5eSPekka Enberg 	}
132125af47eeSMatt Evans 
132225af47eeSMatt Evans 	for (i = 0; i < nrcpus; i++) {
132325af47eeSMatt Evans 		kvm_cpus[i] = kvm_cpu__init(kvm, i);
132425af47eeSMatt Evans 		if (!kvm_cpus[i])
132525af47eeSMatt Evans 			die("unable to initialize KVM VCPU");
132625af47eeSMatt Evans 	}
132725af47eeSMatt Evans 
1328d60bafe5SSasha Levin 	thread_pool__init(nr_online_cpus);
13294932d174SSasha Levin fail:
13304932d174SSasha Levin 	return r;
1331e1e46fe6SSasha Levin }
1332e1e46fe6SSasha Levin 
1333e1e46fe6SSasha Levin static int kvm_cmd_run_work(void)
1334e1e46fe6SSasha Levin {
1335e1e46fe6SSasha Levin 	int i, r = -1;
1336e1e46fe6SSasha Levin 	void *ret = NULL;
1337e1e46fe6SSasha Levin 
1338839051d9SSasha Levin 	for (i = 0; i < nrcpus; i++) {
1339d77a9efaSCyrill Gorcunov 		if (pthread_create(&kvm_cpus[i]->thread, NULL, kvm_cpu_thread, kvm_cpus[i]) != 0)
13405ee154d1SPekka Enberg 			die("unable to create KVM VCPU thread");
13415ee154d1SPekka Enberg 	}
13425ee154d1SPekka Enberg 
134349e5227dSSasha Levin 	/* Only VCPU #0 is going to exit by itself when shutting down */
134449e5227dSSasha Levin 	if (pthread_join(kvm_cpus[0]->thread, &ret) != 0)
1345e1e46fe6SSasha Levin 		r = 0;
13465ee154d1SPekka Enberg 
134789e0575aSPekka Enberg 	kvm_cpu__delete(kvm_cpus[0]);
134820715a22SSasha Levin 	kvm_cpus[0] = NULL;
134989e0575aSPekka Enberg 
135049e5227dSSasha Levin 	for (i = 1; i < nrcpus; i++) {
1351c23d9748SSasha Levin 		if (kvm_cpus[i]->is_running) {
135249e5227dSSasha Levin 			pthread_kill(kvm_cpus[i]->thread, SIGKVMEXIT);
1353d77a9efaSCyrill Gorcunov 			if (pthread_join(kvm_cpus[i]->thread, &ret) != 0)
13545ee154d1SPekka Enberg 				die("pthread_join");
135589e0575aSPekka Enberg 			kvm_cpu__delete(kvm_cpus[i]);
1356c23d9748SSasha Levin 		}
1357e1e46fe6SSasha Levin 		if (ret == NULL)
1358e1e46fe6SSasha Levin 			r = 0;
13595ee154d1SPekka Enberg 	}
1360f967c427SPrasad Joshi 
1361e1e46fe6SSasha Levin 	return r;
1362e1e46fe6SSasha Levin }
1363e1e46fe6SSasha Levin 
13644932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret)
1365e1e46fe6SSasha Levin {
13664932d174SSasha Levin 	int r = 0;
13674932d174SSasha Levin 
1368e6694207SSasha Levin 	compat__print_all_messages();
1369e6694207SSasha Levin 
1370807b77b9SCyrill Gorcunov 	r = symbol_exit(kvm);
13714932d174SSasha Levin 	if (r < 0)
1372807b77b9SCyrill Gorcunov 		pr_warning("symbol_exit() failed with error %d\n", r);
13734932d174SSasha Levin 
1374e3c4f8aaSSasha Levin 	r = irq__exit(kvm);
1375e3c4f8aaSSasha Levin 	if (r < 0)
1376e3c4f8aaSSasha Levin 		pr_warning("irq__exit() failed with error %d\n", r);
1377e3c4f8aaSSasha Levin 
1378aba1efa5SPekka Enberg 	fb__stop();
1379aba1efa5SPekka Enberg 
1380a67da3beSAsias He 	r = virtio_scsi_exit(kvm);
1381a67da3beSAsias He 	if (r < 0)
1382a67da3beSAsias He 		pr_warning("virtio_scsi_exit() failed with error %d\n", r);
1383a67da3beSAsias He 
13849f9207c5SSasha Levin 	r = virtio_blk__exit(kvm);
13859f9207c5SSasha Levin 	if (r < 0)
13869f9207c5SSasha Levin 		pr_warning("virtio_blk__exit() failed with error %d\n", r);
13879f9207c5SSasha Levin 
1388495fbd4eSSasha Levin 	r = virtio_rng__exit(kvm);
1389495fbd4eSSasha Levin 	if (r < 0)
1390495fbd4eSSasha Levin 		pr_warning("virtio_rng__exit() failed with error %d\n", r);
1391a0a1e3c2SPrasad Joshi 
1392b54cb31cSSasha Levin 	r = disk_image__close_all(kvm->disks, cfg.image_count);
13939f9207c5SSasha Levin 	if (r < 0)
13949f9207c5SSasha Levin 		pr_warning("disk_image__close_all() failed with error %d\n", r);
13957af40b91SSasha Levin 
139620715a22SSasha Levin 	r = serial8250__exit(kvm);
139720715a22SSasha Levin 	if (r < 0)
139820715a22SSasha Levin 		pr_warning("serial8250__exit() failed with error %d\n", r);
139920715a22SSasha Levin 
140020c39545SSasha Levin 	r = rtc__exit(kvm);
140120c39545SSasha Levin 	if (r < 0)
140220c39545SSasha Levin 		pr_warning("rtc__exit() failed with error %d\n", r);
140320c39545SSasha Levin 
14041add9f73SSasha Levin 	r = kvm__arch_free_firmware(kvm);
14051add9f73SSasha Levin 	if (r < 0)
14061add9f73SSasha Levin 		pr_warning("kvm__arch_free_firmware() failed with error %d\n", r);
14071add9f73SSasha Levin 
14087af40b91SSasha Levin 	r = ioport__exit(kvm);
14097af40b91SSasha Levin 	if (r < 0)
14107af40b91SSasha Levin 		pr_warning("ioport__exit() failed with error %d\n", r);
14117af40b91SSasha Levin 
1412ea6eeb1cSSasha Levin 	r = ioeventfd__exit(kvm);
1413ea6eeb1cSSasha Levin 	if (r < 0)
1414ea6eeb1cSSasha Levin 		pr_warning("ioeventfd__exit() failed with error %d\n", r);
1415ea6eeb1cSSasha Levin 
14166d987703SSasha Levin 	r = pci__exit(kvm);
14176d987703SSasha Levin 	if (r < 0)
14186d987703SSasha Levin 		pr_warning("pci__exit() failed with error %d\n", r);
14196d987703SSasha Levin 
1420495fbd4eSSasha Levin 	r = kvm__exit(kvm);
1421495fbd4eSSasha Levin 	if (r < 0)
1422495fbd4eSSasha Levin 		pr_warning("pci__exit() failed with error %d\n", r);
1423f967c427SPrasad Joshi 
142449777800SPekka Enberg 	free(kvm_cpus);
142549777800SPekka Enberg 
1426e1e46fe6SSasha Levin 	if (guest_ret == 0)
1427f967c427SPrasad Joshi 		printf("\n  # KVM session ended normally.\n");
1428e1e46fe6SSasha Levin }
1429e1e46fe6SSasha Levin 
1430e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix)
1431e1e46fe6SSasha Levin {
14324932d174SSasha Levin 	int r, ret = -EFAULT;
1433e1e46fe6SSasha Levin 
1434e1e46fe6SSasha Levin 	r = kvm_cmd_run_init(argc, argv);
1435e1e46fe6SSasha Levin 	if (r < 0)
1436e1e46fe6SSasha Levin 		return r;
1437e1e46fe6SSasha Levin 
1438e1e46fe6SSasha Levin 	ret = kvm_cmd_run_work();
1439e1e46fe6SSasha Levin 	kvm_cmd_run_exit(ret);
1440e1e46fe6SSasha Levin 
1441e1e46fe6SSasha Levin 	return ret;
1442f967c427SPrasad Joshi }
1443