- Timestamp:
- Nov 5, 2012 1:50:57 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 81813
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r43494 r43803 136 136 uint64_t vmx_cr4_fixed1; 137 137 uint64_t vmx_vmcs_enum; 138 uint64_t vmx_ept caps;138 uint64_t vmx_ept_vpid_caps; 139 139 } msr; 140 140 /* Last instruction error */ … … 426 426 if ( g_HvmR0.vmx.msr.vmx_proc_ctls2.n.allowed1 427 427 & (VMX_VMCS_CTRL_PROC_EXEC2_EPT | VMX_VMCS_CTRL_PROC_EXEC2_VPID)) 428 g_HvmR0.vmx.msr.vmx_eptcaps = ASMRdMsr(MSR_IA32_VMX_EPT_CAPS); 428 { 429 g_HvmR0.vmx.msr.vmx_ept_vpid_caps = ASMRdMsr(MSR_IA32_VMX_EPT_VPID_CAP); 430 } 429 431 } 430 432 … … 1213 1215 pVM->hm.s.vmx.msr.vmx_cr4_fixed1 = g_HvmR0.vmx.msr.vmx_cr4_fixed1; 1214 1216 pVM->hm.s.vmx.msr.vmx_vmcs_enum = g_HvmR0.vmx.msr.vmx_vmcs_enum; 1215 pVM->hm.s.vmx.msr.vmx_ept caps = g_HvmR0.vmx.msr.vmx_eptcaps;1217 pVM->hm.s.vmx.msr.vmx_ept_vpid_caps = g_HvmR0.vmx.msr.vmx_ept_vpid_caps; 1216 1218 pVM->hm.s.svm.msrHwcr = g_HvmR0.svm.msrHwcr; 1217 1219 pVM->hm.s.svm.u32Rev = g_HvmR0.svm.u32Rev; -
trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
r43798 r43803 166 166 if ( pVM 167 167 && pVM->hm.s.vmx.fVpid 168 && (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS))168 && (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)) 169 169 { 170 170 hmR0VmxFlushVPID(pVM, NULL /* pvCpu */, VMX_FLUSH_VPID_ALL_CONTEXTS, 0 /* GCPtr */); … … 431 431 if (pVM->hm.s.fNestedPaging) 432 432 { 433 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT)434 { 435 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_SINGLE_CONTEXT)433 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT) 434 { 435 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT) 436 436 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_SINGLE_CONTEXT; 437 else if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL_CONTEXTS)437 else if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS) 438 438 pVM->hm.s.vmx.enmFlushEpt = VMX_FLUSH_EPT_ALL_CONTEXTS; 439 439 else … … 460 460 if (pVM->hm.s.vmx.fVpid) 461 461 { 462 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID)463 { 464 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT)462 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID) 463 { 464 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT) 465 465 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_SINGLE_CONTEXT; 466 else if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS)466 else if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS) 467 467 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_ALL_CONTEXTS; 468 468 else … … 472 472 * We do not handle other flush type combinations, ignore VPID capabilities. 473 473 */ 474 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR)474 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 475 475 Log(("VMXR0SetupVM: Only VMX_FLUSH_VPID_INDIV_ADDR supported. Ignoring VPID.\n")); 476 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS)476 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS) 477 477 Log(("VMXR0SetupVM: Only VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n")); 478 478 pVM->hm.s.vmx.enmFlushVpid = VMX_FLUSH_VPID_NOT_SUPPORTED; … … 2552 2552 else 2553 2553 { 2554 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT)2554 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT) 2555 2555 hmR0VmxFlushVPID(pVM, pVCpu, VMX_FLUSH_VPID_SINGLE_CONTEXT, 0 /* GCPtr */); 2556 2556 else … … 2579 2579 * as supported by the CPU. 2580 2580 */ 2581 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR)2581 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 2582 2582 { 2583 2583 for (unsigned i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++) … … 2742 2742 * as supported by the CPU. 2743 2743 */ 2744 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR)2744 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 2745 2745 { 2746 2746 for (unsigned i = 0; i < pVCpu->hm.s.TlbShootdown.cPages; i++) … … 5101 5101 { 5102 5102 /* If we can flush just this page do it, otherwise flush as little as possible. */ 5103 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR)5103 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 5104 5104 hmR0VmxFlushVPID(pVM, pVCpu, VMX_FLUSH_VPID_INDIV_ADDR, GCVirt); 5105 5105 else -
trunk/src/VBox/VMM/VMMR3/HM.cpp
r43756 r43803 1049 1049 LogRel(("HM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER *must* be set\n")); 1050 1050 1051 if (pVM->hm.s.vmx.msr.vmx_ept caps)1051 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps) 1052 1052 { 1053 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP S = %RX64\n", pVM->hm.s.vmx.msr.vmx_eptcaps));1054 1055 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_RWX_X_ONLY)1056 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_RWX_X_ONLY\n"));1057 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_RWX_W_ONLY)1058 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_RWX_W_ONLY\n"));1059 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_RWX_WX_ONLY)1060 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_RWX_WX_ONLY\n"));1061 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_GAW_21_BITS)1062 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_GAW_21_BITS\n"));1063 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_GAW_30_BITS)1064 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_GAW_30_BITS\n"));1065 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_GAW_39_BITS)1066 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_GAW_39_BITS\n"));1067 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_GAW_48_BITS)1068 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_GAW_48_BITS\n"));1069 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_GAW_57_BITS)1070 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_GAW_57_BITS\n"));1071 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_EMT_UC)1072 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_EMT_UC\n"));1073 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_EMT_WC)1074 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_EMT_WC\n"));1075 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_EMT_WT)1076 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_EMT_WT\n"));1077 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_EMT_WP)1078 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_EMT_WP\n"));1079 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_EMT_WB)1080 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_EMT_WB\n"));1081 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_SP_21_BITS)1082 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_SP_21_BITS\n"));1083 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_SP_30_BITS)1084 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_SP_30_BITS\n"));1085 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_SP_39_BITS)1086 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_SP_39_BITS\n"));1087 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_SP_48_BITS)1088 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_SP_48_BITS\n"));1089 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT)1090 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVEPT\n"));1091 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_SINGLE_CONTEXT)1092 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVEPT_CAPS_SINGLE_CONTEXT\n"));1093 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL_CONTEXTS)1094 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVEPT_CAPS_ALL_CONTEXTS\n"));1095 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID)1096 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVVPID\n"));1097 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR)1098 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVVPID_CAPS_INDIV_ADDR\n"));1099 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT)1100 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVVPID_CAPS_SINGLE_CONTEXT\n"));1101 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS)1102 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVVPID_CAPS_ALL_CONTEXTS\n"));1103 if (pVM->hm.s.vmx.msr.vmx_ept caps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS)1104 LogRel(("HM: MSR_IA32_VMX_EPT_ CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS\n"));1053 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP = %RX64\n", pVM->hm.s.vmx.msr.vmx_ept_vpid_caps)); 1054 1055 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY) 1056 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY\n")); 1057 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_RWX_W_ONLY) 1058 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_RWX_W_ONLY\n")); 1059 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_RWX_WX_ONLY) 1060 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_RWX_WX_ONLY\n")); 1061 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_GAW_21_BITS) 1062 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_GAW_21_BITS\n")); 1063 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_GAW_30_BITS) 1064 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_GAW_30_BITS\n")); 1065 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_GAW_39_BITS) 1066 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_GAW_39_BITS\n")); 1067 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_GAW_48_BITS) 1068 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_GAW_48_BITS\n")); 1069 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_GAW_57_BITS) 1070 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_GAW_57_BITS\n")); 1071 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_UC) 1072 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_EMT_UC\n")); 1073 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WC) 1074 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_EMT_WC\n")); 1075 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WT) 1076 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_EMT_WT\n")); 1077 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WP) 1078 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_EMT_WP\n")); 1079 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB) 1080 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB\n")); 1081 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_SP_21_BITS) 1082 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_SP_21_BITS\n")); 1083 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_SP_30_BITS) 1084 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_SP_30_BITS\n")); 1085 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_SP_39_BITS) 1086 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_SP_39_BITS\n")); 1087 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_SP_48_BITS) 1088 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_SP_48_BITS\n")); 1089 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT) 1090 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVEPT\n")); 1091 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT) 1092 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT\n")); 1093 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS) 1094 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS\n")); 1095 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID) 1096 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVVPID\n")); 1097 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR) 1098 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR\n")); 1099 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT) 1100 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT\n")); 1101 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS) 1102 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS\n")); 1103 if (pVM->hm.s.vmx.msr.vmx_ept_vpid_caps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS) 1104 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n")); 1105 1105 } 1106 1106 -
trunk/src/VBox/VMM/include/HMInternal.h
r43798 r43803 357 357 uint64_t vmx_cr4_fixed1; 358 358 uint64_t vmx_vmcs_enum; 359 uint64_t vmx_ept caps;359 uint64_t vmx_ept_vpid_caps; 360 360 } msr; 361 361
Note:
See TracChangeset
for help on using the changeset viewer.