Skip to content

Commit a11a10f

Browse files
Xiangyang Wuwenlingz
authored andcommitted
HV:MM:gpa2hpa related error checking fix
In the current hypervisor design, when HPA is not found for the specified gpa by calling gpa2hpa or local_gpa2hpa, 0 will be returned as a error code, but 0 may be a valid HPA for vm0; error checking is missed when invoking gpa2hpa or local_gpa2hpa; when invoking lookup_address, the caller guarantees that parameter pointer pml4_page and pointer pg_size is not NULL. If local_gpa2hpa/gpa2hpa returns a invalid HPA, it means that this function fails to find the HPA of the specified gpa of vm. If local_gpa2hpa/gpa2hpa return value is a valid HPA, it means that this function have found the HPA of the specified gpa of vm. Each valid vm's EPTP is initialized during vm creating, vm's EPTP is valid until this vm is destroyed. So the caller can guarantee parameter pointer pml4_page is not NULL. The caller uses a temporary variable to store page size. So the caller can guarantee parameter pointer pg_size is not NULL. In this patch, define a invalid HPA for gpa2hpa and local_gpa2hpa;add some error checking when invoking local_gpa2hpa/gpa2hpa;add precondition for lookup_address function and remove redundant error checking. V1-->V2: Define INVALID_HPA as a invalid HPA for gpa2hpa and local_gpa2hpa; Updated related error checking when invoking gpa2hpa or local_gpa2hpa; V2-->V3: Add some debug information if specified gpa2hpa mapping doesn't exit and ept_mr_del is called; Update INVALID_HPA definition easier to be reviewed. V3-->V4: Add vm->id and gpa into pr_error; Add precondition to ept_mr_del to cover [gpa,gpa+size) unmapping case. V4-->V5: Update comments; Update pr_error message. Tracked-On: #1258 Signed-off-by: Xiangyang Wu <xiangyang.wu@linux.intel.com> Reviewed-by: Li, Fei1 <fei1.li@intel.com>
1 parent 041bd59 commit a11a10f

File tree

7 files changed

+67
-19
lines changed

7 files changed

+67
-19
lines changed

hypervisor/arch/x86/ept.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ void destroy_ept(struct vm *vm)
6060
if (vm->arch_vm.m2p != NULL)
6161
free_ept_mem((uint64_t *)vm->arch_vm.m2p);
6262
}
63-
63+
/* using return value INVALID_HPA as error code */
6464
uint64_t local_gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size)
6565
{
66-
uint64_t hpa = 0UL;
66+
uint64_t hpa = INVALID_HPA;
6767
uint64_t *pgentry, pg_size = 0UL;
6868
void *eptp;
6969
struct vcpu *vcpu = vcpu_from_pid(vm, get_cpu_id());
@@ -83,15 +83,19 @@ uint64_t local_gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size)
8383
pr_err("VM %d GPA2HPA: failed for gpa 0x%llx",
8484
vm->vm_id, gpa);
8585
}
86-
87-
if (size != NULL) {
86+
/**
87+
* If specified parameter size is not NULL and
88+
* the HPA of parameter gpa is found, pg_size shall
89+
* be returned through parameter size.
90+
*/
91+
if ((size != NULL) && (hpa != INVALID_HPA)) {
8892
*size = (uint32_t)pg_size;
8993
}
9094

9195
return hpa;
9296
}
9397

