Changeset 63648 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Aug 26, 2016 11:44:40 AM (8 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/GIM.cpp
r62641 r63648 347 347 } 348 348 return VINF_SUCCESS; 349 } 350 351 352 /** 353 * Applies relocations to data and code managed by this 354 * component. This function will be called at init and 355 * whenever the VMM need to relocate it self inside the GC. 356 * 357 * @param pVM The cross context VM structure. 358 * @param offDelta Relocation delta relative to old location. 359 */ 360 VMMR3_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta) 361 { 362 switch (pVM->gim.s.enmProviderId) 363 { 364 case GIMPROVIDERID_HYPERV: 365 gimR3HvRelocate(pVM, offDelta); 366 break; 367 368 default: 369 break; 370 } 349 371 } 350 372 -
trunk/src/VBox/VMM/VMMR3/GIMHv.cpp
r62642 r63648 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_GIM 23 #include <VBox/vmm/apic.h> 23 24 #include <VBox/vmm/gim.h> 24 25 #include <VBox/vmm/cpum.h> … … 49 50 * GIM Hyper-V saved-state version. 50 51 */ 51 #define GIM_HV_SAVED_STATE_VERSION UINT32_C(2) 52 #define GIM_HV_SAVED_STATE_VERSION UINT32_C(3) 53 /** Saved states, prior to any synthetic interrupt controller support. */ 54 #define GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC UINT32_C(2) 52 55 /** Vanilla saved states, prior to any debug support. */ 53 56 #define GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG UINT32_C(1) … … 180 183 static void gimR3HvTermHypercallSupport(PVM pVM); 181 184 static int gimR3HvInitDebugSupport(PVM pVM); 182 #if 0 /** @todo currently unused, which is probably very wrong */183 185 static void gimR3HvTermDebugSupport(PVM pVM); 184 #endif 185 186 static DECLCALLBACK(void) gimR3HvTimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser); 186 187 187 188 /** … … 197 198 AssertReturn(pVM->gim.s.enmProviderId == GIMPROVIDERID_HYPERV, VERR_INTERNAL_ERROR_5); 198 199 199 int rc;200 200 PGIMHV pHv = &pVM->gim.s.u.Hv; 201 201 … … 209 209 * Validate the Hyper-V settings. 210 210 */ 211 rc= CFGMR3ValidateConfig(pCfgHv, "/HyperV/",211 int rc2 = CFGMR3ValidateConfig(pCfgHv, "/HyperV/", 212 212 "VendorID" 213 213 "|VSInterface" 214 214 "|HypercallDebugInterface", 215 215 "" /* pszValidNodes */, "GIM/HyperV" /* pszWho */, 0 /* uInstance */); 216 if (RT_FAILURE(rc ))217 return rc ;216 if (RT_FAILURE(rc2)) 217 return rc2; 218 218 } 219 219 … … 221 221 * The Hyper-V vendor signature, must be 12 characters. */ 222 222 char szVendor[13]; 223 rc = CFGMR3QueryStringDef(pCfgHv, "VendorID", szVendor, sizeof(szVendor), "VBoxVBoxVBox");223 int rc = CFGMR3QueryStringDef(pCfgHv, "VendorID", szVendor, sizeof(szVendor), "VBoxVBoxVBox"); 224 224 AssertLogRelRCReturn(rc, rc); 225 225 AssertLogRelMsgReturn(strlen(szVendor) == 12, … … 255 255 //| GIM_HV_BASE_FEAT_VP_RUNTIME_MSR 256 256 | GIM_HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR 257 //| GIM_HV_BASE_FEAT_BASIC_SYN TH_IC258 //| GIM_HV_BASE_FEAT_S YNTH_TIMER_MSRS257 //| GIM_HV_BASE_FEAT_BASIC_SYNIC_MSRS 258 //| GIM_HV_BASE_FEAT_STIMER_MSRS 259 259 | GIM_HV_BASE_FEAT_APIC_ACCESS_MSRS 260 260 | GIM_HV_BASE_FEAT_HYPERCALL_MSRS … … 279 279 /* Hypervisor recommendations to the guest. */ 280 280 pHv->uHyperHints = GIM_HV_HINT_MSR_FOR_SYS_RESET 281 | GIM_HV_HINT_RELAX_TIME_CHECKS; 281 | GIM_HV_HINT_RELAX_TIME_CHECKS 282 //| GIM_HV_HINT_X2APIC_MSRS 283 ; 282 284 283 285 /* Expose more if we're posing as Microsoft. We can, if needed, force MSR-based Hv … … 347 349 RT_ZERO(HyperLeaf); 348 350 HyperLeaf.uLeaf = UINT32_C(0x40000000); 349 HyperLeaf.uEax = UINT32_C(0x40000006); /* Minimum value for Hyper-V is 0x40000005. */ 351 if ( pHv->fIsVendorMsHv 352 && pHv->fIsInterfaceVs) 353 HyperLeaf.uEax = UINT32_C(0x40000082); /* Since we expose 0x40000082 below for the Hyper-V PV-debugging case. */ 354 else 355 HyperLeaf.uEax = UINT32_C(0x40000006); /* Minimum value for Hyper-V default is 0x40000005. */ 350 356 /* 351 357 * Don't report vendor as 'Microsoft Hv'[1] by default, see @bugref{7270#c152}. … … 404 410 AssertLogRelRCReturn(rc, rc); 405 411 412 RT_ZERO(HyperLeaf); 413 HyperLeaf.uLeaf = UINT32_C(0x40000005); 414 rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf); 415 AssertLogRelRCReturn(rc, rc); 416 417 /* Leaf 0x40000006 is inserted in gimR3HvInitCompleted(). */ 418 406 419 if ( pHv->fIsVendorMsHv 407 420 && pHv->fIsInterfaceVs) … … 437 450 for (unsigned i = 0; i < RT_ELEMENTS(g_aMsrRanges_HyperV); i++) 438 451 { 439 rc= CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_HyperV[i]);440 AssertLogRelRCReturn(rc , rc);452 int rc2 = CPUMR3MsrRangesInsert(pVM, &g_aMsrRanges_HyperV[i]); 453 AssertLogRelRCReturn(rc2, rc2); 441 454 } 442 455 … … 449 462 { 450 463 PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu; 451 for ( size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintXMsr); idxSintMsr++)452 pHvCpu->auSint XMsr[idxSintMsr] = MSR_GIM_HV_SINT_MASKED;464 for (uint8_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++) 465 pHvCpu->auSintMsrs[idxSintMsr] = MSR_GIM_HV_SINT_MASKED; 453 466 } 454 467 … … 464 477 rc = gimR3HvInitDebugSupport(pVM); 465 478 AssertLogRelRCReturn(rc, rc); 479 480 /* 481 * Setup up the per-VCPU synthetic timers. 482 */ 483 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 484 { 485 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 486 PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu; 487 488 for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++) 489 { 490 PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer]; 491 492 /* Associate the synthetic timer with its corresponding VCPU. */ 493 pHvStimer->idCpu = pVCpu->idCpu; 494 pHvStimer->idxStimer = idxStimer; 495 496 /* Create the timer and associate the context pointers. */ 497 RTStrPrintf(&pHvStimer->szTimerDesc[0], sizeof(pHvStimer->szTimerDesc), "Hyper-V[%u] Timer%u", pVCpu->idCpu, 498 idxStimer); 499 rc = TMR3TimerCreateInternal(pVM, TMCLOCK_VIRTUAL_SYNC, gimR3HvTimerCallback, pHvStimer /* pvUser */, 500 pHvStimer->szTimerDesc, &pHvStimer->pTimerR3); 501 AssertLogRelRCReturn(rc, rc); 502 pHvStimer->pTimerR0 = TMTimerR0Ptr(pHvStimer->pTimerR3); 503 pHvStimer->pTimerRC = TMTimerRCPtr(pHvStimer->pTimerR3); 504 } 505 } 506 507 /* 508 * Inform APIC whether Hyper-V compatibility mode is enabled or not. 509 */ 510 if (pHv->uHyperHints & GIM_HV_HINT_X2APIC_MSRS) 511 APICR3HvSetCompatMode(pVM, true); 512 513 /* 514 * Register statistics. 515 */ 516 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 517 { 518 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 519 PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu; 520 521 for (size_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStatStimerFired); idxStimer++) 522 { 523 int rc2 = STAMR3RegisterF(pVM, &pHvCpu->aStatStimerFired[idxStimer], STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, 524 STAMUNIT_OCCURENCES, "Number of times the synthetic timer fired.", 525 "/GIM/HyperV/%u/Stimer%u_Fired", idCpu, idxStimer); 526 AssertLogRelRCReturn(rc2, rc2); 527 } 528 } 466 529 467 530 return VINF_SUCCESS; … … 516 579 gimR3HvReset(pVM); 517 580 gimR3HvTermHypercallSupport(pVM); 581 gimR3HvTermDebugSupport(pVM); 582 583 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 584 { 585 PGIMHVCPU pHvCpu = &pVM->aCpus[idCpu].gim.s.u.HvCpu; 586 for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++) 587 { 588 PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer]; 589 TMR3TimerDestroy(pHvStimer->pTimerR3); 590 } 591 } 592 518 593 return VINF_SUCCESS; 594 } 595 596 597 /** 598 * Applies relocations to data and code managed by this 599 * component. This function will be called at init and 600 * whenever the VMM need to relocate it self inside the GC. 601 * 602 * @param pVM The cross context VM structure. 603 * @param offDelta Relocation delta relative to old location. 604 */ 605 VMMR3_INT_DECL(void) gimR3HvRelocate(PVM pVM, RTGCINTPTR offDelta) 606 { 607 RT_NOREF1(offDelta); 608 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 609 { 610 PGIMHVCPU pHvCpu = &pVM->aCpus[idCpu].gim.s.u.HvCpu; 611 for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++) 612 { 613 PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer]; 614 pHvStimer->pTimerRC = TMTimerRCPtr(pHvStimer->pTimerR3); 615 } 616 } 519 617 } 520 618 … … 568 666 { 569 667 PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu; 668 pHvCpu->uSControlMsr = 0; 570 669 pHvCpu->uSimpMsr = 0; 571 670 pHvCpu->uSiefpMsr = 0; 572 671 pHvCpu->uApicAssistPageMsr = 0; 573 for (size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintXMsr); idxSintMsr++) 574 pHvCpu->auSintXMsr[idxSintMsr] = MSR_GIM_HV_SINT_MASKED; 672 673 for (uint8_t idxSint = 0; idxSint < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSint++) 674 pHvCpu->auSintMsrs[idxSint] = MSR_GIM_HV_SINT_MASKED; 675 676 for (uint8_t idxStimer = 0; idxStimer < RT_ELEMENTS(pHvCpu->aStimers); idxStimer++) 677 { 678 PGIMHVSTIMER pHvStimer = &pHvCpu->aStimers[idxStimer]; 679 pHvStimer->uStimerConfigMsr = 0; 680 pHvStimer->uStimerCountMsr = 0; 681 } 575 682 } 576 683 } … … 741 848 PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu; 742 849 SSMR3PutU64(pSSM, pHvCpu->uSimpMsr); 743 SSMR3PutU64(pSSM, pHvCpu->auSintXMsr[GIM_HV_VMBUS_MSG_SINT]); 850 for (size_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++) 851 SSMR3PutU64(pSSM, pHvCpu->auSintMsrs[idxSintMsr]); 744 852 } 745 853 … … 760 868 * Load the Hyper-V SSM version first. 761 869 */ 762 uint32_t uHvSavedStat Version;763 int rc = SSMR3GetU32(pSSM, &uHvSavedStat Version);870 uint32_t uHvSavedStateVersion; 871 int rc = SSMR3GetU32(pSSM, &uHvSavedStateVersion); 764 872 AssertRCReturn(rc, rc); 765 if ( uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION 766 && uHvSavedStatVersion != GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG) 873 if ( uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION 874 && uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC 875 && uHvSavedStateVersion != GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG) 767 876 return SSMR3SetLoadError(pSSM, VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION, RT_SRC_POS, 768 877 N_("Unsupported Hyper-V saved-state version %u (current %u)!"), 769 uHvSavedStat Version, GIM_HV_SAVED_STATE_VERSION);878 uHvSavedStateVersion, GIM_HV_SAVED_STATE_VERSION); 770 879 771 880 /* … … 855 964 * Load the debug support data. 856 965 */ 857 if (uHvSavedStat Version > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG)966 if (uHvSavedStateVersion > GIM_HV_SAVED_STATE_VERSION_PRE_DEBUG) 858 967 { 859 968 SSMR3GetU64(pSSM, &pHv->uDbgPendingBufferMsr); … … 870 979 PGIMHVCPU pHvCpu = &pVM->aCpus[i].gim.s.u.HvCpu; 871 980 SSMR3GetU64(pSSM, &pHvCpu->uSimpMsr); 872 SSMR3GetU64(pSSM, &pHvCpu->auSintXMsr[GIM_HV_VMBUS_MSG_SINT]); 981 if (uHvSavedStateVersion <= GIM_HV_SAVED_STATE_VERSION_PRE_SYNIC) 982 SSMR3GetU64(pSSM, &pHvCpu->auSintMsrs[GIM_HV_VMBUS_MSG_SINT]); 983 else 984 { 985 for (uint8_t idxSintMsr = 0; idxSintMsr < RT_ELEMENTS(pHvCpu->auSintMsrs); idxSintMsr++) 986 SSMR3GetU64(pSSM, &pHvCpu->auSintMsrs[idxSintMsr]); 987 } 873 988 } 874 989 … … 910 1025 { 911 1026 /** @todo Inform APIC. */ 912 LogRel(("GIM : HyperV%u: Enabled APIC-assist page at %#RGp\n", pVCpu->idCpu, GCPhysApicAssistPage));1027 LogRel(("GIM%u: HyperV: Enabled APIC-assist page at %#RGp\n", pVCpu->idCpu, GCPhysApicAssistPage)); 913 1028 } 914 1029 else 915 1030 { 916 LogRelFunc(("GIM : HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));1031 LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc)); 917 1032 rc = VERR_GIM_OPERATION_FAILED; 918 1033 } … … 922 1037 } 923 1038 924 LogRelFunc(("GIM : HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbApicAssistPage));1039 LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbApicAssistPage)); 925 1040 return VERR_NO_MEMORY; 926 1041 } … … 935 1050 VMMR3_INT_DECL(int) gimR3HvDisableApicAssistPage(PVMCPU pVCpu) 936 1051 { 937 LogRel(("GIM : HyperV%u: Disabled APIC-assist page\n", pVCpu->idCpu));1052 LogRel(("GIM%u: HyperV: Disabled APIC-assist page\n", pVCpu->idCpu)); 938 1053 /** @todo inform APIC */ 939 1054 return VINF_SUCCESS; 1055 } 1056 1057 1058 /** 1059 * Hyper-V synthetic timer callback. 1060 * 1061 * @param pVM The cross context VM structure. 1062 * @param pTimer Pointer to timer. 1063 * @param pvUser Pointer to the synthetic timer. 1064 */ 1065 static DECLCALLBACK(void) gimR3HvTimerCallback(PVM pVM, PTMTIMER pTimer, void *pvUser) 1066 { 1067 PGIMHVSTIMER pHvStimer = (PGIMHVSTIMER)pvUser; 1068 Assert(pHvStimer); 1069 Assert(TMTimerIsLockOwner(pTimer)); 1070 Assert(pHvStimer->idCpu < pVM->cCpus); 1071 1072 PVMCPU pVCpu = &pVM->aCpus[pHvStimer->idCpu]; 1073 PGIMHVCPU pHvCpu = &pVCpu->gim.s.u.HvCpu; 1074 Assert(pHvStimer->idxStimer < RT_ELEMENTS(pHvCpu->aStatStimerFired)); 1075 1076 STAM_COUNTER_INC(&pHvCpu->aStatStimerFired[pHvStimer->idxStimer]); 1077 1078 uint64_t const uStimerConfig = pHvStimer->uStimerConfigMsr; 1079 uint16_t const idxSint = MSR_GIM_HV_STIMER_GET_SINTX(uStimerConfig); 1080 if (RT_LIKELY(idxSint < RT_ELEMENTS(pHvCpu->auSintMsrs))) 1081 { 1082 uint64_t const uSint = pHvCpu->auSintMsrs[idxSint]; 1083 if (!MSR_GIM_HV_SINT_IS_MASKED(uSint)) 1084 { 1085 uint8_t const uVector = MSR_GIM_HV_SINT_GET_VECTOR(uSint); 1086 bool const fAutoEoi = MSR_GIM_HV_SINT_IS_AUTOEOI(uSint); 1087 APICHvSendInterrupt(pVCpu, uVector, fAutoEoi, XAPICTRIGGERMODE_EDGE); 1088 } 1089 } 1090 1091 /* Re-arm the timer if it's periodic. */ 1092 if (MSR_GIM_HV_STIMER_IS_PERIODIC(uStimerConfig)) 1093 gimHvStartStimer(pVCpu, pHvStimer); 940 1094 } 941 1095 … … 968 1122 { 969 1123 /** @todo SIEF setup. */ 970 LogRel(("GIM : HyperV%u: Enabled SIEF page at %#RGp\n", pVCpu->idCpu, GCPhysSiefPage));1124 LogRel(("GIM%u: HyperV: Enabled SIEF page at %#RGp\n", pVCpu->idCpu, GCPhysSiefPage)); 971 1125 } 972 1126 else 973 1127 { 974 LogRelFunc(("GIM : HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));1128 LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc)); 975 1129 rc = VERR_GIM_OPERATION_FAILED; 976 1130 } … … 980 1134 } 981 1135 982 LogRelFunc(("GIM : HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSiefPage));1136 LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSiefPage)); 983 1137 return VERR_NO_MEMORY; 984 1138 } … … 993 1147 VMMR3_INT_DECL(int) gimR3HvDisableSiefPage(PVMCPU pVCpu) 994 1148 { 995 LogRel(("GIM : HyperV%u: Disabled APIC-assist page\n", pVCpu->idCpu));1149 LogRel(("GIM%u: HyperV: Disabled APIC-assist page\n", pVCpu->idCpu)); 996 1150 /** @todo SIEF teardown. */ 997 1151 return VINF_SUCCESS; … … 1142 1296 { 1143 1297 /** @todo SIM setup. */ 1144 LogRel(("GIM : HyperV%u: Enabled SIM page at %#RGp\n", pVCpu->idCpu, GCPhysSimPage));1298 LogRel(("GIM%u: HyperV: Enabled SIM page at %#RGp\n", pVCpu->idCpu, GCPhysSimPage)); 1145 1299 } 1146 1300 else 1147 1301 { 1148 LogRelFunc(("GIM : HyperV%u: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc));1302 LogRelFunc(("GIM%u: HyperV: PGMPhysSimpleWriteGCPhys failed. rc=%Rrc\n", pVCpu->idCpu, rc)); 1149 1303 rc = VERR_GIM_OPERATION_FAILED; 1150 1304 } … … 1154 1308 } 1155 1309 1156 LogRelFunc(("GIM : HyperV%u: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSimPage));1310 LogRelFunc(("GIM%u: HyperV: Failed to alloc %u bytes\n", pVCpu->idCpu, cbSimPage)); 1157 1311 return VERR_NO_MEMORY; 1158 1312 } … … 1167 1321 VMMR3_INT_DECL(int) gimR3HvDisableSimPage(PVMCPU pVCpu) 1168 1322 { 1169 LogRel(("GIM : HyperV%u: Disabled SIM page\n", pVCpu->idCpu));1323 LogRel(("GIM%u: HyperV: Disabled SIM page\n", pVCpu->idCpu)); 1170 1324 /** @todo SIM teardown. */ 1171 1325 return VINF_SUCCESS; … … 1400 1554 1401 1555 1402 #if 0 /** @todo currently unused, which is probably very wrong */1403 1556 /** 1404 1557 * Terminates Hyper-V guest debug support. … … 1415 1568 } 1416 1569 } 1417 #endif1418 1570 1419 1571 -
trunk/src/VBox/VMM/VMMR3/VM.cpp
r62869 r63648 1264 1264 DBGFR3Relocate(pVM, offDelta); 1265 1265 PDMR3Relocate(pVM, offDelta); 1266 GIMR3Relocate(pVM, offDelta); 1266 1267 } 1267 1268
Note:
See TracChangeset
for help on using the changeset viewer.