Vmware 嵌套 VT EPT 性能暴降 解决方案
2022-10-30 19:10:19 Author: bbs.pediy.com(查看原文) 阅读量:6 收藏

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

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;

}

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


文章来源: https://bbs.pediy.com/thread-274932.htm
如有侵权请联系:admin#unsafe.sh