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 <sainath.grandhi@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Shuo A Liu 2021-05-27 11:18:43 +08:00 committed by Xie, Nanlin
parent 811e367ad9
commit 17bc7f08c9
4 changed files with 54 additions and 0 deletions

View File

@ -10,6 +10,7 @@
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/guest/ept.h> #include <asm/guest/ept.h>
#include <asm/guest/vept.h>
#include <asm/vtd.h> #include <asm/vtd.h>
#include <asm/lapic.h> #include <asm/lapic.h>
#include <asm/irq.h> #include <asm/irq.h>
@ -263,6 +264,11 @@ void init_pcpu_post(uint16_t pcpu_id)
*/ */
reserve_buffer_for_ept_pages(); 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; pcpu_sync = ALL_CPUS_MASK;
/* Start all secondary cores */ /* Start all secondary cores */
startup_paddr = prepare_trampoline(); startup_paddr = prepare_trampoline();

View File

@ -13,6 +13,7 @@
#include <asm/guest/vm.h> #include <asm/guest/vm.h>
#include <asm/guest/vmcs.h> #include <asm/guest/vmcs.h>
#include <asm/guest/nested.h> #include <asm/guest/nested.h>
#include <asm/guest/vept.h>
/* Cache the content of MSR_IA32_VMX_BASIC */ /* Cache the content of MSR_IA32_VMX_BASIC */
static uint32_t 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 */ /* Cache the value of physical MSR_IA32_VMX_BASIC */
vmx_basic = (uint32_t)msr_read(MSR_IA32_VMX_BASIC); vmx_basic = (uint32_t)msr_read(MSR_IA32_VMX_BASIC);
setup_vmcs_shadowing_bitmap(); setup_vmcs_shadowing_bitmap();
init_vept();
} }
} }

View File

@ -13,6 +13,36 @@
#include <asm/guest/ept.h> #include <asm/guest/ept.h>
#include <asm/guest/nested.h> #include <asm/guest/nested.h>
/*
* 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 * @pre vcpu != NULL
*/ */
@ -35,3 +65,14 @@ int32_t invept_vmexit_handler(struct acrn_vcpu *vcpu)
return 0; 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;
}

View File

@ -7,6 +7,10 @@
#define VEPT_H #define VEPT_H
#ifdef CONFIG_NVMX_ENABLED #ifdef CONFIG_NVMX_ENABLED
void reserve_buffer_for_sept_pages(void);
void init_vept(void);
int32_t invept_vmexit_handler(struct acrn_vcpu *vcpu); int32_t invept_vmexit_handler(struct acrn_vcpu *vcpu);
#else
static inline void reserve_buffer_for_sept_pages(void) {};
#endif /* CONFIG_NVMX_ENABLED */ #endif /* CONFIG_NVMX_ENABLED */
#endif /* VEPT_H */ #endif /* VEPT_H */