Changeset 46365 in vbox
- Timestamp:
- Jun 3, 2013 3:02:41 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r46310 r46365 25 25 #endif 26 26 27 28 /******************************************************************************* 29 * Defined Constants And Macros * 30 *******************************************************************************/ 31 32 /** 33 * MSR-bitmap read permissions. 34 */ 35 typedef enum SVMMSREXITREAD 36 { 37 /** Reading this MSR causes a VM-exit. */ 38 SVMMSREXIT_INTERCEPT_READ = 0xb, 39 /** Reading this MSR does not cause a VM-exit. */ 40 SVMMSREXIT_PASSTHRU_READ 41 } VMXMSREXITREAD; 42 43 /** 44 * MSR-bitmap write permissions. 45 */ 46 typedef enum SVMMSREXITWRITE 47 { 48 /** Writing to this MSR causes a VM-exit. */ 49 SVMMSREXIT_INTERCEPT_WRITE = 0xd, 50 /** Writing to this MSR does not cause a VM-exit. */ 51 SVMMSREXIT_PASSTHRU_WRITE 52 } VMXMSREXITWRITE; 53 54 27 55 /******************************************************************************* 28 56 * Internal Functions * 29 57 *******************************************************************************/ 30 31 32 /******************************************************************************* 33 * Defined Constants And Macros * 34 *******************************************************************************/ 58 static void hmR0SvmSetMSRPermission(PVMCPU pVCpu, unsigned uMsr, SVMMSREXITREAD enmRead, SVMMSREXITWRITE enmWrite); 35 59 36 60 … … 305 329 Assert(pVM->hm.s.svm.fSupported); 306 330 307 for ( uint32_ti = 0; i < pVM->cCpus; i++)331 for (VMCPUID i = 0; i < pVM->cCpus; i++) 308 332 { 309 333 PVMCPU pVCpu = &pVM->aCpus[i]; … … 312 336 AssertMsgReturn(pVmcb, ("Invalid pVmcb\n"), VERR_SVM_INVALID_PVMCB); 313 337 314 /* Intercept traps. */338 /* Trap exceptions unconditionally (debug purposes). */ 315 339 #ifdef HMSVM_ALWAYS_TRAP_PF 316 340 pVmcb->ctrl.u32InterceptException |= RT_BIT(X86_XCPT_PF); … … 320 344 | RT_BIT(X86_XCPT_DB) 321 345 | RT_BIT(X86_XCPT_DE) 346 | RT_BIT(X86_XCPT_NM) 322 347 | RT_BIT(X86_XCPT_UD) 323 348 | RT_BIT(X86_XCPT_NP) 324 349 | RT_BIT(X86_XCPT_SS) 325 350 | RT_BIT(X86_XCPT_GP) 326 | RT_BIT(X86_XCPT_ MF)327 | RT_BIT(X86_XCPT_ PF);351 | RT_BIT(X86_XCPT_PF) 352 | RT_BIT(X86_XCPT_MF); 328 353 #endif 329 354 330 /* -XXX- todo. */ 355 /* Set up unconditional intercepts and conditions. */ 356 pVmcb->ctrl.u32InterceptCtrl1 = SVM_CTRL1_INTERCEPT_INTR /* External interrupt causes a VM-exit. */ 357 | SVM_CTRL1_INTERCEPT_VINTR /* When guest enabled interrupts cause a VM-exit. */ 358 | SVM_CTRL1_INTERCEPT_NMI /* Non-Maskable Interrupts causes a VM-exit. */ 359 | SVM_CTRL1_INTERCEPT_SMI /* System Management Interrupt cause a VM-exit. */ 360 | SVM_CTRL1_INTERCEPT_INIT /* INIT signal causes a VM-exit. */ 361 | SVM_CTRL1_INTERCEPT_RDPMC /* RDPMC causes a VM-exit. */ 362 | SVM_CTRL1_INTERCEPT_CPUID /* CPUID causes a VM-exit. */ 363 | SVM_CTRL1_INTERCEPT_RSM /* RSM causes a VM-exit. */ 364 | SVM_CTRL1_INTERCEPT_HLT /* HLT causes a VM-exit. */ 365 | SVM_CTRL1_INTERCEPT_INOUT_BITMAP /* Use the IOPM to cause IOIO VM-exits. */ 366 | SVM_CTRL1_INTERCEPT_MSR_SHADOW /* MSR access not covered by MSRPM causes a VM-exit.*/ 367 | SVM_CTRL1_INTERCEPT_INVLPGA /* INVLPGA causes a VM-exit. */ 368 | SVM_CTRL1_INTERCEPT_SHUTDOWN /* Shutdown events causes a VM-exit. */ 369 | SVM_CTRL1_INTERCEPT_FERR_FREEZE; /* Intercept "freezing" during legacy FPU handling. */ 370 371 pVmcb->ctrl.u32InterceptCtrl2 = SVM_CTRL2_INTERCEPT_VMRUN /* VMRUN causes a VM-exit. */ 372 | SVM_CTRL2_INTERCEPT_VMMCALL /* VMMCALL causes a VM-exit. */ 373 | SVM_CTRL2_INTERCEPT_VMLOAD /* VMLOAD causes a VM-exit. */ 374 | SVM_CTRL2_INTERCEPT_VMSAVE /* VMSAVE causes a VM-exit. */ 375 | SVM_CTRL2_INTERCEPT_STGI /* STGI causes a VM-exit. */ 376 | SVM_CTRL2_INTERCEPT_CLGI /* CLGI causes a VM-exit. */ 377 | SVM_CTRL2_INTERCEPT_SKINIT /* SKINIT causes a VM-exit. */ 378 | SVM_CTRL2_INTERCEPT_WBINVD /* WBINVD causes a VM-exit. */ 379 | SVM_CTRL2_INTERCEPT_MONITOR /* MONITOR causes a VM-exit. */ 380 | SVM_CTRL2_INTERCEPT_MWAIT_UNCOND; /* MWAIT causes a VM-exit. */ 381 382 /* CR0, CR4 reads must be intercepted, our shadow values are not necessarily the same as the guest's. */ 383 pVmcb->ctrl.u16InterceptRdCRx = RT_BIT(0) | RT_BIT(4); 384 385 /* CR0, CR4 writes must be intercepted for obvious reasons. */ 386 pVmcb->ctrl.u16InterceptWrCRx = RT_BIT(0) | RT_BIT(4); 387 388 /* Intercept all DRx reads and writes by default. Changed later on. */ 389 pVmcb->ctrl.u16InterceptRdDRx = 0xffff; 390 pVmcb->ctrl.u16InterceptWrDRx = 0xffff; 391 392 /* Virtualize masking of INTR interrupts. (reads/writes from/to CR8 go to the V_TPR register) */ 393 pVmcb->ctrl.IntCtrl.n.u1VIrqMasking = 1; 394 395 /* Ignore the priority in the TPR; just deliver it to the guest when we tell it to. */ 396 pVmcb->ctrl.IntCtrl.n.u1IgnoreTPR = 1; 397 398 /* Set IO and MSR bitmap permission bitmap physical addresses. */ 399 pVmcb->ctrl.u64IOPMPhysAddr = g_HCPhysIOBitmap; 400 pVmcb->ctrl.u64MSRPMPhysAddr = pVCpu->hm.s.svm.HCPhysMsrBitmap; 401 402 /* No LBR virtualization. */ 403 pVmcb->ctrl.u64LBRVirt = 0; 404 405 /* The ASID must start at 1; the host uses 0. */ 406 pVmcb->ctrl.TLBCtrl.n.u32ASID = 1; 407 408 /* 409 * Setup the PAT MSR (applicable for Nested Paging only). 410 * The default value should be 0x0007040600070406ULL, but we want to treat all guest memory as WB, 411 * so choose type 6 for all PAT slots. 412 */ 413 pVmcb->guest.u64GPAT = UINT64_C(0x0006060606060606); 414 415 /* Without Nested Paging, we need additionally intercepts. */ 416 if (!pVM->hm.s.fNestedPaging) 417 { 418 /* CR3 reads/writes must be intercepted; our shadow values differ from the guest values. */ 419 pVmcb->ctrl.u16InterceptRdCRx |= RT_BIT(3); 420 pVmcb->ctrl.u16InterceptWrCRx |= RT_BIT(3); 421 422 /* Intercept INVLPG and task switches (may change CR3, EFLAGS, LDT). */ 423 pVmcb->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_INVLPG 424 | SVM_CTRL1_INTERCEPT_TASK_SWITCH; 425 426 /* Page faults must be intercepted to implement shadow paging. */ 427 pVmcb->ctrl.u32InterceptException |= RT_BIT(X86_XCPT_PF); 428 } 429 430 /* 431 * The following MSRs are saved/restored automatically during the world-switch. 432 * Don't intercept guest read/write accesses to these MSRs. 433 */ 434 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_LSTAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 435 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_CSTAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 436 hmR0SvmSetMSRPermission(pVCpu, MSR_K6_STAR, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 437 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_SF_MASK, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 438 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_FS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 439 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_GS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 440 hmR0SvmSetMSRPermission(pVCpu, MSR_K8_KERNEL_GS_BASE, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 441 hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_CS, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 442 hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_ESP, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 443 hmR0SvmSetMSRPermission(pVCpu, MSR_IA32_SYSENTER_EIP, SVMMSREXIT_PASSTHRU_READ, SVMMSREXIT_PASSTHRU_WRITE); 331 444 } 332 445 … … 334 447 } 335 448 449 450 /** 451 * Sets the permission bits for the specified MSR. 452 * 453 * @param pVCpu Pointer to the VMCPU. 454 * @param uMsr The MSR. 455 * @param fRead Whether reading is allowed. 456 * @param fWrite Whether writing is allowed. 457 */ 458 static void hmR0SvmSetMSRPermission(PVMCPU pVCpu, uint32_t uMsr, SVMMSREXITREAD enmRead, SVMMSREXITWRITE enmWrite) 459 { 460 unsigned ulBit; 461 uint8_t *pbMsrBitmap = (uint8_t *)pVCpu->hm.s.svm.pvMsrBitmap; 462 463 /* 464 * Layout: 465 * Byte offset MSR range 466 * 0x000 - 0x7ff 0x00000000 - 0x00001fff 467 * 0x800 - 0xfff 0xc0000000 - 0xc0001fff 468 * 0x1000 - 0x17ff 0xc0010000 - 0xc0011fff 469 * 0x1800 - 0x1fff Reserved 470 */ 471 if (uMsr <= 0x00001FFF) 472 { 473 /* Pentium-compatible MSRs */ 474 ulBit = uMsr * 2; 475 } 476 else if ( uMsr >= 0xC0000000 477 && uMsr <= 0xC0001FFF) 478 { 479 /* AMD Sixth Generation x86 Processor MSRs and SYSCALL */ 480 ulBit = (uMsr - 0xC0000000) * 2; 481 pbMsrBitmap += 0x800; 482 } 483 else if ( uMsr >= 0xC0010000 484 && uMsr <= 0xC0011FFF) 485 { 486 /* AMD Seventh and Eighth Generation Processor MSRs */ 487 ulBit = (uMsr - 0xC0001000) * 2; 488 pbMsrBitmap += 0x1000; 489 } 490 else 491 { 492 AssertFailed(); 493 return; 494 } 495 496 Assert(ulBit < 0x3fff /* 16 * 1024 - 1 */); 497 if (enmRead == SVMMSREXIT_INTERCEPT_READ) 498 ASMBitSet(pbMsrBitmap, ulBit); 499 else 500 ASMBitClear(pbMsrBitmap, ulBit); 501 502 if (enmWrite == SVMMSREXIT_INTERCEPT_WRITE) 503 ASMBitSet(pbMsrBitmap, ulBit + 1); 504 else 505 ASMBitClear(pbMsrBitmap, ulBit + 1); 506 } 507
Note:
See TracChangeset
for help on using the changeset viewer.