ioctl_kvm_run.c revision b755614143ce6aab5265ed32c1bb6c8f748e7898
14ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor/* 24ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor * Check decoding of KVM_* commands of ioctl syscall using /dev/kvm API. 39f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor * Based on kvmtest.c from https://lwn.net/Articles/658512/ 44807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor * 54ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor * kvmtest.c author: Josh Triplett <josh@joshtriplett.org> 64ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor * Copyright (c) 2015 Intel Corporation 79f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor * Copyright (c) 2017-2018 The strace developers. 84ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor * 99f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor * Permission is hereby granted, free of charge, to any person obtaining a copy 103f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * of this software and associated documentation files (the "Software"), to 113f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * deal in the Software without restriction, including without limitation the 123f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 133f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * sell copies of the Software, and to permit persons to whom the Software is 143f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * furnished to do so, subject to the following conditions: 153f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * 163f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * The above copyright notice and this permission notice shall be included in 173f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * all copies or substantial portions of the Software. 183f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * 193f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 203f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2123bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2223bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2323bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2423bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2523bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek * IN THE SOFTWARE. 2623bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek */ 2723bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek 28dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor#include "tests.h" 29dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor 30dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor#if defined HAVE_LINUX_KVM_H \ 318f7c540ac42370c40ebcdc4b69018c938faf94ecArgyrios Kyrtzidis && defined HAVE_STRUCT_KVM_REGS \ 328f7c540ac42370c40ebcdc4b69018c938faf94ecArgyrios Kyrtzidis && defined HAVE_STRUCT_KVM_SREGS \ 33b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis && defined HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION \ 34b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis &&(defined __x86_64__ || defined __i386__) 35b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis 36b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <fcntl.h> 37b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <stdint.h> 38b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <stdio.h> 39b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <stdlib.h> 40b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <string.h> 41b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <sys/ioctl.h> 42b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <sys/mman.h> 43b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis# include <linux/kvm.h> 44b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis 45b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidisstatic int 46b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidiskvm_ioctl(int fd, unsigned long cmd, const char *cmd_str, void *arg) 479f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor{ 489f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor int rc = ioctl(fd, cmd, arg); 49572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor if (rc < 0) 503453bf7da9ac88cd2421b7fdccebf5cd2b8a9d87Argyrios Kyrtzidis perror_msg_and_skip("%s", cmd_str); 514419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor return rc; 524419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor} 534419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 544419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor#define KVM_IOCTL(fd_, cmd_, arg_) \ 554419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor kvm_ioctl((fd_), (cmd_), #cmd_, (arg_)) 564ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor 574ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregorstatic const char dev[] = "/dev/kvm"; 58572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregorstatic const char vm_dev[] = "anon_inode:kvm-vm"; 594419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregorstatic const char vcpu_dev[] = "anon_inode:kvm-vcpu"; 604ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregorstatic size_t page_size; 614ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor 62572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregorextern const char code[]; 634419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregorextern const unsigned short code_size; 644419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 654419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor__asm__( 664419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor ".type code, @object \n" 674419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor "code: \n" 684419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor " mov $0xd80003f8, %edx \n" 694419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor " mov $'\n', %al \n" 704419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor " out %al, (%dx) \n" 719b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth " hlt \n" 724ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor ".size code, . - code \n" 734ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor ".type code_size, @object \n" 744ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor "code_size: \n" 754ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor " .short . - code \n" 764ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor ".size code_size, . - code_size \n" 774ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor ); 789b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth 794ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor 804ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregorstatic void 814ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregorrun_kvm(const int vcpu_fd, struct kvm_run *const run, const size_t mmap_size, 824ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor void *const mem) 834ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor{ 844ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor /* Initialize CS to point at 0, via a read-modify-write of sregs. */ 854ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor struct kvm_sregs sregs; 869b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth KVM_IOCTL(vcpu_fd, KVM_GET_SREGS, &sregs); 879b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth printf("ioctl(%d<%s>, KVM_GET_SREGS, {cs={base=%#jx, limit=%u, selector=%u" 884ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor ", type=%u, present=%u, dpl=%u, db=%u, s=%u, l=%u, g=%u, avl=%u}" 89ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor ", ...}) = 0\n", vcpu_fd, vcpu_dev, (uintmax_t) sregs.cs.base, 904419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor sregs.cs.limit, sregs.cs.selector, sregs.cs.type, 914419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor sregs.cs.present, sregs.cs.dpl, sregs.cs.db, sregs.cs.s, 924ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor sregs.cs.l, sregs.cs.g, sregs.cs.avl); 934ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor 944ae8f298b1ea51b4c2234f9148e2e4349c9bdd23Douglas Gregor sregs.cs.base = 0; 953f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek sregs.cs.selector = 0; 963f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek KVM_IOCTL(vcpu_fd, KVM_SET_SREGS, &sregs); 973f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek printf("ioctl(%d<%s>, KVM_SET_SREGS, {cs={base=%#jx, limit=%u" 984419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor ", selector=%u, type=%u, present=%u, dpl=%u, db=%u, s=%u" 994419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor ", l=%u, g=%u, avl=%u}, ...}) = 0\n", 1004419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor vcpu_fd, vcpu_dev, (uintmax_t) sregs.cs.base, 1014419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor sregs.cs.limit, sregs.cs.selector, sregs.cs.type, 1024419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor sregs.cs.present, sregs.cs.dpl, sregs.cs.db, sregs.cs.s, 1034419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor sregs.cs.l, sregs.cs.g, sregs.cs.avl); 1044419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 1054419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor /* 1063f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * Initialize registers: instruction pointer for our code, addends, 1073f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek * and initial flags required by x86 architecture. 1083f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek */ 1094419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor struct kvm_regs regs = { 1104419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor .rip = page_size, 1114419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor .rax = 2, 1124419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor .rbx = 2, 1134419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor .rflags = 0x2, 1144419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor }; 1153f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek KVM_IOCTL(vcpu_fd, KVM_SET_REGS, ®s); 1163f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek printf("ioctl(%d<%s>, KVM_SET_REGS, {rax=%#jx, ..." 1173f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek ", rsp=%#jx, rbp=%#jx, ..., rip=%#jx, rflags=%#jx}) = 0\n", 1183f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek vcpu_fd, vcpu_dev, (uintmax_t) regs.rax, 11942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor (uintmax_t) regs.rsp, (uintmax_t) regs.rbp, 1203f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek (uintmax_t) regs.rip, (uintmax_t) regs.rflags); 1213f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek 1223f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek /* Copy the code */ 12342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor memcpy(mem, code, code_size); 12442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor 1253f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek const char *p = "\n"; 1263f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek 1273f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek /* Repeatedly run code and handle VM exits. */ 12842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor for (;;) { 12942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor KVM_IOCTL(vcpu_fd, KVM_RUN, NULL); 1303f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek printf("ioctl(%d<%s>, KVM_RUN, 0) = 0\n", vcpu_fd, vcpu_dev); 1313f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek 1323f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek switch (run->exit_reason) { 1339b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth case KVM_EXIT_HLT: 134a676379b26edc959193f9f919ba9c6d296a57824Argyrios Kyrtzidis if (p) 1353f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek error_msg_and_fail("premature KVM_EXIT_HLT"); 136a676379b26edc959193f9f919ba9c6d296a57824Argyrios Kyrtzidis return; 1373f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek case KVM_EXIT_IO: 13850402470f07f720c509c8797f40a106a0d4af6a7Argyrios Kyrtzidis if (run->io.direction == KVM_EXIT_IO_OUT 139d7711ec430fde5706f85ba6c4b85283a8e743ff7Argyrios Kyrtzidis && run->io.size == 1 14042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor && run->io.port == 0x03f8 1413f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek && run->io.count == 1 1423f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek && run->io.data_offset < mmap_size 1433f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek && p && *p == ((char *) run)[run->io.data_offset]) 1449b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth p = NULL; 145a676379b26edc959193f9f919ba9c6d296a57824Argyrios Kyrtzidis else 1463f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek error_msg_and_fail("unhandled KVM_EXIT_IO"); 14742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor break; 1483f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek case KVM_EXIT_MMIO: 14950402470f07f720c509c8797f40a106a0d4af6a7Argyrios Kyrtzidis error_msg_and_fail("Got an unexpected MMIO exit:" 150d7711ec430fde5706f85ba6c4b85283a8e743ff7Argyrios Kyrtzidis " phys_addr %#llx," 15142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor " data %02x %02x %02x %02x" 1523f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek " %02x %02x %02x %02x," 1533f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek " len %u, is_write %hhu", 1543f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek (unsigned long long) run->mmio.phys_addr, 1553f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek run->mmio.data[0], run->mmio.data[1], 15642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor run->mmio.data[2], run->mmio.data[3], 1573f4046004be223b03f1f895bb934e44921ccf805Ted Kremenek run->mmio.data[4], run->mmio.data[5], 15842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor run->mmio.data[6], run->mmio.data[7], 15942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor run->mmio.len, run->mmio.is_write); 16023bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek 16123bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek default: 16223bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek error_msg_and_fail("exit_reason = %#x", 1634419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor run->exit_reason); 1644419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor } 1654419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor } 1664419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor} 1674419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 1684419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregorint 1694419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregormain(void) 1704419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor{ 1714419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor skip_if_unavailable("/proc/self/fd/"); 1724419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 1734419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor int kvm = open(dev, O_RDWR); 1744419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor if (kvm < 0) 1754419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor perror_msg_and_skip("open: %s", dev); 1764419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor 1774419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor /* Make sure we have the stable version of the API */ 1784419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor int ret = KVM_IOCTL(kvm, KVM_GET_API_VERSION, 0); 1794419b675577d7c281a659fab1fec10e1bfbe04c5Douglas Gregor if (ret != KVM_API_VERSION) 18023bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek error_msg_and_skip("KVM_GET_API_VERSION returned %d" 18123bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek ", KVM_API_VERSION is %d", 18223bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek kvm, KVM_API_VERSION); 18323bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek printf("ioctl(%d<%s>, KVM_GET_API_VERSION, 0) = %d\n", 18442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor kvm, dev, ret); 18523bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek 18623bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek int vm_fd = KVM_IOCTL(kvm, KVM_CREATE_VM, 0); 18723bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek printf("ioctl(%d<%s>, KVM_CREATE_VM, 0) = %d<%s>\n", 18842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor kvm, dev, vm_fd, vm_dev); 18942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor 1909b2a0ac970a077bdc0bf08c6c682f80ad733c892Chandler Carruth /* Allocate one aligned page of guest memory to hold the code. */ 19142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor page_size = get_page_size(); 19223bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek void *const mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, 193a676379b26edc959193f9f919ba9c6d296a57824Argyrios Kyrtzidis MAP_SHARED | MAP_ANONYMOUS, -1, 0); 19442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor if (mem == MAP_FAILED) 195c059f89d888cd214e18ed09a7b47339201526381Argyrios Kyrtzidis perror_msg_and_fail("mmap page"); 196a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor 197a676379b26edc959193f9f919ba9c6d296a57824Argyrios Kyrtzidis /* Map it to the second page frame (to avoid the real-mode IDT at 0). */ 19823bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek struct kvm_userspace_memory_region region = { 19942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor .slot = 0, 20042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor .guest_phys_addr = page_size, 20123bc11ff1874f8875426c9a8a29fe1e6894c3503Ted Kremenek .memory_size = page_size, 20242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor .userspace_addr = (uintptr_t) mem, 20342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor }; 204d7711ec430fde5706f85ba6c4b85283a8e743ff7Argyrios Kyrtzidis KVM_IOCTL(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion); 205d7711ec430fde5706f85ba6c4b85283a8e743ff7Argyrios Kyrtzidis printf("ioctl(%d<%s>, KVM_SET_USER_MEMORY_REGION" 20642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor ", {slot=0, flags=0, guest_phys_addr=%#lx, memory_size=%lu" 20742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor ", userspace_addr=%p}) = 0\n", vm_fd, vm_dev, 208dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor (unsigned long) page_size, (unsigned long) page_size, mem); 209dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor 2108f7c540ac42370c40ebcdc4b69018c938faf94ecArgyrios Kyrtzidis int vcpu_fd = KVM_IOCTL(vm_fd, KVM_CREATE_VCPU, NULL); 211b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis printf("ioctl(%d<%s>, KVM_CREATE_VCPU, 0) = %d<%s>\n", 212b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis vm_fd, vm_dev, vcpu_fd, vcpu_dev); 213b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis 214b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis /* Map the shared kvm_run structure and following data. */ 215b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis ret = KVM_IOCTL(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); 216b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis struct kvm_run *run; 217b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis if (ret < (int) sizeof(*run)) 218b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis error_msg_and_fail("KVM_GET_VCPU_MMAP_SIZE returned %d < %d", 219b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis ret, (int) sizeof(*run)); 220b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis printf("ioctl(%d<%s>, KVM_GET_VCPU_MMAP_SIZE, 0) = %d\n", 221b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis kvm, dev, ret); 222b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis 223b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis const size_t mmap_size = (ret + page_size - 1) & -page_size; 224b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, 225b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis MAP_SHARED, vcpu_fd, 0); 226b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis if (run == MAP_FAILED) 227b94b62c3b15967d29f63165e834fa4f12944394cArgyrios Kyrtzidis perror_msg_and_fail("mmap vcpu"); 228 229 run_kvm(vcpu_fd, run, mmap_size, mem); 230 231 puts("+++ exited with 0 +++"); 232 return 0; 233} 234 235#else /* !HAVE_LINUX_KVM_H */ 236 237SKIP_MAIN_UNDEFINED("HAVE_LINUX_KVM_H && HAVE_STRUCT_KVM_REGS && " 238 "HAVE_STRUCT_KVM_SREGS && " 239 "HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION && " 240 "(__x86_64__ || __i386__)") 241 242#endif 243