1 /*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include "opt_ddb.h" 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/pcpu.h> 37 38 #include <vm/vm.h> 39 #include <vm/pmap.h> 40 41 #include <machine/segments.h> 42 #include <machine/vmm.h> 43 #include "vmm_host.h" 44 #include "vmx_cpufunc.h" 45 #include "vmcs.h" 46 #include "ept.h" 47 #include "vmx.h" 48 49 #ifdef DDB 50 #include <ddb/ddb.h> 51 #endif 52 53 static uint64_t 54 vmcs_fix_regval(uint32_t encoding, uint64_t val) 55 { 56 57 switch (encoding) { 58 case VMCS_GUEST_CR0: 59 val = vmx_fix_cr0(val); 60 break; 61 case VMCS_GUEST_CR4: 62 val = vmx_fix_cr4(val); 63 break; 64 default: 65 break; 66 } 67 return (val); 68 } 69 70 static uint32_t 71 vmcs_field_encoding(int ident) 72 { 73 switch (ident) { 74 case VM_REG_GUEST_CR0: 75 return (VMCS_GUEST_CR0); 76 case VM_REG_GUEST_CR3: 77 return (VMCS_GUEST_CR3); 78 case VM_REG_GUEST_CR4: 79 return (VMCS_GUEST_CR4); 80 case VM_REG_GUEST_DR7: 81 return (VMCS_GUEST_DR7); 82 case VM_REG_GUEST_RSP: 83 return (VMCS_GUEST_RSP); 84 case VM_REG_GUEST_RIP: 85 return (VMCS_GUEST_RIP); 86 case VM_REG_GUEST_RFLAGS: 87 return (VMCS_GUEST_RFLAGS); 88 case VM_REG_GUEST_ES: 89 return (VMCS_GUEST_ES_SELECTOR); 90 case VM_REG_GUEST_CS: 91 return (VMCS_GUEST_CS_SELECTOR); 92 case VM_REG_GUEST_SS: 93 return (VMCS_GUEST_SS_SELECTOR); 94 case VM_REG_GUEST_DS: 95 return (VMCS_GUEST_DS_SELECTOR); 96 case VM_REG_GUEST_FS: 97 return (VMCS_GUEST_FS_SELECTOR); 98 case VM_REG_GUEST_GS: 99 return (VMCS_GUEST_GS_SELECTOR); 100 case VM_REG_GUEST_TR: 101 return (VMCS_GUEST_TR_SELECTOR); 102 case VM_REG_GUEST_LDTR: 103 return (VMCS_GUEST_LDTR_SELECTOR); 104 case VM_REG_GUEST_EFER: 105 return (VMCS_GUEST_IA32_EFER); 106 case VM_REG_GUEST_PDPTE0: 107 return (VMCS_GUEST_PDPTE0); 108 case VM_REG_GUEST_PDPTE1: 109 return (VMCS_GUEST_PDPTE1); 110 case VM_REG_GUEST_PDPTE2: 111 return (VMCS_GUEST_PDPTE2); 112 case VM_REG_GUEST_PDPTE3: 113 return (VMCS_GUEST_PDPTE3); 114 default: 115 return (-1); 116 } 117 118 } 119 120 static int 121 vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 122 { 123 124 switch (seg) { 125 case VM_REG_GUEST_ES: 126 *base = VMCS_GUEST_ES_BASE; 127 *lim = VMCS_GUEST_ES_LIMIT; 128 *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 129 break; 130 case VM_REG_GUEST_CS: 131 *base = VMCS_GUEST_CS_BASE; 132 *lim = VMCS_GUEST_CS_LIMIT; 133 *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 134 break; 135 case VM_REG_GUEST_SS: 136 *base = VMCS_GUEST_SS_BASE; 137 *lim = VMCS_GUEST_SS_LIMIT; 138 *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 139 break; 140 case VM_REG_GUEST_DS: 141 *base = VMCS_GUEST_DS_BASE; 142 *lim = VMCS_GUEST_DS_LIMIT; 143 *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 144 break; 145 case VM_REG_GUEST_FS: 146 *base = VMCS_GUEST_FS_BASE; 147 *lim = VMCS_GUEST_FS_LIMIT; 148 *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 149 break; 150 case VM_REG_GUEST_GS: 151 *base = VMCS_GUEST_GS_BASE; 152 *lim = VMCS_GUEST_GS_LIMIT; 153 *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 154 break; 155 case VM_REG_GUEST_TR: 156 *base = VMCS_GUEST_TR_BASE; 157 *lim = VMCS_GUEST_TR_LIMIT; 158 *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 159 break; 160 case VM_REG_GUEST_LDTR: 161 *base = VMCS_GUEST_LDTR_BASE; 162 *lim = VMCS_GUEST_LDTR_LIMIT; 163 *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 164 break; 165 case VM_REG_GUEST_IDTR: 166 *base = VMCS_GUEST_IDTR_BASE; 167 *lim = VMCS_GUEST_IDTR_LIMIT; 168 *acc = VMCS_INVALID_ENCODING; 169 break; 170 case VM_REG_GUEST_GDTR: 171 *base = VMCS_GUEST_GDTR_BASE; 172 *lim = VMCS_GUEST_GDTR_LIMIT; 173 *acc = VMCS_INVALID_ENCODING; 174 break; 175 default: 176 return (EINVAL); 177 } 178 179 return (0); 180 } 181 182 int 183 vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 184 { 185 int error; 186 uint32_t encoding; 187 188 /* 189 * If we need to get at vmx-specific state in the VMCS we can bypass 190 * the translation of 'ident' to 'encoding' by simply setting the 191 * sign bit. As it so happens the upper 16 bits are reserved (i.e 192 * set to 0) in the encodings for the VMCS so we are free to use the 193 * sign bit. 194 */ 195 if (ident < 0) 196 encoding = ident & 0x7fffffff; 197 else 198 encoding = vmcs_field_encoding(ident); 199 200 if (encoding == (uint32_t)-1) 201 return (EINVAL); 202 203 if (!running) 204 VMPTRLD(vmcs); 205 206 error = vmread(encoding, retval); 207 208 if (!running) 209 VMCLEAR(vmcs); 210 211 return (error); 212 } 213 214 int 215 vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 216 { 217 int error; 218 uint32_t encoding; 219 220 if (ident < 0) 221 encoding = ident & 0x7fffffff; 222 else 223 encoding = vmcs_field_encoding(ident); 224 225 if (encoding == (uint32_t)-1) 226 return (EINVAL); 227 228 val = vmcs_fix_regval(encoding, val); 229 230 if (!running) 231 VMPTRLD(vmcs); 232 233 error = vmwrite(encoding, val); 234 235 if (!running) 236 VMCLEAR(vmcs); 237 238 return (error); 239 } 240 241 int 242 vmcs_setdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 243 { 244 int error; 245 uint32_t base, limit, access; 246 247 error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 248 if (error != 0) 249 panic("vmcs_setdesc: invalid segment register %d", seg); 250 251 if (!running) 252 VMPTRLD(vmcs); 253 if ((error = vmwrite(base, desc->base)) != 0) 254 goto done; 255 256 if ((error = vmwrite(limit, desc->limit)) != 0) 257 goto done; 258 259 if (access != VMCS_INVALID_ENCODING) { 260 if ((error = vmwrite(access, desc->access)) != 0) 261 goto done; 262 } 263 done: 264 if (!running) 265 VMCLEAR(vmcs); 266 return (error); 267 } 268 269 int 270 vmcs_getdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 271 { 272 int error; 273 uint32_t base, limit, access; 274 uint64_t u64; 275 276 error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 277 if (error != 0) 278 panic("vmcs_getdesc: invalid segment register %d", seg); 279 280 if (!running) 281 VMPTRLD(vmcs); 282 if ((error = vmread(base, &u64)) != 0) 283 goto done; 284 desc->base = u64; 285 286 if ((error = vmread(limit, &u64)) != 0) 287 goto done; 288 desc->limit = u64; 289 290 if (access != VMCS_INVALID_ENCODING) { 291 if ((error = vmread(access, &u64)) != 0) 292 goto done; 293 desc->access = u64; 294 } 295 done: 296 if (!running) 297 VMCLEAR(vmcs); 298 return (error); 299 } 300 301 int 302 vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 303 { 304 int error; 305 306 VMPTRLD(vmcs); 307 308 /* 309 * Guest MSRs are saved in the VM-exit MSR-store area. 310 * Guest MSRs are loaded from the VM-entry MSR-load area. 311 * Both areas point to the same location in memory. 312 */ 313 if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 314 goto done; 315 if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 316 goto done; 317 318 if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 319 goto done; 320 if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 321 goto done; 322 323 error = 0; 324 done: 325 VMCLEAR(vmcs); 326 return (error); 327 } 328 329 int 330 vmcs_init(struct vmcs *vmcs) 331 { 332 int error, codesel, datasel, tsssel; 333 u_long cr0, cr4, efer; 334 uint64_t pat, fsbase, idtrbase; 335 336 codesel = vmm_get_host_codesel(); 337 datasel = vmm_get_host_datasel(); 338 tsssel = vmm_get_host_tsssel(); 339 340 /* 341 * Make sure we have a "current" VMCS to work with. 342 */ 343 VMPTRLD(vmcs); 344 345 /* Host state */ 346 347 /* Initialize host IA32_PAT MSR */ 348 pat = vmm_get_host_pat(); 349 if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 350 goto done; 351 352 /* Load the IA32_EFER MSR */ 353 efer = vmm_get_host_efer(); 354 if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 355 goto done; 356 357 /* Load the control registers */ 358 359 cr0 = vmm_get_host_cr0(); 360 if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 361 goto done; 362 363 cr4 = vmm_get_host_cr4() | CR4_VMXE; 364 if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 365 goto done; 366 367 /* Load the segment selectors */ 368 if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 369 goto done; 370 371 if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 372 goto done; 373 374 if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 375 goto done; 376 377 if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 378 goto done; 379 380 if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 381 goto done; 382 383 if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 384 goto done; 385 386 if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 387 goto done; 388 389 /* 390 * Load the Base-Address for %fs and idtr. 391 * 392 * Note that we exclude %gs, tss and gdtr here because their base 393 * address is pcpu specific. 394 */ 395 fsbase = vmm_get_host_fsbase(); 396 if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 397 goto done; 398 399 idtrbase = vmm_get_host_idtrbase(); 400 if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 401 goto done; 402 403 /* instruction pointer */ 404 if ((error = vmwrite(VMCS_HOST_RIP, (u_long)vmx_exit_guest)) != 0) 405 goto done; 406 407 /* link pointer */ 408 if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 409 goto done; 410 done: 411 VMCLEAR(vmcs); 412 return (error); 413 } 414 415 #ifdef DDB 416 extern int vmxon_enabled[]; 417 418 DB_SHOW_COMMAND(vmcs, db_show_vmcs) 419 { 420 uint64_t cur_vmcs, val; 421 uint32_t exit; 422 423 if (!vmxon_enabled[curcpu]) { 424 db_printf("VMX not enabled\n"); 425 return; 426 } 427 428 if (have_addr) { 429 db_printf("Only current VMCS supported\n"); 430 return; 431 } 432 433 vmptrst(&cur_vmcs); 434 if (cur_vmcs == VMCS_INITIAL) { 435 db_printf("No current VM context\n"); 436 return; 437 } 438 db_printf("VMCS: %jx\n", cur_vmcs); 439 db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 440 db_printf("Activity: "); 441 val = vmcs_read(VMCS_GUEST_ACTIVITY); 442 switch (val) { 443 case 0: 444 db_printf("Active"); 445 break; 446 case 1: 447 db_printf("HLT"); 448 break; 449 case 2: 450 db_printf("Shutdown"); 451 break; 452 case 3: 453 db_printf("Wait for SIPI"); 454 break; 455 default: 456 db_printf("Unknown: %#lx", val); 457 } 458 db_printf("\n"); 459 exit = vmcs_read(VMCS_EXIT_REASON); 460 if (exit & 0x80000000) 461 db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 462 else 463 db_printf("Exit Reason: %u\n", exit & 0xffff); 464 db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 465 db_printf("Guest Linear Address: %#lx\n", 466 vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 467 switch (exit & 0x8000ffff) { 468 case EXIT_REASON_EXCEPTION: 469 case EXIT_REASON_EXT_INTR: 470 val = vmcs_read(VMCS_EXIT_INTR_INFO); 471 db_printf("Interrupt Type: "); 472 switch (val >> 8 & 0x7) { 473 case 0: 474 db_printf("external"); 475 break; 476 case 2: 477 db_printf("NMI"); 478 break; 479 case 3: 480 db_printf("HW exception"); 481 break; 482 case 4: 483 db_printf("SW exception"); 484 break; 485 default: 486 db_printf("?? %lu", val >> 8 & 0x7); 487 break; 488 } 489 db_printf(" Vector: %lu", val & 0xff); 490 if (val & 0x800) 491 db_printf(" Error Code: %lx", 492 vmcs_read(VMCS_EXIT_INTR_ERRCODE)); 493 db_printf("\n"); 494 break; 495 case EXIT_REASON_EPT_FAULT: 496 case EXIT_REASON_EPT_MISCONFIG: 497 db_printf("Guest Physical Address: %#lx\n", 498 vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 499 break; 500 } 501 db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 502 } 503 #endif 504