Skip to content

Commit 2d6c754

Browse files
JasonChenCJjren1
authored andcommitted
mmu: refine the checking of entry present
- change the input param of check_page_table_present from struct map_params to page_table_type - check EPT present bits misconfiguration in check_page_table_present - change var "table_present" to more suitable name "entry_present" Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com> Acked-by: Tian, Kevin <kevin.tian@intel.com>
1 parent 60425f9 commit 2d6c754

File tree

2 files changed

+56
-28
lines changed

2 files changed

+56
-28
lines changed

hypervisor/arch/x86/mmu.c

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,30 @@ static bool check_mmu_1gb_support(struct map_params *map_params)
171171
return status;
172172
}
173173

174+
static inline uint32_t check_page_table_present(int page_table_type,
175+
uint64_t table_entry)
176+
{
177+
if (page_table_type == PTT_EPT) {
178+
table_entry &= (IA32E_EPT_R_BIT | IA32E_EPT_W_BIT |
179+
IA32E_EPT_X_BIT);
180+
/* RWX misconfiguration for:
181+
* - write-only
182+
* - write-execute
183+
* - execute-only (if cap not support)
184+
* no check for reserved bits
185+
*/
186+
if ((table_entry == IA32E_EPT_W_BIT) ||
187+
(table_entry == (IA32E_EPT_W_BIT | IA32E_EPT_X_BIT)) ||
188+
((table_entry == IA32E_EPT_X_BIT) &&
189+
!check_ept_x_only_support()))
190+
return PT_MISCFG_PRESENT;
191+
} else {
192+
table_entry &= (IA32E_COMM_P_BIT);
193+
}
194+
195+
return (table_entry) ? PT_PRESENT : PT_NOT_PRESENT;
196+
}
197+
174198
static uint32_t map_mem_region(void *vaddr, void *paddr,
175199
void *table_base, uint64_t attr, uint32_t table_level,
176200
int table_type, enum mem_map_request_type request_type)
@@ -345,19 +369,6 @@ static uint32_t fetch_page_table_offset(void *addr, uint32_t table_level)
345369
return table_offset;
346370
}
347371

