Currently in TDX test case init stage, it setup an initial lvl5 boot page table, but VM code support only lvl4 page table. This mismatch make the test cases requiring virtual memory crash. Add below changes to support lvl5 page table for virtual memory: 1. skip finding high memory 2. check X86_CR4_LA57 to decide to initialize lvl5 or lvl4 page table 3. always set X86_CR0_NE for TDX test case Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx> Reviewed-by: Yu Zhang <yu.c.zhang@xxxxxxxxx> --- lib/x86/processor.h | 1 + lib/x86/setup.c | 5 +++++ lib/x86/vm.c | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 865269fd3857..4deff9ebe044 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -35,6 +35,7 @@ #define X86_CR0_MP 0x00000002 #define X86_CR0_EM 0x00000004 #define X86_CR0_TS 0x00000008 +#define X86_CR0_NE 0x00000020 #define X86_CR0_WP 0x00010000 #define X86_CR0_AM 0x00040000 #define X86_CR0_NW 0x20000000 diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 3a60762494d6..0c299d3dd9bc 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -64,6 +64,11 @@ static struct mbi_bootinfo *bootinfo; #ifdef __x86_64__ void find_highmem(void) { +#ifdef TARGET_EFI + /* The largest free memory region is already chosen in setup_efi() */ + return; +#endif /* TARGET_EFI */ + /* Memory above 4 GB is only supported on 64-bit systems. */ if (!(bootinfo->flags & 64)) return; diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 56be57be673a..4ead6ed358ae 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -3,6 +3,7 @@ #include "vmalloc.h" #include "alloc_page.h" #include "smp.h" +#include "tdx.h" static pteval_t pte_opt_mask; @@ -16,7 +17,12 @@ pteval_t *install_pte(pgd_t *cr3, pteval_t *pt = cr3; unsigned offset; - for (level = PAGE_LEVEL; level > pte_level; --level) { + if (read_cr4() & X86_CR4_LA57) + level = 5; + else + level = PAGE_LEVEL; + + for (; level > pte_level; --level) { offset = PGDIR_OFFSET((uintptr_t)virt, level); if (!(pt[offset] & PT_PRESENT_MASK)) { pteval_t *new_pt = pt_page; @@ -187,7 +193,11 @@ void *setup_mmu(phys_addr_t end_of_memory, void *opt_mask) #ifndef __x86_64__ write_cr4(X86_CR4_PSE); #endif - write_cr0(X86_CR0_PG |X86_CR0_PE | X86_CR0_WP); + /* According to TDX module spec 10.6.1 CR0.NE should be 1 */ + if (is_tdx_guest()) + write_cr0(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE); + else + write_cr0(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP); printf("paging enabled\n"); printf("cr0 = %lx\n", read_cr0()); -- 2.25.1