mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-26 07:21:37 +00:00
mmu:create temporary page tables for guest at run time
Before this patch, guest temporary page tables were generated by hardcode at compile time, HV will copy this page tables to guest before guest launch. This patch creates temporary page tables at runtime for the range of 0~4G, and create page tables to cover new range(511G~511G+16M) with trusty requirement. Signed-off-by: Mingqiang Chi <mingqiang.chi@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:
parent
4d0f26d0e1
commit
9aa9a77457
@ -162,36 +162,4 @@ cpu_secondary_pdt_addr:
|
||||
address = address + 0x200000
|
||||
.endr
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* GUEST initial 4G page table
|
||||
*
|
||||
* guest starts with long mode, HV needs to prepare Guest identity
|
||||
* mapped page table.
|
||||
*
|
||||
* guest page tables covers 4G size, with 2M page size.
|
||||
*
|
||||
* HV copy this page table (6 pages) to guest address
|
||||
* CPU_Boot_Page_Tables_Start_VM before executing guest instruction.
|
||||
*
|
||||
******************************************************************/
|
||||
.align CPU_PAGE_SIZE
|
||||
.global CPU_Boot_Page_Tables_Start_VM
|
||||
CPU_Boot_Page_Tables_Start_VM:
|
||||
.quad vm_cpu_pdpt_addr + (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT)
|
||||
.align CPU_PAGE_SIZE
|
||||
vm_cpu_pdpt_addr:
|
||||
address = 0
|
||||
.rept 4
|
||||
.quad vm_cpu_pdt_addr + address + (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT)
|
||||
address = address + CPU_PAGE_SIZE
|
||||
.endr
|
||||
.align CPU_PAGE_SIZE
|
||||
vm_cpu_pdt_addr:
|
||||
address = 0
|
||||
.rept 2048
|
||||
.quad address + (IA32E_PDPTE_PS_BIT | IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT)
|
||||
address = address + 0x200000
|
||||
.endr
|
||||
|
||||
.end
|
||||
|
@ -41,21 +41,6 @@
|
||||
|
||||
#define ACRN_DBG_EPT 6
|
||||
|
||||
void *create_guest_paging(struct vm *vm)
|
||||
{
|
||||
void *hva_dest;
|
||||
void *hva_src;
|
||||
|
||||
/* copy guest identity mapped 4G page table to guest */
|
||||
hva_dest = GPA2HVA(vm,
|
||||
(uint64_t)CPU_Boot_Page_Tables_Start_VM);
|
||||
hva_src = (void *)(_ld_cpu_secondary_reset_load
|
||||
+ (CPU_Boot_Page_Tables_Start_VM
|
||||
- _ld_cpu_secondary_reset_start));
|
||||
/* 2MB page size, need to copy 6 pages */
|
||||
memcpy_s(hva_dest, 6 * CPU_PAGE_SIZE, hva_src, 6 * CPU_PAGE_SIZE);
|
||||
return (void *)CPU_Boot_Page_Tables_Start_VM;
|
||||
}
|
||||
|
||||
static uint64_t find_next_table(uint32_t table_offset, void *table_base)
|
||||
{
|
||||
|
@ -335,3 +335,132 @@ int prepare_vm0_memmap_and_e820(struct vm *vm)
|
||||
CONFIG_RAM_SIZE, MAP_UNMAP, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* GUEST initial page table
|
||||
*
|
||||
* guest starts with long mode, HV needs to prepare Guest identity
|
||||
* mapped page table.
|
||||
* For SOS:
|
||||
* Guest page tables cover 0~4G space with 2M page size, will use
|
||||
* 6 pages memory for page tables.
|
||||
* For UOS(Trusty not enabled):
|
||||
* Guest page tables cover 0~4G space with 2M page size, will use
|
||||
* 6 pages memory for page tables.
|
||||
* For UOS(Trusty enabled):
|
||||
* Guest page tables cover 0~4G and trusy memory space with 2M page size,
|
||||
* will use 7 pages memory for page tables.
|
||||
* This API assume that the trusty memory is remapped to guest physical address
|
||||
* of 511G to 511G + 16MB
|
||||
*
|
||||
* FIXME: here using hard code GUEST_INIT_PAGE_TABLE_START as guest init page
|
||||
* table gpa start, and it will occupy at most GUEST_INIT_PT_PAGE_NUM pages.
|
||||
* Some check here:
|
||||
* - guest page table space should not override cpu_secondary_reset code area
|
||||
* (it's a little tricky here, as under current identical mapping, HV & SOS
|
||||
* share same memory under 1M; under uefi boot mode, the defered AP startup
|
||||
* need cpu_secondary_reset code area which reserved by uefi stub keep there
|
||||
* no change even after SOS startup)
|
||||
* - guest page table space should not override possible RSDP fix segment
|
||||
*
|
||||
* Anyway, it's a tmp solution, the init page tables should be totally removed
|
||||
* after guest realmode/32bit no paging mode got supported.
|
||||
******************************************************************/
|
||||
#define GUEST_INIT_PAGE_TABLE_SKIP_SIZE 0x8000UL
|
||||
#define GUEST_INIT_PAGE_TABLE_START (CONFIG_LOW_RAM_START + \
|
||||
GUEST_INIT_PAGE_TABLE_SKIP_SIZE)
|
||||
#define GUEST_INIT_PT_PAGE_NUM 7
|
||||
#define RSDP_F_ADDR 0xE0000
|
||||
uint64_t create_guest_initial_paging(struct vm *vm)
|
||||
{
|
||||
uint64_t i = 0;
|
||||
uint64_t entry = 0;
|
||||
uint64_t entry_num = 0;
|
||||
uint64_t pdpt_base_paddr = 0;
|
||||
uint64_t pd_base_paddr = 0;
|
||||
uint64_t table_present = 0;
|
||||
uint64_t table_offset = 0;
|
||||
void *addr = NULL;
|
||||
void *pml4_addr = GPA2HVA(vm, GUEST_INIT_PAGE_TABLE_START);
|
||||
|
||||
_Static_assert((GUEST_INIT_PAGE_TABLE_START + 7 * PAGE_SIZE_4K) <
|
||||
RSDP_F_ADDR, "RSDP fix segment could be override");
|
||||
|
||||
if (GUEST_INIT_PAGE_TABLE_SKIP_SIZE <
|
||||
(unsigned long)&_ld_cpu_secondary_reset_size) {
|
||||
panic("guest init PTs override cpu_secondary_reset code");
|
||||
}
|
||||
|
||||
/* Using continuous memory for guest page tables, the total 4K page
|
||||
* number for it(without trusty) is GUEST_INIT_PT_PAGE_NUM-1.
|
||||
* here make sure they are init as 0 (page entry no present)
|
||||
*/
|
||||
memset(pml4_addr, 0, PAGE_SIZE_4K * GUEST_INIT_PT_PAGE_NUM-1);
|
||||
|
||||
/* Write PML4E */
|
||||
table_present = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT);
|
||||
/* PML4 used 1 page, skip it to fetch PDPT */
|
||||
pdpt_base_paddr = GUEST_INIT_PAGE_TABLE_START + PAGE_SIZE_4K;
|
||||
entry = pdpt_base_paddr | table_present;
|
||||
MEM_WRITE64(pml4_addr, entry);
|
||||
|
||||
/* Write PDPTE, PDPT used 1 page, skip it to fetch PD */
|
||||
pd_base_paddr = pdpt_base_paddr + PAGE_SIZE_4K;
|
||||
addr = pml4_addr + PAGE_SIZE_4K;
|
||||
/* Guest page tables cover 0~4G space with 2M page size */
|
||||
for (i = 0; i < 4; i++) {
|
||||
entry = ((pd_base_paddr + (i * PAGE_SIZE_4K))
|
||||
| table_present);
|
||||
MEM_WRITE64(addr, entry);
|
||||
addr += IA32E_COMM_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* Write PDE, PT used 4 pages */
|
||||
table_present = (IA32E_PDPTE_PS_BIT
|
||||
| IA32E_COMM_P_BIT
|
||||
| IA32E_COMM_RW_BIT);
|
||||
/* Totally 2048(512*4) entries with 2M page size for 0~4G*/
|
||||
entry_num = IA32E_NUM_ENTRIES * 4;
|
||||
addr = pml4_addr + 2 * PAGE_SIZE_4K;
|
||||
for (i = 0; i < entry_num; i++) {
|
||||
entry = (i * (1 << MMU_PDE_PAGE_SHIFT)) | table_present;
|
||||
MEM_WRITE64(addr, entry);
|
||||
addr += IA32E_COMM_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* For UOS, if trusty is enabled,
|
||||
* need to setup tempory page table for trusty
|
||||
* FIXME: this is a tempory solution for trusty enabling,
|
||||
* the final solution is that vSBL will setup guest page tables
|
||||
*/
|
||||
if (vm->sworld_control.sworld_enabled && !is_vm0(vm)) {
|
||||
/* clear page entry for trusty */
|
||||
memset(pml4_addr + 6 * PAGE_SIZE_4K, 0, PAGE_SIZE_4K);
|
||||
|
||||
/* Write PDPTE for trusy memory, PD will use 7th page */
|
||||
pd_base_paddr = GUEST_INIT_PAGE_TABLE_START +
|
||||
(6 * PAGE_SIZE_4K);
|
||||
table_offset =
|
||||
IA32E_PDPTE_INDEX_CALC(TRUSTY_EPT_REBASE_GPA);
|
||||
addr = (pml4_addr + PAGE_SIZE_4K + table_offset);
|
||||
table_present = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT);
|
||||
entry = (pd_base_paddr | table_present);
|
||||
MEM_WRITE64(addr, entry);
|
||||
|
||||
/* Write PDE for trusty with 2M page size */
|
||||
entry_num = TRUSTY_MEMORY_SIZE / (1 << MMU_PDE_PAGE_SHIFT);
|
||||
addr = pml4_addr + 6 * PAGE_SIZE_4K;
|
||||
table_present = (IA32E_PDPTE_PS_BIT
|
||||
| IA32E_COMM_P_BIT
|
||||
| IA32E_COMM_RW_BIT);
|
||||
for (i = 0; i < entry_num; i++) {
|
||||
entry = (TRUSTY_EPT_REBASE_GPA +
|
||||
(i * (1 << MMU_PDE_PAGE_SHIFT)))
|
||||
| table_present;
|
||||
MEM_WRITE64(addr, entry);
|
||||
addr += IA32E_COMM_ENTRY_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return GUEST_INIT_PAGE_TABLE_START;
|
||||
}
|
||||
|
@ -98,9 +98,10 @@ int create_vcpu(int cpu_id, struct vm *vm, struct vcpu **rtn_vcpu_handle)
|
||||
/* Is this VCPU a VM BSP, create page hierarchy for this VM */
|
||||
if (is_vcpu_bsp(vcpu)) {
|
||||
/* Set up temporary guest page tables */
|
||||
vm->arch_vm.guest_pml4 = create_guest_paging(vm);
|
||||
vm->arch_vm.guest_init_pml4 = create_guest_initial_paging(vm);
|
||||
pr_info("VM *d VCPU %d CR3: 0x%016llx ",
|
||||
vm->attr.id, vcpu->vcpu_id, vm->arch_vm.guest_pml4);
|
||||
vm->attr.id, vcpu->vcpu_id,
|
||||
vm->arch_vm.guest_init_pml4);
|
||||
}
|
||||
|
||||
/* Allocate VMCS region for this VCPU */
|
||||
|
@ -38,9 +38,6 @@
|
||||
|
||||
_Static_assert(NR_WORLD == 2, "Only 2 Worlds supported!");
|
||||
|
||||
/* Trusty EPT rebase gpa: 511G */
|
||||
#define TRUSTY_EPT_REBASE_GPA (511ULL*1024ULL*1024ULL*1024ULL)
|
||||
|
||||
#define TRUSTY_VERSION 1
|
||||
|
||||
struct trusty_startup_param {
|
||||
|
@ -270,7 +270,7 @@ static void init_guest_state(struct vcpu *vcpu)
|
||||
} else if (get_vcpu_mode(vcpu) == PAGE_PROTECTED_MODE) {
|
||||
cur_context->cr0 = ((uint64_t)CR0_PG | CR0_PE | CR0_NE);
|
||||
cur_context->cr4 = ((uint64_t)CR4_PSE | CR4_PAE | CR4_MCE | CR4_VMXE);
|
||||
cur_context->cr3 = (uint64_t)vm->arch_vm.guest_pml4 | CR3_PWT;
|
||||
cur_context->cr3 = vm->arch_vm.guest_init_pml4 | CR3_PWT;
|
||||
}
|
||||
|
||||
value = cur_context->cr0;
|
||||
|
@ -124,7 +124,7 @@ int load_guest(struct vm *vm, struct vcpu *vcpu)
|
||||
pr_info("VCPU%d Entry: 0x%llx, RSI: 0x%016llx, cr3: 0x%016llx",
|
||||
vcpu->vcpu_id, vcpu->entry_addr,
|
||||
cur_context->guest_cpu_regs.regs.rsi,
|
||||
vm->arch_vm.guest_pml4);
|
||||
vm->arch_vm.guest_init_pml4);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -43,6 +43,9 @@
|
||||
#define CPU_PAGE_SIZE 0x1000
|
||||
#define CPU_PAGE_MASK 0xFFFFFFFFFFFFF000
|
||||
|
||||
#define MMU_PTE_PAGE_SHIFT CPU_PAGE_SHIFT
|
||||
#define MMU_PDE_PAGE_SHIFT 21
|
||||
|
||||
/* Define CPU stack alignment */
|
||||
#define CPU_STACK_ALIGN 16
|
||||
|
||||
|
@ -113,7 +113,7 @@ struct vm_state_info {
|
||||
};
|
||||
|
||||
struct vm_arch {
|
||||
void *guest_pml4; /* Guest pml4 */
|
||||
uint64_t guest_init_pml4;/* Guest init pml4 */
|
||||
/* EPT hierarchy for Normal World */
|
||||
uint64_t nworld_eptp;
|
||||
/* EPT hierarchy for Secure World
|
||||
|
@ -381,7 +381,7 @@ extern uint8_t CPU_Boot_Page_Tables_Start_VM[];
|
||||
|
||||
/* External Interfaces */
|
||||
int is_ept_supported(void);
|
||||
void *create_guest_paging(struct vm *vm);
|
||||
uint64_t create_guest_initial_paging(struct vm *vm);
|
||||
void destroy_ept(struct vm *vm);
|
||||
uint64_t gpa2hpa(struct vm *vm, uint64_t gpa);
|
||||
uint64_t gpa2hpa_check(struct vm *vm, uint64_t gpa,
|
||||
|
@ -36,6 +36,10 @@
|
||||
#define MMC_PROD_NAME_WITH_PSN_LEN 15
|
||||
#define BUP_MKHI_BOOTLOADER_SEED_LEN 64
|
||||
|
||||
/* Trusty EPT rebase gpa: 511G */
|
||||
#define TRUSTY_EPT_REBASE_GPA (511ULL*1024ULL*1024ULL*1024ULL)
|
||||
#define TRUSTY_MEMORY_SIZE 0x01000000
|
||||
|
||||
/* Structure of seed info */
|
||||
struct seed_info {
|
||||
uint8_t cse_svn;
|
||||
|
Loading…
Reference in New Issue
Block a user