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 */