首页
社区
课程
招聘
Vmware 嵌套 VT EPT 性能暴降 解决方案
发表于: 2022-10-30 17:50 22763

Vmware 嵌套 VT EPT 性能暴降 解决方案

2022-10-30 17:50
22763

近段时间在Vmware中使用 VT EPT技术时
发生性能爆降甚至鼠标不能动的现象
检查 VM exit 事件,无任何问题
设置 Vmware 核心数 16 发现比 核心数 4 还卡
设置核心数 1 发现 稳定运行 无卡顿
觉得可能是 EPT 多次寻址问题
HyperPlatform 项目将在每个CPU设置不同的EPT目录
我将代码改为以下

测试发现性能正常 操作流畅 无卡顿 CPU占用降低
so 问题解决
原理是设置CPU核心为同一页表
Vmware 可能某种原因无法识别我们是为那个CPU设置的页表
但是他可以根据 设置的物理地址判断是否为同一个页表结构

别忘记卸载时

EptData* g_EptData = 0;
// Builds EPT, allocates pre-allocated entires, initializes and returns EptData
_Use_decl_annotations_ EptData* EptInitialization() {
    PAGED_CODE()
 
        if (g_EptData != 0)//增加
            return g_EptData;//增加
    static const auto kEptPageWalkLevel = 4ul;
 
    // Allocate ept_data
    const auto ept_data = static_cast<EptData*>(ExAllocatePoolWithTag(
        NonPagedPool, sizeof(EptData), kHyperPlatformCommonPoolTag));
    if (!ept_data) {
        return nullptr;
    }
    RtlZeroMemory(ept_data, sizeof(EptData));
 
    //// Allocate EptPointer
    //const auto ept_poiner = reinterpret_cast<EptPointer*>(ExAllocatePoolWithTag(
    //    NonPagedPool, PAGE_SIZE, kHyperPlatformCommonPoolTag));
    //if (!ept_poiner) {
    //    ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
    //    return nullptr;
    //}
    //RtlZeroMemory(ept_poiner, PAGE_SIZE);
 
    // Allocate EPT_PML4 and initialize EptPointer
    const auto ept_pml4 = static_cast<EptCommonEntry*>(
        ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, kHyperPlatformCommonPoolTag));
    if (!ept_pml4) {
        ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
        return nullptr;
    }
    RtlZeroMemory(ept_pml4, PAGE_SIZE);
 
    ept_data->ept_pointer.all = 0;
    ept_data->ept_pointer.fields.memory_type =
        static_cast<ULONG64>(EptpGetMemoryType(UtilPaFromVa(ept_pml4)));
    ept_data->ept_pointer.fields.page_walk_length = kEptPageWalkLevel - 1;
    ept_data->ept_pointer.fields.pml4_address =
        UtilPfnFromPa(UtilPaFromVa(ept_pml4));
 
    // Initialize all EPT entries for all physical memory pages
    const auto pm_ranges = UtilGetPhysicalMemoryRanges();
    for (auto run_index = 0ul; run_index < pm_ranges->number_of_runs;
        ++run_index) {
        const auto run = &pm_ranges->run[run_index];
        const auto base_addr = run->base_page * PAGE_SIZE;
        for (auto page_index = 0ull; page_index < run->page_count; ++page_index) {
            const auto indexed_addr = base_addr + page_index * PAGE_SIZE;
            const auto ept_pt_entry =
                EptpConstructTables(ept_pml4, 4, indexed_addr, nullptr);
            if (!ept_pt_entry) {
                EptpDestructTables(ept_pml4, 4);
                ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
                return nullptr;
            }
        }
    }
 
    // Initialize an EPT entry for APIC_BASE. It is required to allocated it now
    // for some reasons, or else, system hangs.
    const Ia32ApicBaseMsr apic_msr = { UtilReadMsr64(Msr::kIa32ApicBase) };
    if (!EptpConstructTables(ept_pml4, 4, apic_msr.fields.apic_base * PAGE_SIZE,
        nullptr)) {
        EptpDestructTables(ept_pml4, 4);
        ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
        return nullptr;
    }
 
    // Allocate preallocated_entries
    const auto preallocated_entries_size =
        sizeof(EptCommonEntry*) * kEptpNumberOfPreallocatedEntries;
    const auto preallocated_entries = static_cast<EptCommonEntry**>(
        ExAllocatePoolWithTag(NonPagedPool, preallocated_entries_size,
            kHyperPlatformCommonPoolTag));
    if (!preallocated_entries) {
        EptpDestructTables(ept_pml4, 4);
        ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
        return nullptr;
    }
    RtlZeroMemory(preallocated_entries, preallocated_entries_size);
 
    // And fill preallocated_entries with newly created entries
    for (auto i = 0ul; i < kEptpNumberOfPreallocatedEntries; ++i) {
        const auto ept_entry = EptpAllocateEptEntry(nullptr);
        if (!ept_entry) {
            EptpFreeUnusedPreAllocatedEntries(preallocated_entries, 0);
            EptpDestructTables(ept_pml4, 4);
            ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
            return nullptr;
        }
        preallocated_entries[i] = ept_entry;
    }
 
    // Initialization completed
    ept_data->ept_pml4 = ept_pml4;
    ept_data->preallocated_entries = preallocated_entries;
    ept_data->preallocated_entries_count = 0;
 
    g_EptData = ept_data;//增加
    return ept_data;
}
EptData* g_EptData = 0;
// Builds EPT, allocates pre-allocated entires, initializes and returns EptData
_Use_decl_annotations_ EptData* EptInitialization() {
    PAGED_CODE()
 
        if (g_EptData != 0)//增加
            return g_EptData;//增加
    static const auto kEptPageWalkLevel = 4ul;
 
    // Allocate ept_data
    const auto ept_data = static_cast<EptData*>(ExAllocatePoolWithTag(
        NonPagedPool, sizeof(EptData), kHyperPlatformCommonPoolTag));
    if (!ept_data) {
        return nullptr;
    }
    RtlZeroMemory(ept_data, sizeof(EptData));
 
    //// Allocate EptPointer
    //const auto ept_poiner = reinterpret_cast<EptPointer*>(ExAllocatePoolWithTag(
    //    NonPagedPool, PAGE_SIZE, kHyperPlatformCommonPoolTag));
    //if (!ept_poiner) {
    //    ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
    //    return nullptr;
    //}
    //RtlZeroMemory(ept_poiner, PAGE_SIZE);
 
    // Allocate EPT_PML4 and initialize EptPointer
    const auto ept_pml4 = static_cast<EptCommonEntry*>(
        ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, kHyperPlatformCommonPoolTag));
    if (!ept_pml4) {
        ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
        return nullptr;
    }
    RtlZeroMemory(ept_pml4, PAGE_SIZE);
 
    ept_data->ept_pointer.all = 0;
    ept_data->ept_pointer.fields.memory_type =
        static_cast<ULONG64>(EptpGetMemoryType(UtilPaFromVa(ept_pml4)));
    ept_data->ept_pointer.fields.page_walk_length = kEptPageWalkLevel - 1;
    ept_data->ept_pointer.fields.pml4_address =
        UtilPfnFromPa(UtilPaFromVa(ept_pml4));
 
    // Initialize all EPT entries for all physical memory pages
    const auto pm_ranges = UtilGetPhysicalMemoryRanges();
    for (auto run_index = 0ul; run_index < pm_ranges->number_of_runs;
        ++run_index) {
        const auto run = &pm_ranges->run[run_index];
        const auto base_addr = run->base_page * PAGE_SIZE;
        for (auto page_index = 0ull; page_index < run->page_count; ++page_index) {
            const auto indexed_addr = base_addr + page_index * PAGE_SIZE;
            const auto ept_pt_entry =
                EptpConstructTables(ept_pml4, 4, indexed_addr, nullptr);
            if (!ept_pt_entry) {
                EptpDestructTables(ept_pml4, 4);
                ExFreePoolWithTag(ept_data, kHyperPlatformCommonPoolTag);
                return nullptr;
            }
        }
    }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 10
