diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index f5d10c925..b235872ba 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -299,7 +299,7 @@ void set_vcpu_regs(struct acrn_vcpu *vcpu, struct acrn_vcpu_regs *vcpu_regs) vcpu_regs->cr0); } -static struct acrn_vcpu_regs realmode_init_regs = { +static struct acrn_vcpu_regs realmode_init_vregs = { .gdt = { .limit = 0xFFFFU, .base = 0UL, @@ -318,9 +318,40 @@ static struct acrn_vcpu_regs realmode_init_regs = { .cr4 = 0UL, }; +static uint64_t init_vgdt[] = { + 0x0UL, + 0x0UL, + 0x00CF9B000000FFFFUL, /* Linear Code */ + 0x00CF93000000FFFFUL, /* Linear Data */ +}; + +static struct acrn_vcpu_regs protect_mode_init_vregs = { + .cs_ar = PROTECTED_MODE_CODE_SEG_AR, + .cs_limit = PROTECTED_MODE_SEG_LIMIT, + .cs_sel = 0x10U, + .cr0 = CR0_ET | CR0_NE | CR0_PE, + .ds_sel = 0x18U, + .ss_sel = 0x18U, + .es_sel = 0x18U, +}; + void reset_vcpu_regs(struct acrn_vcpu *vcpu) { - set_vcpu_regs(vcpu, &realmode_init_regs); + set_vcpu_regs(vcpu, &realmode_init_vregs); +} + +void init_vcpu_protect_mode_regs(struct acrn_vcpu *vcpu, uint64_t vgdt_base_gpa) +{ + struct acrn_vcpu_regs vcpu_regs; + + (void)memcpy_s((void*)&vcpu_regs, sizeof(struct acrn_vcpu_regs), + (void *)&protect_mode_init_vregs, sizeof(struct acrn_vcpu_regs)); + + vcpu_regs.gdt.base = vgdt_base_gpa; + vcpu_regs.gdt.limit = sizeof(init_vgdt) - 1U; + (void)copy_to_gpa(vcpu->vm, &init_vgdt, vgdt_base_gpa, sizeof(init_vgdt)); + + set_vcpu_regs(vcpu, &vcpu_regs); } void set_vcpu_startup_entry(struct acrn_vcpu *vcpu, uint64_t entry) diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index 0b964be3a..63187835a 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -17,18 +17,22 @@ #define NUM_REMAIN_1G_PAGES 3UL -static void prepare_bsp_gdt(struct acrn_vm *vm) +/* + * We put the guest init gdt after kernel/bootarg/ramdisk images. Suppose this is a + * safe place for guest init gdt of guest whatever the configuration is used by guest. + */ +static uint64_t get_guest_gdt_base_gpa(const struct acrn_vm *vm) { - size_t gdt_len; - uint64_t gdt_base_hpa; + uint64_t new_guest_gdt_base_gpa, guest_kernel_end_gpa, guest_bootargs_end_gpa, guest_ramdisk_end_gpa; - gdt_base_hpa = gpa2hpa(vm, boot_context.gdt.base); - if (boot_context.gdt.base != gdt_base_hpa) { - gdt_len = ((size_t)boot_context.gdt.limit + 1U) / sizeof(uint8_t); - (void)copy_to_gpa(vm, hpa2hva(boot_context.gdt.base), boot_context.gdt.base, gdt_len); - } + guest_kernel_end_gpa = (uint64_t)vm->sw.kernel_info.kernel_load_addr + vm->sw.kernel_info.kernel_size; + guest_bootargs_end_gpa = (uint64_t)vm->sw.bootargs_info.load_addr + vm->sw.bootargs_info.size; + guest_ramdisk_end_gpa = (uint64_t)vm->sw.ramdisk_info.load_addr + vm->sw.ramdisk_info.size; - return; + new_guest_gdt_base_gpa = max(guest_kernel_end_gpa, max(guest_bootargs_end_gpa, guest_ramdisk_end_gpa)); + new_guest_gdt_base_gpa = (new_guest_gdt_base_gpa + 7UL) & ~(8UL - 1UL); + + return new_guest_gdt_base_gpa; } /** @@ -181,8 +185,12 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm) pr_dbg("Loading guest to run-time location"); - prepare_bsp_gdt(vm); - set_vcpu_regs(vcpu, &boot_context); + /* + * TODO: + * - We need to initialize the guest bsp registers according to + * guest boot mode (real mode vs protect mode) + */ + init_vcpu_protect_mode_regs(vcpu, get_guest_gdt_base_gpa(vcpu->vm)); /* Copy the guest kernel image to its run-time location */ (void)copy_to_gpa(vm, sw_kernel->kernel_src_addr, diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index 775a751f3..3f56a0586 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -603,6 +603,18 @@ void set_vcpu_regs(struct acrn_vcpu *vcpu, struct acrn_vcpu_regs *vcpu_regs); */ void reset_vcpu_regs(struct acrn_vcpu *vcpu); +/** + * @brief Initialize the protect mode vcpu registers + * + * Initialize vCPU's all registers in run_context to initial protece mode values. + * + * @param[inout] vcpu pointer to vcpu data structure + * @param[in] vgdt_base_gpa guest physical address of gdt for guest + * + * @return None + */ +void init_vcpu_protect_mode_regs(struct acrn_vcpu *vcpu, uint64_t vgdt_base_gpa); + /** * @brief set the vCPU startup entry *