nEPT: Fix test cases for 2M huge pages
PATCH 1/1 nEPT: Fix test cases for 2M huge pages
If 2M pages are available with EPT, the test code creates its initial identity map with such pages. But then it tries to remap two 4K pages in that range which fails as their level 3 PTE is set up for huge pages.
Fix this up by ensuring that install_ept_entry always create non-large page directory entries and by remapping the 2M area around those two test pages in 4K chunks.
--- x86/vmx.c | 3 ++- x86/vmx.h | 3 ++- x86/vmx_tests.c | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-)
x86/vmx.c +2 -1
@@ -173,7 +173,8 @@ void install_ept_entry(unsigned long *pml4,memset (new_pt,0 ,PAGE_SIZE ); pt[offset] =virt_to_phys (new_pt) |EPT_RA |EPT_WA |EPT_EA ; - } + }else + pt[offset] &= ~EPT_LARGE_PAGE ; pt =phys_to_virt (pt[offset] &0xffffffffff000ull ); } offset = ((unsigned long)guest_addr >> ((level-1) *
x86/vmx.h +2 -1
@@ -485,7 +485,8 @@ enum Ctrl1 {#define EPT_PAGE_LEVEL 4#define EPT_PGDIR_WIDTH 9#define EPT_PGDIR_MASK 511 -#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK_2M (~(PAGE_SIZE_2M-1))#define EPT_VLT_RD 1#define EPT_VLT_WR (1 << 1)
x86/vmx_tests.c +8 -0
@@ -915,6 +915,7 @@ static int setup_ept()static void ept_init () { +unsigned long base_addr1, base_addr2;u32 ctrl_cpu[2 ]; init_fail = false;
@@ -934,6 +935,13 @@ static void ept_init()memset (data_page2,0x0 ,PAGE_SIZE ); *((u32 *)data_page1) =MAGIC_VAL_1 ; *((u32 *)data_page2) =MAGIC_VAL_2 ; + base_addr1 = (unsigned long )data_page1 &PAGE_MASK_2M ; + base_addr2 = (unsigned long )data_page2 &PAGE_MASK_2M ; +if (setup_ept_range (pml4, base_addr1, base_addr1 +PAGE_SIZE_2M ,0 ,0 , +EPT_WA |EPT_RA |EPT_EA ) || +setup_ept_range (pml4, base_addr2, base_addr2 +PAGE_SIZE_2M ,0 ,0 , +EPT_WA |EPT_RA |EPT_EA )) + init_fail = true;install_ept (pml4, (unsigned long )data_page1, (unsigned long )data_page2,EPT_RA |EPT_WA |EPT_EA ); }
Signature · 1 line
1.8.1.1.298.ge7eed54
Paolo Bonzini
maintainerIl 23/10/2013 15:38, Jan Kiszka ha scritto:
Quoted 60 lines
If 2M pages are available with EPT, the test code creates its initial identity map with such pages. But then it tries to remap two 4K pages in that range which fails as their level 3 PTE is set up for huge pages.
Fix this up by ensuring that
install_ept_entryalways create non-large page directory entries and by remapping the 2M area around those two test pages in 4K chunks.Signed-off-by Jan Kiszka <[email protected]>--- x86/vmx.c | 3 ++- x86/vmx.h | 3 ++- x86/vmx_tests.c | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-)x86/vmx.c +2
-1@@ -173,7 +173,8 @@ void install_ept_entry(unsigned long *pml4,memset (new_pt,0 ,PAGE_SIZE ); pt[offset] =virt_to_phys (new_pt) |EPT_RA |EPT_WA |EPT_EA ; - } + }else + pt[offset] &= ~EPT_LARGE_PAGE ; pt =phys_to_virt (pt[offset] &0xffffffffff000ull ); } offset = ((unsigned long)guest_addr >> ((level-1) *x86/vmx.h +2
-1@@ -485,7 +485,8 @@ enum Ctrl1 {#define EPT_PAGE_LEVEL 4#define EPT_PGDIR_WIDTH 9#define EPT_PGDIR_MASK 511 -#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK_2M (~(PAGE_SIZE_2M-1))#define EPT_VLT_RD 1#define EPT_VLT_WR (1 << 1)x86/vmx_tests.c +1
-0@@ -915,6 +915,7 @@ static int setup_ept()static void ept_init () { +unsigned long base_addr1, base_addr2;u32 ctrl_cpu[2 ]; init_fail = false;@@ -934,6 +935,13 @@ static void ept_init()memset (data_page2,0x0 ,PAGE_SIZE ); *((u32 *)data_page1) =MAGIC_VAL_1 ; *((u32 *)data_page2) =MAGIC_VAL_2 ;
x86/vmx_tests.c static void ept_init() · line 947
Quoted 10 lines
x86/vmx_tests.c +7
-0+ base_addr1 = (unsigned long )data_page1 &PAGE_MASK_2M ; + base_addr2 = (unsigned long )data_page2 &PAGE_MASK_2M ; +if (setup_ept_range (pml4, base_addr1, base_addr1 +PAGE_SIZE_2M ,0 ,0 , +EPT_WA |EPT_RA |EPT_EA ) || +setup_ept_range (pml4, base_addr2, base_addr2 +PAGE_SIZE_2M ,0 ,0 , +EPT_WA |EPT_RA |EPT_EA )) + init_fail = true;install_ept (pml4, (unsigned long )data_page1, (unsigned long )data_page2,EPT_RA |EPT_WA |EPT_EA ); }
Applied to kvm-unit-tests.git vmx.
Paolo