支持
分享
最新回复 (15)
雪    币: 1085
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bxb
2
沙发
2022-10-30 23:51
0
雪    币: 1182
活跃值: (954)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
相当于每个cpu共享了 ept?
2022-10-31 08:27
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
正常情况都是 每个核心给一个EPT
2022-10-31 08:31
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
5
6
2022-10-31 13:29
0
雪    币: 2926
活跃值: (3132)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
https://github.com/tandasat/HyperPlatform/commit/c7e2d37d12672e7fabc2c6288cfe08f25dddf142
2022-10-31 16:26
0
雪    币: 1246
活跃值: (1978)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
所有核心共用一套EPT,多核情况下的EPT HOOK 会造成大量的vmexit吧?
2022-10-31 18:11
0
雪    币: 1100
活跃值: (126)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这种方式 好像对 MTF Exit有影响
2022-11-1 14:30
0
雪    币: 2242
活跃值: (3782)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
9
newmiaoxin 这种方式 好像对 MTF Exit有影响
多核下可能会出现页目录设置错误逻辑问题
2022-11-1 15:13
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
共享ept页在做hook时,MTF权限切换空隙会使得其他core hook失效
2022-11-2 09:58
0
雪    币: 2242
活跃值: (3782)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
11
Ae0LuS 共享ept页在做hook时,MTF权限切换空隙会使得其他core hook失效
是的,但这种概率极小,而且时间片段也很小,有个办法能解决
直接上反汇编引擎,他读什么我给什么直接跳走
2022-11-2 11:35
0
雪    币: 412
活跃值: (2181)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
12
6
2022-11-2 14:34
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
13
逍遥m 是的,但这种概率极小,而且时间片段也很小,有个办法能解决 直接上反汇编引擎,他读什么我给什么直接跳走
那不就是KiTpEmulateInstruction
2022-11-2 15:31
0
雪    币: 2242
活跃值: (3782)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
14
hzqst 那不就是KiTpEmulateInstruction

KiTpSetupCompletion is used to finalize registration of a trace point, which first calls KiTpReadImageData based on the instruction size that was specified. An instruction parser (KiTpParseInstructionPrefix, KiTpFetchInstructionBytes) is used, followed by an emulator (KiTpEmulateInstruction, KiTpEmulateMovzx, and many more) are used to determine the instruction size that is required. Once the information is known, the original instructions are copied. For what it’s worth, KiTpReadImageData is a simple function which attaches to the input process and basically does a memcpy of the address and specified bytes.


https://www.alex-ionescu.com/?p=358


大表哥一句话让我查好久 

2022-11-2 17:22
0
雪    币: 1182
活跃值: (954)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
逍遥m 是的,但这种概率极小,而且时间片段也很小,有个办法能解决 直接上反汇编引擎,他读什么我给什么直接跳走
他读什么你给什么 , 意思自己取值? 我发现mtf win7共享ept 几乎不会出问题, 但是win10 没几分钟就gg
2022-11-8 10:32
0
雪    币: 493
活跃值: (1808)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
感谢感谢,我也遇到了这个问题
2024-5-18 18:38
0
游客
登录 | 注册 方可回帖
返回
//