From 17bc7f08c9e0923c1381215f72ee0ac4d10b30fa Mon Sep 17 00:00:00 2001 From: Shuo A Liu Date: Thu, 27 May 2021 11:18:43 +0800 Subject: [PATCH] hv: nested: Create a page pool for shadow EPT construction Shadow EPT uses lots of pages to construct the shadow page table. To utilize the memory more efficient, a page poll sept_page_pool is introduced. For simplicity, total platform RAM size is considered to calculate the memory needed for shadow page tables. This is not an accurate upper bound. This can satisfy typical use-cases where there is not a lot of overcommitment and sharing of memory between L2 VMs. Memory of the pool is marked as reserved from E820 table in early stage. Tracked-On: #5923 Signed-off-by: Sainath Grandhi Signed-off-by: Zide Chen Signed-off-by: Shuo A Liu Reviewed-by: Jason Chen CJ Acked-by: Eddie Dong --- hypervisor/arch/x86/cpu.c | 6 +++ hypervisor/arch/x86/guest/nested.c | 3 ++ hypervisor/arch/x86/guest/vept.c | 41 ++++++++++++++++++++ hypervisor/include/arch/x86/asm/guest/vept.h | 4 ++ 4 files changed, 54 insertions(+) diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 14a0c4dfb..8f69c99bb 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +264,11 @@ void init_pcpu_post(uint16_t pcpu_id) */ reserve_buffer_for_ept_pages(); + /* + * Reserve memory from platform E820 for shadow EPT 4K pages + */ + reserve_buffer_for_sept_pages(); + pcpu_sync = ALL_CPUS_MASK; /* Start all secondary cores */ startup_paddr = prepare_trampoline(); diff --git a/hypervisor/arch/x86/guest/nested.c b/hypervisor/arch/x86/guest/nested.c index 6c865adcf..3a714ebfe 100644 --- a/hypervisor/arch/x86/guest/nested.c +++ b/hypervisor/arch/x86/guest/nested.c @@ -13,6 +13,7 @@ #include #include #include +#include /* Cache the content of MSR_IA32_VMX_BASIC */ static uint32_t vmx_basic; @@ -1555,5 +1556,7 @@ void init_nested_vmx(__unused struct acrn_vm *vm) /* Cache the value of physical MSR_IA32_VMX_BASIC */ vmx_basic = (uint32_t)msr_read(MSR_IA32_VMX_BASIC); setup_vmcs_shadowing_bitmap(); + + init_vept(); } } diff --git a/hypervisor/arch/x86/guest/vept.c b/hypervisor/arch/x86/guest/vept.c index 658c887fe..fea24fd22 100644 --- a/hypervisor/arch/x86/guest/vept.c +++ b/hypervisor/arch/x86/guest/vept.c @@ -13,6 +13,36 @@ #include #include +/* + * For simplicity, total platform RAM size is considered to calculate the + * memory needed for shadow page tables. This is not an accurate upper bound. + * This can satisfy typical use-cases where there is not a lot ofovercommitment + * and sharing of memory between L2 VMs. + * + * Page table entry need 8 bytes to represent every 4K page frame. + * Total number of bytes = (CONFIG_PLATFORM_RAM_SIZE/4096) * 8 + * Number of pages needed = Total number of bytes needed/4096 + */ +#define TOTAL_SEPT_4K_PAGES_SIZE ((CONFIG_PLATFORM_RAM_SIZE * 8UL) / 4096UL) +#define TOTAL_SEPT_4K_PAGES_NUM (TOTAL_SEPT_4K_PAGES_SIZE / PAGE_SIZE) + +static struct page_pool sept_page_pool; +static struct page *sept_pages; +static uint64_t sept_page_bitmap[TOTAL_SEPT_4K_PAGES_NUM / 64U]; + +/* + * @brief Reserve space for SEPT 4K pages from platform E820 table + * At moment, we only support nested VMX for SOS VM. + */ +void reserve_buffer_for_sept_pages(void) +{ + uint64_t page_base; + + page_base = e820_alloc_memory(TOTAL_SEPT_4K_PAGES_SIZE, ~0UL); + set_paging_supervisor(page_base, TOTAL_SEPT_4K_PAGES_SIZE); + sept_pages = (struct page *)page_base; +} + /** * @pre vcpu != NULL */ @@ -35,3 +65,14 @@ int32_t invept_vmexit_handler(struct acrn_vcpu *vcpu) return 0; } + +void init_vept(void) +{ + sept_page_pool.start_page = sept_pages; + sept_page_pool.bitmap_size = TOTAL_SEPT_4K_PAGES_NUM / 64U; + sept_page_pool.bitmap = sept_page_bitmap; + sept_page_pool.dummy_page = NULL; + spinlock_init(&sept_page_pool.lock); + memset((void *)sept_page_pool.bitmap, 0, sept_page_pool.bitmap_size * sizeof(uint64_t)); + sept_page_pool.last_hint_id = 0UL; +} diff --git a/hypervisor/include/arch/x86/asm/guest/vept.h b/hypervisor/include/arch/x86/asm/guest/vept.h index f0b59b22a..70c7ddf7e 100644 --- a/hypervisor/include/arch/x86/asm/guest/vept.h +++ b/hypervisor/include/arch/x86/asm/guest/vept.h @@ -7,6 +7,10 @@ #define VEPT_H #ifdef CONFIG_NVMX_ENABLED +void reserve_buffer_for_sept_pages(void); +void init_vept(void); int32_t invept_vmexit_handler(struct acrn_vcpu *vcpu); +#else +static inline void reserve_buffer_for_sept_pages(void) {}; #endif /* CONFIG_NVMX_ENABLED */ #endif /* VEPT_H */