1b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes/*
2b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * Check decoding of KVM_* commands of ioctl syscall using /dev/kvm API.
3b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * Based on kvmtest.c from https://lwn.net/Articles/658512/
4b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes *
5b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * kvmtest.c author: Josh Triplett <josh@joshtriplett.org>
6b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * Copyright (c) 2015 Intel Corporation
7b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * Copyright (c) 2017-2018 The strace developers.
8b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes *
9b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * Permission is hereby granted, free of charge, to any person obtaining a copy
10b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * of this software and associated documentation files (the "Software"), to
11b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * deal in the Software without restriction, including without limitation the
12b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * sell copies of the Software, and to permit persons to whom the Software is
14b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * furnished to do so, subject to the following conditions:
15b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes *
16b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * The above copyright notice and this permission notice shall be included in
17b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * all copies or substantial portions of the Software.
18b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes *
19b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes * IN THE SOFTWARE.
26b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes */
27b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
28b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes#include "tests.h"
29b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
30b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes#if defined HAVE_LINUX_KVM_H				\
31b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes && defined HAVE_STRUCT_KVM_REGS			\
32b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes && defined HAVE_STRUCT_KVM_SREGS			\
33b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes && defined HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION	\
34b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes &&(defined __x86_64__ || defined __i386__)
35b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
36b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <fcntl.h>
37b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <stdint.h>
38b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <stdio.h>
39b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <stdlib.h>
40b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <string.h>
41b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <sys/ioctl.h>
42b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <sys/mman.h>
43b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes# include <linux/kvm.h>
44b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
45b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic int
46b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hugheskvm_ioctl(int fd, unsigned long cmd, const char *cmd_str, void *arg)
47b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes{
48b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	int rc = ioctl(fd, cmd, arg);
49b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (rc < 0)
50b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		perror_msg_and_skip("%s", cmd_str);
51b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	return rc;
52b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes}
53b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
54b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes#define KVM_IOCTL(fd_, cmd_, arg_)	\
55b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	kvm_ioctl((fd_), (cmd_), #cmd_, (arg_))
56b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
57b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic const char dev[] = "/dev/kvm";
58b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic const char vm_dev[] = "anon_inode:kvm-vm";
59b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic const char vcpu_dev[] = "anon_inode:kvm-vcpu";
60b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic size_t page_size;
61b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
62b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesextern const char code[];
63b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesextern const unsigned short code_size;
64b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
65b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes__asm__(
66b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	".type code, @object		\n"
67b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"code:				\n"
68b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"	mov $0xd80003f8, %edx	\n"
69b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"	mov $'\n', %al		\n"
70b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"	out %al, (%dx)		\n"
71b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"	hlt			\n"
72b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	".size code, . - code		\n"
73b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	".type code_size, @object	\n"
74b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"code_size:			\n"
75b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	"	.short . - code		\n"
76b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	".size code_size, . - code_size	\n"
77b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	);
78b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
79b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
80b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesstatic void
81b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesrun_kvm(const int vcpu_fd, struct kvm_run *const run, const size_t mmap_size,
82b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	void *const mem)
83b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes{
84b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Initialize CS to point at 0, via a read-modify-write of sregs. */
85b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	struct kvm_sregs sregs;
86b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	KVM_IOCTL(vcpu_fd, KVM_GET_SREGS, &sregs);
87b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_GET_SREGS, {cs={base=%#jx, limit=%u, selector=%u"
88b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", type=%u, present=%u, dpl=%u, db=%u, s=%u, l=%u, g=%u, avl=%u}"
89b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", ...}) = 0\n", vcpu_fd, vcpu_dev, (uintmax_t) sregs.cs.base,
90b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.limit, sregs.cs.selector, sregs.cs.type,
91b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.present, sregs.cs.dpl, sregs.cs.db, sregs.cs.s,
92b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.l, sregs.cs.g, sregs.cs.avl);
93b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
94b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	sregs.cs.base = 0;
95b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	sregs.cs.selector = 0;
96b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	KVM_IOCTL(vcpu_fd, KVM_SET_SREGS, &sregs);
97b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_SET_SREGS, {cs={base=%#jx, limit=%u"
98b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", selector=%u, type=%u, present=%u, dpl=%u, db=%u, s=%u"
99b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", l=%u, g=%u, avl=%u}, ...}) = 0\n",
100b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       vcpu_fd, vcpu_dev, (uintmax_t) sregs.cs.base,
101b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.limit, sregs.cs.selector, sregs.cs.type,
102b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.present, sregs.cs.dpl, sregs.cs.db, sregs.cs.s,
103b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       sregs.cs.l, sregs.cs.g, sregs.cs.avl);
104b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
105b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/*
106b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	 * Initialize registers: instruction pointer for our code, addends,
107b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	 * and initial flags required by x86 architecture.
108b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	 */
109b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	struct kvm_regs regs = {
110b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.rip = page_size,
111b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.rax = 2,
112b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.rbx = 2,
113b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.rflags = 0x2,
114b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	};
115b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	KVM_IOCTL(vcpu_fd, KVM_SET_REGS, &regs);
116b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_SET_REGS, {rax=%#jx, ..."
117b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", rsp=%#jx, rbp=%#jx, ..., rip=%#jx, rflags=%#jx}) = 0\n",
118b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       vcpu_fd, vcpu_dev, (uintmax_t) regs.rax,
119b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       (uintmax_t) regs.rsp, (uintmax_t) regs.rbp,
120b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       (uintmax_t) regs.rip, (uintmax_t) regs.rflags);
121b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
122b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Copy the code */
123b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	memcpy(mem, code, code_size);
124b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
125b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	const char *p = "\n";
126b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
127b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Repeatedly run code and handle VM exits. */
128b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	for (;;) {
129b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		KVM_IOCTL(vcpu_fd, KVM_RUN, NULL);
130b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		printf("ioctl(%d<%s>, KVM_RUN, 0) = 0\n", vcpu_fd, vcpu_dev);
131b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
132b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		switch (run->exit_reason) {
133b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		case KVM_EXIT_HLT:
134b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			if (p)
135b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				error_msg_and_fail("premature KVM_EXIT_HLT");
136b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			return;
137b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		case KVM_EXIT_IO:
138b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			if (run->io.direction == KVM_EXIT_IO_OUT
139b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			    && run->io.size == 1
140b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			    && run->io.port == 0x03f8
141b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			    && run->io.count == 1
142b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			    && run->io.data_offset < mmap_size
143b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			    && p && *p == ((char *) run)[run->io.data_offset])
144b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				p = NULL;
145b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			else
146b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				error_msg_and_fail("unhandled KVM_EXIT_IO");
147b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			break;
148b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		case KVM_EXIT_MMIO:
149b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			error_msg_and_fail("Got an unexpected MMIO exit:"
150b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   " phys_addr %#llx,"
151b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   " data %02x %02x %02x %02x"
152b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes						" %02x %02x %02x %02x,"
153b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   " len %u, is_write %hhu",
154b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   (unsigned long long) run->mmio.phys_addr,
155b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->mmio.data[0], run->mmio.data[1],
156b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->mmio.data[2], run->mmio.data[3],
157b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->mmio.data[4], run->mmio.data[5],
158b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->mmio.data[6], run->mmio.data[7],
159b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->mmio.len, run->mmio.is_write);
160b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
161b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		default:
162b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes			error_msg_and_fail("exit_reason = %#x",
163b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes					   run->exit_reason);
164b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		}
165b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	}
166b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes}
167b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
168b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesint
169b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughesmain(void)
170b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes{
171b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	skip_if_unavailable("/proc/self/fd/");
172b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
173b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	int kvm = open(dev, O_RDWR);
174b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (kvm < 0)
175b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		perror_msg_and_skip("open: %s", dev);
176b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
177b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Make sure we have the stable version of the API */
178b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	int ret = KVM_IOCTL(kvm, KVM_GET_API_VERSION, 0);
179b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (ret != KVM_API_VERSION)
180b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		error_msg_and_skip("KVM_GET_API_VERSION returned %d"
181b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				   ", KVM_API_VERSION is %d",
182b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				   kvm, KVM_API_VERSION);
183b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_GET_API_VERSION, 0) = %d\n",
184b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       kvm, dev, ret);
185b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
186b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	int vm_fd = KVM_IOCTL(kvm, KVM_CREATE_VM, 0);
187b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_CREATE_VM, 0) = %d<%s>\n",
188b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       kvm, dev, vm_fd, vm_dev);
189b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
190b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Allocate one aligned page of guest memory to hold the code. */
191b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	page_size = get_page_size();
192b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	void *const mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
193b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
194b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (mem == MAP_FAILED)
195b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		perror_msg_and_fail("mmap page");
196b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
197b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Map it to the second page frame (to avoid the real-mode IDT at 0). */
198b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	struct kvm_userspace_memory_region region = {
199b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.slot = 0,
200b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.guest_phys_addr = page_size,
201b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.memory_size = page_size,
202b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		.userspace_addr = (uintptr_t) mem,
203b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	};
204b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	KVM_IOCTL(vm_fd, KVM_SET_USER_MEMORY_REGION, &region);
205b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_SET_USER_MEMORY_REGION"
206b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", {slot=0, flags=0, guest_phys_addr=%#lx, memory_size=%lu"
207b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       ", userspace_addr=%p}) = 0\n", vm_fd, vm_dev,
208b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       (unsigned long) page_size, (unsigned long) page_size, mem);
209b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
210b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	int vcpu_fd = KVM_IOCTL(vm_fd, KVM_CREATE_VCPU, NULL);
211b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_CREATE_VCPU, 0) = %d<%s>\n",
212b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       vm_fd, vm_dev, vcpu_fd, vcpu_dev);
213b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
214b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	/* Map the shared kvm_run structure and following data. */
215b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	ret = KVM_IOCTL(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL);
216b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	struct kvm_run *run;
217b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (ret < (int) sizeof(*run))
218b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		error_msg_and_fail("KVM_GET_VCPU_MMAP_SIZE returned %d < %d",
219b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes				   ret, (int) sizeof(*run));
220b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	printf("ioctl(%d<%s>, KVM_GET_VCPU_MMAP_SIZE, 0) = %d\n",
221b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	       kvm, dev, ret);
222b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
223b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	const size_t mmap_size = (ret + page_size - 1) & -page_size;
224b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
225b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		   MAP_SHARED, vcpu_fd, 0);
226b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	if (run == MAP_FAILED)
227b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		perror_msg_and_fail("mmap vcpu");
228b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
229b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	run_kvm(vcpu_fd, run, mmap_size, mem);
230b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
231b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	puts("+++ exited with 0 +++");
232b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes	return 0;
233b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes}
234b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
235b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes#else /* !HAVE_LINUX_KVM_H */
236b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
237b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott HughesSKIP_MAIN_UNDEFINED("HAVE_LINUX_KVM_H && HAVE_STRUCT_KVM_REGS && "
238b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		    "HAVE_STRUCT_KVM_SREGS && "
239b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		    "HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION && "
240b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes		    "(__x86_64__ || __i386__)")
241b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes
242b755614143ce6aab5265ed32c1bb6c8f748e7898Elliott Hughes#endif
243