348-
static inline uint32_t check_page_table_present(struct map_params *map_params,
349-
uint64_t table_entry)
350-
{
351-
if (map_params->page_table_type == PTT_EPT) {
352-
table_entry &= (IA32E_EPT_R_BIT | IA32E_EPT_W_BIT |
353-
IA32E_EPT_X_BIT);
354-
} else {
355-
table_entry &= (IA32E_COMM_P_BIT);
356-
}
357-
358-
return (table_entry) ? PT_PRESENT : PT_NOT_PRESENT;
359-
}
360-
361372
static int get_table_entry(void *addr, void *table_base,
362373
uint32_t table_level, uint64_t *table_entry)
363374
{
@@ -381,7 +392,7 @@ static void *walk_paging_struct(void *addr, void *table_base,
381392
{
382393
uint32_t table_offset;
383394
uint64_t table_entry;
384-
uint64_t table_present;
395+
uint64_t entry_present;
385396
/* if table_level == IA32E_PT Just return the same address
386397
* can't walk down any further
387398
*/
@@ -405,15 +416,15 @@ static void *walk_paging_struct(void *addr, void *table_base,
405416
/* Set table present bits to any of the
406417
* read/write/execute bits
407418
*/
408-
table_present = (IA32E_EPT_R_BIT | IA32E_EPT_W_BIT |
419+
entry_present = (IA32E_EPT_R_BIT | IA32E_EPT_W_BIT |
409420
IA32E_EPT_X_BIT);
410421
} else {
411422
/* Set table preset bits to P bit or r/w bit */
412-
table_present = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT);
423+
entry_present = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT);
413424
}
414425

415426
/* Determine if a valid entry exists */
416-
if ((table_entry & table_present) == 0) {
427+
if ((table_entry & entry_present) == 0) {
417428
/* No entry present - need to allocate a new table */
418429
sub_table_addr = alloc_paging_struct();
419430
/* Check to ensure memory available for this structure*/
@@ -431,7 +442,7 @@ static void *walk_paging_struct(void *addr, void *table_base,
431442
* sub-table
432443
*/
433444
MEM_WRITE64(table_base + table_offset,
434-
HVA2HPA(sub_table_addr) | table_present);
445+
HVA2HPA(sub_table_addr) | entry_present);
435446
} else {
436447
/* Get address of the sub-table */
437448
sub_table_addr = HPA2HVA(table_entry & IA32E_REF_MASK);
@@ -610,7 +621,7 @@ int obtain_last_page_table_entry(struct map_params *map_params,
610621
struct entry_params *entry, void *addr, bool direct)
611622
{
612623
uint64_t table_entry;
613-
uint32_t table_present = 0;
624+
uint32_t entry_present = 0;
614625
int ret = 0;
615626
/* Obtain the PML4 address */
616627
void *table_addr = direct ? (map_params->pml4_base)
@@ -620,8 +631,12 @@ int obtain_last_page_table_entry(struct map_params *map_params,
620631
ret = get_table_entry(addr, table_addr, IA32E_PML4, &table_entry);
621632
if (ret < 0)
622633
return ret;
623-
table_present = check_page_table_present(map_params, table_entry);
624-
if (table_present == PT_NOT_PRESENT) {
634+
entry_present = check_page_table_present(map_params->page_table_type,
635+
table_entry);
636+
if (entry_present == PT_MISCFG_PRESENT) {
637+
pr_err("Present bits misconfigurated");
638+
return -EINVAL;
639+
} else if (entry_present == PT_NOT_PRESENT) {
625640
/* PML4E not present, return PML4 base address */
626641
entry->entry_level = IA32E_PML4;
627642
entry->entry_base = table_addr;
@@ -638,8 +653,12 @@ int obtain_last_page_table_entry(struct map_params *map_params,
638653
ret = get_table_entry(addr, table_addr, IA32E_PDPT, &table_entry);
639654
if (ret < 0)
640655
return ret;
641-
table_present = check_page_table_present(map_params, table_entry);
642-
if (table_present == PT_NOT_PRESENT) {
656+
entry_present = check_page_table_present(map_params->page_table_type,
657+
table_entry);
658+
if (entry_present == PT_MISCFG_PRESENT) {
659+
pr_err("Present bits misconfigurated");
660+
return -EINVAL;
661+
} else if (entry_present == PT_NOT_PRESENT) {
643662
/* PDPTE not present, return PDPT base address */
644663
entry->entry_level = IA32E_PDPT;
645664
entry->entry_base = table_addr;
@@ -667,8 +686,12 @@ int obtain_last_page_table_entry(struct map_params *map_params,
667686
ret = get_table_entry(addr, table_addr, IA32E_PD, &table_entry);
668687
if (ret < 0)
669688
return ret;
670-
table_present = check_page_table_present(map_params, table_entry);
671-
if (table_present == PT_NOT_PRESENT) {
689+
entry_present = check_page_table_present(map_params->page_table_type,
690+
table_entry);
691+
if (entry_present == PT_MISCFG_PRESENT) {
692+
pr_err("Present bits misconfigurated");
693+
return -EINVAL;
694+
} else if (entry_present == PT_NOT_PRESENT) {
672695
/* PDE not present, return PDE base address */
673696
entry->entry_level = IA32E_PD;
674697
entry->entry_base = table_addr;
@@ -677,7 +700,6 @@ int obtain_last_page_table_entry(struct map_params *map_params,
677700
entry->entry_off = fetch_page_table_offset(addr, IA32E_PD);
678701
entry->entry_val = table_entry;
679702
return 0;
680-
681703
}
682704
if (table_entry & IA32E_PDE_PS_BIT) {
683705
/* 2MB page size, return the base addr of the pg entry*/
@@ -695,8 +717,13 @@ int obtain_last_page_table_entry(struct map_params *map_params,
695717
ret = get_table_entry(addr, table_addr, IA32E_PT, &table_entry);
696718
if (ret < 0)
697719
return ret;
698-
table_present = check_page_table_present(map_params, table_entry);
699-
entry->entry_present = ((table_present == PT_PRESENT)
720+
entry_present = check_page_table_present(map_params->page_table_type,
721+
table_entry);
722+
if (entry_present == PT_MISCFG_PRESENT) {
723+
pr_err("Present bits misconfigurated");
724+
return -EINVAL;
725+
}
726+
entry->entry_present = ((entry_present == PT_PRESENT)
700727
? (PT_PRESENT):(PT_NOT_PRESENT));
701728
entry->entry_level = IA32E_PT;
702729
entry->entry_base = table_addr;

hypervisor/include/arch/x86/mmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ enum _page_table_level {
280280
enum _page_table_present {
281281
PT_NOT_PRESENT = 0,
282282
PT_PRESENT = 1,
283+
PT_MISCFG_PRESENT = 2,
283284
};
284285

285286
/* Page size */

0 commit comments

Comments
 (0)