Virtualize the current logical processor:
| 471 | |
| 472 | // Virtualize the current logical processor: |
| 473 | static bool VirtualizeProcessor() |
| 474 | { |
| 475 | using namespace PhysicalMemory; |
| 476 | |
| 477 | static volatile bool IsVirtualized = false; |
| 478 | IsVirtualized = false; |
| 479 | |
| 480 | CONTEXT Context = {}; |
| 481 | Context.ContextFlags = CONTEXT_ALL; |
| 482 | RtlCaptureContext(&Context); |
| 483 | |
| 484 | if (IsVirtualized) return true; |
| 485 | |
| 486 | // Enable the SVM by setting up the EFER.SVME bit: |
| 487 | EFER Efer = {}; |
| 488 | Efer.Value = __readmsr(static_cast<unsigned long>(AMD_MSR::MSR_EFER)); |
| 489 | Efer.Bitmap.SecureVirtualMachineEnable = TRUE; |
| 490 | __writemsr(static_cast<unsigned long>(AMD_MSR::MSR_EFER), Efer.Value); |
| 491 | |
| 492 | PRIVATE_VM_DATA* Private = reinterpret_cast<PRIVATE_VM_DATA*>(AllocPhys(sizeof(*Private))); |
| 493 | |
| 494 | // Interceptions: |
| 495 | Private->Guest.ControlArea.InterceptCpuid = TRUE; |
| 496 | Private->Guest.ControlArea.InterceptVmrun = TRUE; |
| 497 | Private->Guest.ControlArea.InterceptMsr = TRUE; |
| 498 | Private->Guest.ControlArea.MsrpmBasePa = reinterpret_cast<UINT64>(GetPhysicalAddress(&Private->Msrpm)); |
| 499 | |
| 500 | // Guest Address Space ID: |
| 501 | Private->Guest.ControlArea.GuestAsid = 1; |
| 502 | |
| 503 | // Nested paging: |
| 504 | BuildNestedPagingTables(&Private->Npt); |
| 505 | Private->Guest.ControlArea.NpEnable = TRUE; |
| 506 | Private->Guest.ControlArea.NestedPageTableCr3 = reinterpret_cast<UINT64>(GetPhysicalAddress(&Private->Npt.Pml4e)); |
| 507 | |
| 508 | DESCRIPTOR_TABLE_REGISTER_LONG Gdtr = {}, Idtr = {}; |
| 509 | _sgdt(&Gdtr); |
| 510 | __sidt(&Idtr); |
| 511 | |
| 512 | // Setting up the initial guest state to the current system state: |
| 513 | Private->Guest.StateSaveArea.Gdtr.Base = Gdtr.BaseAddress; |
| 514 | Private->Guest.StateSaveArea.Gdtr.Limit = Gdtr.Limit; |
| 515 | Private->Guest.StateSaveArea.Idtr.Base = Idtr.BaseAddress; |
| 516 | Private->Guest.StateSaveArea.Idtr.Limit = Idtr.Limit; |
| 517 | |
| 518 | Private->Guest.StateSaveArea.Cs.Limit = GetSegmentLimit(Context.SegCs); |
| 519 | Private->Guest.StateSaveArea.Ds.Limit = GetSegmentLimit(Context.SegDs); |
| 520 | Private->Guest.StateSaveArea.Es.Limit = GetSegmentLimit(Context.SegEs); |
| 521 | Private->Guest.StateSaveArea.Ss.Limit = GetSegmentLimit(Context.SegSs); |
| 522 | |
| 523 | Private->Guest.StateSaveArea.Cs.Selector = Context.SegCs; |
| 524 | Private->Guest.StateSaveArea.Ds.Selector = Context.SegDs; |
| 525 | Private->Guest.StateSaveArea.Es.Selector = Context.SegEs; |
| 526 | Private->Guest.StateSaveArea.Ss.Selector = Context.SegSs; |
| 527 | |
| 528 | FillVmcbSegmentAttributes(&Private->Guest.StateSaveArea.Cs.Attrib, reinterpret_cast<const SEGMENT_SELECTOR*>(&Context.SegCs), &Gdtr); |
| 529 | FillVmcbSegmentAttributes(&Private->Guest.StateSaveArea.Ds.Attrib, reinterpret_cast<const SEGMENT_SELECTOR*>(&Context.SegDs), &Gdtr); |
| 530 | FillVmcbSegmentAttributes(&Private->Guest.StateSaveArea.Es.Attrib, reinterpret_cast<const SEGMENT_SELECTOR*>(&Context.SegEs), &Gdtr); |
no test coverage detected