94-
/* using return value 0 as failure, make sure guest will not use hpa 0 */
98+
/* using return value INVALID_HPA as error code */
9599
uint64_t gpa2hpa(struct vm *vm, uint64_t gpa)
96100
{
97101
return local_gpa2hpa(vm, gpa, NULL);
@@ -264,7 +268,9 @@ void ept_mr_modify(struct vm *vm, uint64_t *pml4_page,
264268
vcpu_make_request(vcpu, ACRN_REQUEST_EPT_FLUSH);
265269
}
266270
}
267-
271+
/**
272+
* @pre [gpa,gpa+size) has been mapped into host physical memory region
273+
*/
268274
void ept_mr_del(struct vm *vm, uint64_t *pml4_page,
269275
uint64_t gpa, uint64_t size)
270276
{

hypervisor/arch/x86/guest/guest.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,10 @@ static inline uint32_t local_copy_gpa(struct vm *vm, void *h_ptr, uint64_t gpa,
336336
void *g_ptr;
337337

338338
hpa = local_gpa2hpa(vm, gpa, &pg_size);
339-
if (pg_size == 0U) {
340-
pr_err("GPA2HPA not found");
341-
return 0;
339+
if (hpa == INVALID_HPA) {
340+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping",
341+
__func__, vm->vm_id, gpa);
342+
return 0U;
342343
}
343344

344345
if (fix_pg_size != 0U) {

hypervisor/arch/x86/mmu.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ bool check_continuous_hpa(struct vm *vm, uint64_t gpa_arg, uint64_t size_arg)
292292
curr_hpa = gpa2hpa(vm, gpa);
293293
gpa += PAGE_SIZE_4K;
294294
next_hpa = gpa2hpa(vm, gpa);
295-
if (next_hpa != (curr_hpa + PAGE_SIZE_4K)) {
295+
if ((curr_hpa == INVALID_HPA) || (next_hpa == INVALID_HPA)
296+
|| (next_hpa != (curr_hpa + PAGE_SIZE_4K))) {
296297
return false;
297298
}
298299
size -= PAGE_SIZE_4K;

hypervisor/arch/x86/pagetable.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,15 +417,14 @@ void mmu_add(uint64_t *pml4_page, uint64_t paddr_base,
417417
}
418418
}
419419

420+
/**
421+
* @pre (pml4_page != NULL) && (pg_size != NULL)
422+
*/
420423
uint64_t *lookup_address(uint64_t *pml4_page,
421424
uint64_t addr, uint64_t *pg_size, enum _page_table_type ptt)
422425
{
423426
uint64_t *pml4e, *pdpte, *pde, *pte;
424427

425-
if ((pml4_page == NULL) || (pg_size == NULL)) {
426-
return NULL;
427-
}
428-
429428
pml4e = pml4e_offset(pml4_page, addr);
430429
if (pgentry_present(ptt, *pml4e) == 0UL) {
431430
return NULL;

hypervisor/arch/x86/trusty.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static void create_secure_world_ept(struct vm *vm, uint64_t gpa_orig,
6363
uint64_t nworld_pml4e;
6464
uint64_t sworld_pml4e;
6565
uint64_t gpa;
66+
/* Check the HPA of parameter gpa_orig when invoking check_continuos_hpa */
6667
uint64_t hpa = gpa2hpa(vm, gpa_orig);
6768
uint64_t table_present = EPT_RWX;
6869
uint64_t pdpte, *dest_pdpte_p, *src_pdpte_p;
@@ -76,7 +77,10 @@ static void create_secure_world_ept(struct vm *vm, uint64_t gpa_orig,
7677
return;
7778
}
7879

79-
/* Check the physical address should be continuous */
80+
/**
81+
* Check the HPA of parameter gpa_orig should exist
82+
* Check the physical address should be continuous
83+
*/
8084
if (!check_continuous_hpa(vm, gpa_orig, size)) {
8185
ASSERT(false, "The physical addr is not continuous for Trusty");
8286
return;

hypervisor/common/hypercall.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,9 @@ int32_t hcall_set_ioreq_buffer(struct vm *vm, uint16_t vmid, uint64_t param)
371371
vmid, iobuf.req_buf);
372372

373373
hpa = gpa2hpa(vm, iobuf.req_buf);
374-
if (hpa == 0UL) {
375-
pr_err("%s: invalid GPA.\n", __func__);
374+
if (hpa == INVALID_HPA) {
375+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
376+
__func__, vm->vm_id, iobuf.req_buf);
376377
target_vm->sw.io_shared_page = NULL;
377378
return -EINVAL;
378379
}
@@ -437,6 +438,11 @@ static int32_t local_set_vm_memory_region(struct vm *vm,
437438
pml4_page = (uint64_t *)target_vm->arch_vm.nworld_eptp;
438439
if (region->type != MR_DEL) {
439440
hpa = gpa2hpa(vm, region->vm0_gpa);
441+
if (hpa == INVALID_HPA) {
442+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
443+
__func__, vm->vm_id, region->vm0_gpa);
444+
return -EINVAL;
445+
}
440446
base_paddr = get_hv_image_base();
441447
if (((hpa <= base_paddr) &&
442448
((hpa + region->size) > base_paddr)) ||
@@ -558,6 +564,11 @@ static int32_t write_protect_page(struct vm *vm, struct wp_data *wp)
558564
uint64_t prot_clr;
559565

560566
hpa = gpa2hpa(vm, wp->gpa);
567+
if (hpa == INVALID_HPA) {
568+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
569+
__func__, vm->vm_id, wp->gpa);
570+
return -EINVAL;
571+
}
561572
dev_dbg(ACRN_DBG_HYCALL, "[vm%d] gpa=0x%x hpa=0x%x",
562573
vm->vm_id, wp->gpa, hpa);
563574

@@ -666,6 +677,11 @@ int32_t hcall_gpa_to_hpa(struct vm *vm, uint16_t vmid, uint64_t param)
666677
return -1;
667678
}
668679
v_gpa2hpa.hpa = gpa2hpa(target_vm, v_gpa2hpa.gpa);
680+
if (v_gpa2hpa.hpa == INVALID_HPA) {
681+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
682+
__func__, target_vm->vm_id, v_gpa2hpa.gpa);
683+
return -EINVAL;
684+
}
669685
if (copy_to_gpa(vm, &v_gpa2hpa, param, sizeof(v_gpa2hpa)) != 0) {
670686
pr_err("%s: Unable copy param to vm\n", __func__);
671687
return -1;
@@ -985,8 +1001,9 @@ int32_t hcall_vm_intr_monitor(struct vm *vm, uint16_t vmid, uint64_t param)
9851001

9861002
/* the param for this hypercall is page aligned */
9871003
hpa = gpa2hpa(vm, param);
988-
if (hpa == 0UL) {
989-
pr_err("%s: invalid GPA.\n", __func__);
1004+
if (hpa == INVALID_HPA) {
1005+
pr_err("%s,vm[%hu] gpa 0x%llx,GPA is unmapping.",
1006+
__func__, vm->vm_id, param);
9901007
return -EINVAL;
9911008
}
9921009

hypervisor/include/arch/x86/mmu.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ void flush_vpid_single(uint16_t vpid);
9090
void flush_vpid_global(void);
9191
void invept(struct vcpu *vcpu);
9292
bool check_continuous_hpa(struct vm *vm, uint64_t gpa_arg, uint64_t size_arg);
93+
/**
94+
*@pre (pml4_page != NULL) && (pg_size != NULL)
95+
*/
9396
uint64_t *lookup_address(uint64_t *pml4_page, uint64_t addr,
9497
uint64_t *pg_size, enum _page_table_type ptt);
9598

@@ -125,15 +128,32 @@ static inline void clflush(volatile void *p)
125128
asm volatile ("clflush (%0)" :: "r"(p));
126129
}
127130

131+
/**
132+
* Invalid HPA is defined for error checking,
133+
* according to SDM vol.3A 4.1.4, the maximum
134+
* host physical address width is 52
135+
*/
136+
#define INVALID_HPA (0x1UL << 52U)
128137
/* External Interfaces */
129138
void destroy_ept(struct vm *vm);
139+
/**
140+
* @return INVALID_HPA - the HPA of parameter gpa is unmapping
141+
* @return hpa - the HPA of parameter gpa is hpa
142+
*/
130143
uint64_t gpa2hpa(struct vm *vm, uint64_t gpa);
144+
/**
145+
* @return INVALID_HPA - the HPA of parameter gpa is unmapping
146+
* @return hpa - the HPA of parameter gpa is hpa
147+
*/
131148
uint64_t local_gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size);
132149
uint64_t hpa2gpa(struct vm *vm, uint64_t hpa);
133150
void ept_mr_add(struct vm *vm, uint64_t *pml4_page, uint64_t hpa,
134151
uint64_t gpa, uint64_t size, uint64_t prot_orig);
135152
void ept_mr_modify(struct vm *vm, uint64_t *pml4_page, uint64_t gpa,
136153
uint64_t size, uint64_t prot_set, uint64_t prot_clr);
154+
/**
155+
* @pre [gpa,gpa+size) has been mapped into host physical memory region
156+
*/
137157
void ept_mr_del(struct vm *vm, uint64_t *pml4_page, uint64_t gpa,
138158
uint64_t size);
139159
void free_ept_mem(uint64_t *pml4_page);

0 commit comments

Comments
 (0)