mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-06 10:44:41 +00:00
HV: Add walk_ept_table and get_ept_entry APIs
The walk_ept_table API is used to walk through EPT table for getting all of present pages, user can get each page entry and its size from the walk_ept_table callback. The get_ept_entry is used to getting EPT pointer of the vm, if current context of mv is secure world, return secure world EPT pointer, otherwise return normal world EPT pointer. Signed-off-by: Jack Ren <jack.ren@intel.com> Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Reviewed-by: Li, Fei1 <fei1.li@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
f81585eb3d
commit
f320130d58
@ -30,21 +30,18 @@ void destroy_ept(struct acrn_vm *vm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* using return value INVALID_HPA as error code */
|
/**
|
||||||
|
* @pre: vm != NULL.
|
||||||
|
*/
|
||||||
uint64_t local_gpa2hpa(struct acrn_vm *vm, uint64_t gpa, uint32_t *size)
|
uint64_t local_gpa2hpa(struct acrn_vm *vm, uint64_t gpa, uint32_t *size)
|
||||||
{
|
{
|
||||||
|
/* using return value INVALID_HPA as error code */
|
||||||
uint64_t hpa = INVALID_HPA;
|
uint64_t hpa = INVALID_HPA;
|
||||||
const uint64_t *pgentry;
|
const uint64_t *pgentry;
|
||||||
uint64_t pg_size = 0UL;
|
uint64_t pg_size = 0UL;
|
||||||
void *eptp;
|
void *eptp;
|
||||||
struct acrn_vcpu *vcpu = vcpu_from_pid(vm, get_pcpu_id());
|
|
||||||
|
|
||||||
if ((vcpu != NULL) && (vcpu->arch.cur_context == SECURE_WORLD)) {
|
|
||||||
eptp = vm->arch_vm.sworld_eptp;
|
|
||||||
} else {
|
|
||||||
eptp = vm->arch_vm.nworld_eptp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
eptp = get_ept_entry(vm);
|
||||||
pgentry = lookup_address((uint64_t *)eptp, gpa, &pg_size, &vm->arch_vm.ept_mem_ops);
|
pgentry = lookup_address((uint64_t *)eptp, gpa, &pg_size, &vm->arch_vm.ept_mem_ops);
|
||||||
if (pgentry != NULL) {
|
if (pgentry != NULL) {
|
||||||
hpa = ((*pgentry & (~(pg_size - 1UL)))
|
hpa = ((*pgentry & (~(pg_size - 1UL)))
|
||||||
@ -158,3 +155,63 @@ void ept_del_mr(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa, uint64_t
|
|||||||
vcpu_make_request(vcpu, ACRN_REQUEST_EPT_FLUSH);
|
vcpu_make_request(vcpu, ACRN_REQUEST_EPT_FLUSH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pre: vm != NULL.
|
||||||
|
*/
|
||||||
|
void *get_ept_entry(struct acrn_vm *vm)
|
||||||
|
{
|
||||||
|
void *eptp;
|
||||||
|
struct acrn_vcpu *vcpu = vcpu_from_pid(vm, get_pcpu_id());
|
||||||
|
|
||||||
|
if ((vcpu != NULL) && (vcpu->arch.cur_context == SECURE_WORLD)) {
|
||||||
|
eptp = vm->arch_vm.sworld_eptp;
|
||||||
|
} else {
|
||||||
|
eptp = vm->arch_vm.nworld_eptp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eptp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pre vm != NULL && cb != NULL.
|
||||||
|
*/
|
||||||
|
void walk_ept_table(struct acrn_vm *vm, pge_handler cb)
|
||||||
|
{
|
||||||
|
const struct memory_ops *mem_ops = &vm->arch_vm.ept_mem_ops;
|
||||||
|
uint64_t *pml4e, *pdpte, *pde, *pte;
|
||||||
|
uint64_t i, j, k, m;
|
||||||
|
|
||||||
|
for (i = 0UL; i < PTRS_PER_PML4E; i++) {
|
||||||
|
pml4e = pml4e_offset((uint64_t *)get_ept_entry(vm), i << PML4E_SHIFT);
|
||||||
|
if (mem_ops->pgentry_present(*pml4e) == 0UL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (j = 0UL; j < PTRS_PER_PDPTE; j++) {
|
||||||
|
pdpte = pdpte_offset(pml4e, j << PDPTE_SHIFT);
|
||||||
|
if (mem_ops->pgentry_present(*pdpte) == 0UL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pdpte_large(*pdpte) != 0UL) {
|
||||||
|
cb(pdpte, PDPTE_SIZE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (k = 0UL; k < PTRS_PER_PDE; k++) {
|
||||||
|
pde = pde_offset(pdpte, k << PDE_SHIFT);
|
||||||
|
if (mem_ops->pgentry_present(*pde) == 0UL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pde_large(*pde) != 0UL) {
|
||||||
|
cb(pde, PDE_SIZE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (m = 0UL; m < PTRS_PER_PTE; m++) {
|
||||||
|
pte = pte_offset(pde, m << PTE_SHIFT);
|
||||||
|
if (mem_ops->pgentry_present(*pte) != 0UL) {
|
||||||
|
cb(pte, PTE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#define EPT_H
|
#define EPT_H
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef void (*pge_handler)(uint64_t *pgentry, uint64_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalid HPA is defined for error checking,
|
* Invalid HPA is defined for error checking,
|
||||||
* according to SDM vol.3A 4.1.4, the maximum
|
* according to SDM vol.3A 4.1.4, the maximum
|
||||||
@ -104,6 +106,28 @@ void ept_modify_mr(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa,
|
|||||||
void ept_del_mr(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa,
|
void ept_del_mr(struct acrn_vm *vm, uint64_t *pml4_page, uint64_t gpa,
|
||||||
uint64_t size);
|
uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get EPT pointer of the vm
|
||||||
|
*
|
||||||
|
* @param[in] vm the pointer that points to VM data structure
|
||||||
|
*
|
||||||
|
* @retval If the current context of vm is SECURE_WORLD, return EPT pointer of
|
||||||
|
* secure world, otherwise return EPT pointer of normal world.
|
||||||
|
*/
|
||||||
|
void *get_ept_entry(struct acrn_vm *vm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Walking through EPT table
|
||||||
|
*
|
||||||
|
* @param[in] vm the pointer that points to VM data structure
|
||||||
|
* @param[in] cb the pointer that points to walk_ept_table callback, the callback
|
||||||
|
* will be invoked when getting a present page entry from EPT, and
|
||||||
|
* the callback could get the page entry and page size parameters.
|
||||||
|
*
|
||||||
|
* @return None
|
||||||
|
*/
|
||||||
|
void walk_ept_table(struct acrn_vm *vm, pge_handler cb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief EPT misconfiguration handling
|
* @brief EPT misconfiguration handling
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user