1 /* 2 * Check decoding of KVM_* commands of ioctl syscall using /dev/kvm API. 3 * Based on kvmtest.c from https://lwn.net/Articles/658512/ 4 * 5 * kvmtest.c author: Josh Triplett <josh (at) joshtriplett.org> 6 * Copyright (c) 2015 Intel Corporation 7 * Copyright (c) 2017-2018 The strace developers. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this software and associated documentation files (the "Software"), to 11 * deal in the Software without restriction, including without limitation the 12 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 * sell copies of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 * IN THE SOFTWARE. 26 */ 27 28 #include "tests.h" 29 30 #if defined HAVE_LINUX_KVM_H \ 31 && defined HAVE_STRUCT_KVM_CPUID2 \ 32 && defined HAVE_STRUCT_KVM_REGS \ 33 && defined HAVE_STRUCT_KVM_SREGS \ 34 && defined HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION \ 35 &&(defined __x86_64__ || defined __i386__) 36 37 # include <fcntl.h> 38 # include <stdint.h> 39 # include <stdio.h> 40 # include <stdlib.h> 41 # include <string.h> 42 # include <sys/ioctl.h> 43 # include <sys/mman.h> 44 # include <unistd.h> 45 # include <linux/kvm.h> 46 47 # ifndef KVM_MAX_CPUID_ENTRIES 48 # define KVM_MAX_CPUID_ENTRIES 80 49 # endif 50 51 #include "xlat.h" 52 #include "xlat/kvm_cpuid_flags.h" 53 54 static int 55 kvm_ioctl(int fd, unsigned long cmd, const char *cmd_str, void *arg) 56 { 57 int rc = ioctl(fd, cmd, arg); 58 if (rc < 0) 59 perror_msg_and_skip("%s", cmd_str); 60 return rc; 61 } 62 63 #define KVM_IOCTL(fd_, cmd_, arg_) \ 64 kvm_ioctl((fd_), (cmd_), #cmd_, (arg_)) 65 66 static const char dev[] = "/dev/kvm"; 67 static const char vm_dev[] = "anon_inode:kvm-vm"; 68 static char vcpu_dev[] = "anon_inode:kvm-vcpu:0"; 69 static size_t page_size; 70 71 extern const char code[]; 72 extern const unsigned short code_size; 73 74 __asm__( 75 ".type code, @object \n" 76 "code: \n" 77 " mov $0xd80003f8, %edx \n" 78 " mov $'\n', %al \n" 79 " out %al, (%dx) \n" 80 " hlt \n" 81 ".size code, . - code \n" 82 ".type code_size, @object \n" 83 "code_size: \n" 84 " .short . - code \n" 85 ".size code_size, . - code_size \n" 86 ); 87 88 static void 89 print_kvm_segment(const struct kvm_segment *seg) 90 { 91 printf("{base=%#jx, limit=%u, selector=%u, type=%u, present=%u, " 92 "dpl=%u, db=%u, s=%u, l=%u, g=%u, avl=%u}", 93 (uintmax_t) seg->base, seg->limit, seg->selector, seg->type, 94 seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, 95 seg->avl); 96 } 97 98 static void 99 print_kvm_sregs(const struct kvm_sregs *sregs) 100 { 101 printf("{cs="); 102 print_kvm_segment(&sregs->cs); 103 #if VERBOSE 104 printf(", ds="); 105 print_kvm_segment(&sregs->ds); 106 printf(", es="); 107 print_kvm_segment(&sregs->es); 108 printf(", fs="); 109 print_kvm_segment(&sregs->fs); 110 printf(", gs="); 111 print_kvm_segment(&sregs->gs); 112 printf(", ss="); 113 print_kvm_segment(&sregs->ss); 114 printf(", tr="); 115 print_kvm_segment(&sregs->tr); 116 printf(", ldt="); 117 print_kvm_segment(&sregs->ldt); 118 printf(", gdt={base=%#jx, limit=%u}, idt={base=%#jx, limit=%u}, " 119 "cr0=%llu, cr2=%llu, cr3=%llu, cr4=%llu, cr8=%llu, efer=%llu, " 120 "apic_base=%#jx", (uintmax_t) sregs->gdt.base, sregs->gdt.limit, 121 (uintmax_t) sregs->idt.base, sregs->idt.limit, sregs->cr0, 122 sregs->cr2, sregs->cr3, sregs->cr4, sregs->cr8, sregs->efer, 123 (uintmax_t)sregs->apic_base); 124 printf(", interrupt_bitmap=["); 125 for (size_t i = 0; i < ARRAY_SIZE(sregs->interrupt_bitmap); i++) { 126 if (i) 127 printf(", "); 128 printf("%#jx", (uintmax_t) sregs->interrupt_bitmap[i]); 129 } 130 printf("]"); 131 #else 132 printf(", ..."); 133 #endif 134 printf("}"); 135 } 136 137 static void 138 print_kvm_regs(const struct kvm_regs *regs) 139 { 140 printf("{rax=%#jx", (uintmax_t) regs->rax); 141 #if VERBOSE 142 printf(", rbx=%#jx, rcx=%#jx, rdx=%#jx, rsi=%#jx, rdi=%#jx", 143 (uintmax_t) regs->rbx, (uintmax_t) regs->rcx, 144 (uintmax_t) regs->rdx, (uintmax_t) regs->rsi, 145 (uintmax_t) regs->rdi); 146 #else 147 printf(", ..."); 148 #endif 149 printf(", rsp=%#jx, rbp=%#jx", (uintmax_t) regs->rsp, 150 (uintmax_t) regs->rbp); 151 #if VERBOSE 152 printf(", r8=%#jx, r9=%#jx, r10=%#jx, r11=%#jx, r12=%#jx, r13=%#jx" 153 ", r14=%#jx, r15=%#jx", 154 (uintmax_t) regs->r8, (uintmax_t) regs->r9, 155 (uintmax_t) regs->r10, (uintmax_t) regs->r11, 156 (uintmax_t) regs->r12, (uintmax_t) regs->r13, 157 (uintmax_t) regs->r14, (uintmax_t) regs->r15); 158 #else 159 printf(", ..."); 160 #endif 161 printf(", rip=%#jx, rflags=%#jx}", (uintmax_t) regs->rip, 162 (uintmax_t) regs->rflags); 163 } 164 165 # define need_print_KVM_RUN 1 166 167 static void 168 print_KVM_RUN(const int fd, const char *const dev, const unsigned int reason); 169 170 static void 171 run_kvm(const int vcpu_fd, struct kvm_run *const run, const size_t mmap_size, 172 void *const mem) 173 { 174 /* Initialize CS to point at 0, via a read-modify-write of sregs. */ 175 struct kvm_sregs sregs; 176 KVM_IOCTL(vcpu_fd, KVM_GET_SREGS, &sregs); 177 printf("ioctl(%d<%s>, KVM_GET_SREGS, ", vcpu_fd, vcpu_dev); 178 print_kvm_sregs(&sregs); 179 printf(") = 0\n"); 180 181 sregs.cs.base = 0; 182 sregs.cs.selector = 0; 183 KVM_IOCTL(vcpu_fd, KVM_SET_SREGS, &sregs); 184 printf("ioctl(%d<%s>, KVM_SET_SREGS, ", vcpu_fd, vcpu_dev); 185 print_kvm_sregs(&sregs); 186 printf(") = 0\n"); 187 188 /* 189 * Initialize registers: instruction pointer for our code, addends, 190 * and initial flags required by x86 architecture. 191 */ 192 struct kvm_regs regs = { 193 .rip = page_size, 194 .rax = 2, 195 .rbx = 2, 196 .rflags = 0x2, 197 }; 198 KVM_IOCTL(vcpu_fd, KVM_SET_REGS, ®s); 199 printf("ioctl(%d<%s>, KVM_SET_REGS, ", vcpu_fd, vcpu_dev); 200 print_kvm_regs(®s); 201 printf(") = 0\n"); 202 203 /* Copy the code */ 204 memcpy(mem, code, code_size); 205 206 const char *p = "\n"; 207 208 /* Repeatedly run code and handle VM exits. */ 209 for (;;) { 210 KVM_IOCTL(vcpu_fd, KVM_RUN, NULL); 211 print_KVM_RUN(vcpu_fd, vcpu_dev, run->exit_reason); 212 213 switch (run->exit_reason) { 214 case KVM_EXIT_HLT: 215 if (p) 216 error_msg_and_fail("premature KVM_EXIT_HLT"); 217 return; 218 case KVM_EXIT_IO: 219 if (run->io.direction == KVM_EXIT_IO_OUT 220 && run->io.size == 1 221 && run->io.port == 0x03f8 222 && run->io.count == 1 223 && run->io.data_offset < mmap_size 224 && p && *p == ((char *) run)[run->io.data_offset]) 225 p = NULL; 226 else 227 error_msg_and_fail("unhandled KVM_EXIT_IO"); 228 break; 229 case KVM_EXIT_MMIO: 230 error_msg_and_fail("Got an unexpected MMIO exit:" 231 " phys_addr %#llx," 232 " data %02x %02x %02x %02x" 233 " %02x %02x %02x %02x," 234 " len %u, is_write %hhu", 235 (unsigned long long) run->mmio.phys_addr, 236 run->mmio.data[0], run->mmio.data[1], 237 run->mmio.data[2], run->mmio.data[3], 238 run->mmio.data[4], run->mmio.data[5], 239 run->mmio.data[6], run->mmio.data[7], 240 run->mmio.len, run->mmio.is_write); 241 242 default: 243 error_msg_and_fail("exit_reason = %#x", 244 run->exit_reason); 245 } 246 } 247 } 248 249 static int 250 vcpu_dev_should_have_cpuid(int fd) 251 { 252 int r = 0; 253 char *filename = NULL; 254 char buf[sizeof(vcpu_dev)]; 255 256 if (asprintf(&filename, "/proc/%d/fd/%d", getpid(), fd) < 0) 257 error_msg_and_fail("asprintf"); 258 259 if (readlink(filename, buf, sizeof(buf)) == sizeof(buf) - 1 260 && (memcmp(buf, vcpu_dev, sizeof(buf) - 1) == 0)) 261 r = 1; 262 free(filename); 263 return r; 264 } 265 266 static void 267 print_cpuid_ioctl(int fd, const char *fd_dev, 268 const char *ioctl_name, const struct kvm_cpuid2 *cpuid) 269 { 270 printf("ioctl(%d<%s>, %s, {nent=%u, entries=[", 271 fd, fd_dev, ioctl_name, cpuid->nent); 272 #if VERBOSE 273 for (size_t i = 0; i < cpuid->nent; i++) { 274 if (i) 275 printf(", "); 276 printf("{function=%#x, index=%#x, flags=", 277 cpuid->entries[i].function, cpuid->entries[i].index); 278 printflags(kvm_cpuid_flags, cpuid->entries[i].flags, 279 "KVM_CPUID_FLAG_???"); 280 printf(", eax=%#x, ebx=%#x, ecx=%#x, edx=%#x}", 281 cpuid->entries[i].eax, cpuid->entries[i].ebx, 282 cpuid->entries[i].ecx, cpuid->entries[i].edx); 283 } 284 #else 285 if (cpuid->nent) 286 printf("..."); 287 #endif 288 printf("]}) = 0\n"); 289 } 290 291 int 292 main(void) 293 { 294 skip_if_unavailable("/proc/self/fd/"); 295 296 int kvm = open(dev, O_RDWR); 297 if (kvm < 0) 298 perror_msg_and_skip("open: %s", dev); 299 300 /* Make sure we have the stable version of the API */ 301 int ret = KVM_IOCTL(kvm, KVM_GET_API_VERSION, 0); 302 if (ret != KVM_API_VERSION) 303 error_msg_and_skip("KVM_GET_API_VERSION returned %d" 304 ", KVM_API_VERSION is %d", 305 kvm, KVM_API_VERSION); 306 printf("ioctl(%d<%s>, KVM_GET_API_VERSION, 0) = %d\n", 307 kvm, dev, ret); 308 309 ret = KVM_IOCTL(kvm, KVM_CHECK_EXTENSION, 310 (void *) (uintptr_t) KVM_CAP_USER_MEMORY); 311 printf("ioctl(%d<%s>, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY) = %d\n", 312 kvm, dev, ret); 313 314 int vm_fd = KVM_IOCTL(kvm, KVM_CREATE_VM, 0); 315 printf("ioctl(%d<%s>, KVM_CREATE_VM, 0) = %d<%s>\n", 316 kvm, dev, vm_fd, vm_dev); 317 318 /* Allocate one aligned page of guest memory to hold the code. */ 319 page_size = get_page_size(); 320 void *const mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, 321 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 322 if (mem == MAP_FAILED) 323 perror_msg_and_fail("mmap page"); 324 325 /* Map it to the second page frame (to avoid the real-mode IDT at 0). */ 326 struct kvm_userspace_memory_region region = { 327 .slot = 0, 328 .guest_phys_addr = page_size, 329 .memory_size = page_size, 330 .userspace_addr = (uintptr_t) mem, 331 }; 332 KVM_IOCTL(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion); 333 printf("ioctl(%d<%s>, KVM_SET_USER_MEMORY_REGION" 334 ", {slot=0, flags=0, guest_phys_addr=%#lx, memory_size=%lu" 335 ", userspace_addr=%p}) = 0\n", vm_fd, vm_dev, 336 (unsigned long) page_size, (unsigned long) page_size, mem); 337 338 int vcpu_fd = KVM_IOCTL(vm_fd, KVM_CREATE_VCPU, NULL); 339 if (!vcpu_dev_should_have_cpuid(vcpu_fd)) { 340 /* 341 * This is an older kernel that doesn't place a cpuid 342 * at the end of the dentry associated with vcpu_fd. 343 * Trim the cpuid part of vcpu_dev like: 344 * "anon_inode:kvm-vcpu:0" -> "anon_inode:kvm-vcpu" 345 */ 346 vcpu_dev[strlen (vcpu_dev) - 2] = '\0'; 347 #ifdef KVM_NO_CPUID_CALLBACK 348 KVM_NO_CPUID_CALLBACK; 349 #endif 350 } 351 352 printf("ioctl(%d<%s>, KVM_CREATE_VCPU, 0) = %d<%s>\n", 353 vm_fd, vm_dev, vcpu_fd, vcpu_dev); 354 355 /* Map the shared kvm_run structure and following data. */ 356 ret = KVM_IOCTL(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); 357 struct kvm_run *run; 358 if (ret < (int) sizeof(*run)) 359 error_msg_and_fail("KVM_GET_VCPU_MMAP_SIZE returned %d < %d", 360 ret, (int) sizeof(*run)); 361 printf("ioctl(%d<%s>, KVM_GET_VCPU_MMAP_SIZE, 0) = %d\n", 362 kvm, dev, ret); 363 364 const size_t mmap_size = (ret + page_size - 1) & -page_size; 365 run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, 366 MAP_SHARED, vcpu_fd, 0); 367 if (run == MAP_FAILED) 368 perror_msg_and_fail("mmap vcpu"); 369 370 size_t cpuid_nent = KVM_MAX_CPUID_ENTRIES; 371 struct kvm_cpuid2 *cpuid = tail_alloc(sizeof(*cpuid) + 372 cpuid_nent * 373 sizeof(*cpuid->entries)); 374 375 cpuid->nent = 0; 376 ioctl(kvm, KVM_GET_SUPPORTED_CPUID, cpuid); 377 printf("ioctl(%d<%s>, KVM_GET_SUPPORTED_CPUID, %p) = -1 E2BIG (%m)\n", 378 kvm, dev, cpuid); 379 380 cpuid->nent = cpuid_nent; 381 382 KVM_IOCTL(kvm, KVM_GET_SUPPORTED_CPUID, cpuid); 383 print_cpuid_ioctl(kvm, dev, "KVM_GET_SUPPORTED_CPUID", cpuid); 384 385 struct kvm_cpuid2 cpuid_tmp = { .nent = 0 }; 386 KVM_IOCTL(vcpu_fd, KVM_SET_CPUID2, &cpuid_tmp); 387 printf("ioctl(%d<%s>, KVM_SET_CPUID2, {nent=%u, entries=[]}) = 0\n", 388 vcpu_fd, vcpu_dev, cpuid_tmp.nent); 389 390 KVM_IOCTL(vcpu_fd, KVM_SET_CPUID2, cpuid); 391 print_cpuid_ioctl(vcpu_fd, vcpu_dev, "KVM_SET_CPUID2", cpuid); 392 393 ioctl(vcpu_fd, KVM_SET_CPUID2, NULL); 394 printf("ioctl(%d<%s>, KVM_SET_CPUID2, NULL) = -1 EFAULT (%m)\n", 395 vcpu_fd, vcpu_dev); 396 397 run_kvm(vcpu_fd, run, mmap_size, mem); 398 399 puts("+++ exited with 0 +++"); 400 return 0; 401 } 402 403 #else /* !HAVE_LINUX_KVM_H */ 404 405 SKIP_MAIN_UNDEFINED("HAVE_LINUX_KVM_H && HAVE_STRUCT_KVM_CPUID2 && " 406 "HAVE_STRUCT_KVM_REGS && HAVE_STRUCT_KVM_SREGS && " 407 "HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION && " 408 "(__x86_64__ || __i386__)") 409 410 # define need_print_KVM_RUN 0 411 412 #endif 413