diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index cc66bbb8e..2a27d9b73 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -263,6 +263,51 @@ void set_ap_entry(struct vcpu *vcpu, uint64_t entry) vcpu_set_rip(vcpu, 0UL); } + +/* NOTE: set_bsp_real_mode_entry & set_bsp_protect_mode_regs is only temporary + * function called by UOS. Once we make UOS to use hypercall to set BSP entry, + * we will remove these two functions. + */ + +/* + * @pre reset_vcpu_regs is called in advance + */ +void set_bsp_real_mode_entry(struct vcpu *vcpu) +{ + struct ext_context *ectx; + + ectx = &(vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ext_ctx); + + ectx->cs.selector = REAL_MODE_BSP_INIT_CODE_SEL; + ectx->cs.base = 0x3ff0000UL; + vcpu_set_rip(vcpu, 0xFFF0UL); +} + +static struct acrn_vcpu_regs protect_mode_init_regs = { + .cs_ar = PROTECTED_MODE_CODE_SEG_AR, + .cs_sel = 0x10U, + .ss_sel = 0x18U, + .ds_sel = 0x18U, + .es_sel = 0x18U, + .cr0 = CR0_ET | CR0_NE | CR0_PE, + .cr3 = 0UL, + .cr4 = 0UL, +}; + +void set_bsp_protect_mode_regs(struct vcpu *vcpu) +{ + /* if vcpu is in protect mode, we need to set registers + * according to protect_init_regs first. + */ + uint32_t limit; + protect_mode_init_regs.gdt.base = create_guest_init_gdt(vcpu->vm, + &limit); + protect_mode_init_regs.gdt.limit = (uint16_t) (limit & 0xFFFFU); + set_vcpu_regs(vcpu, &protect_mode_init_regs); + + vcpu_set_rip(vcpu, (uint64_t)vcpu->entry_addr); +} + /*********************************************************************** * * @pre vm != NULL && rtn_vcpu_handle != NULL @@ -593,8 +638,7 @@ int prepare_vcpu(struct vm *vm, uint16_t pcpu_id) vcpu->arch_vcpu.cpu_mode = CPU_MODE_PROTECTED; #else if (is_vm0(vcpu->vm)) { - struct acrn_vcpu_regs *vm0_init_ctx = - (struct acrn_vcpu_regs *)(&vm0_boot_context); + struct acrn_vcpu_regs *vm0_init_ctx = &vm0_boot_context; /* VM0 bsp start mode is decided by the boot context * setup by bootloader / bios */ if ((vm0_init_ctx->ia32_efer & MSR_IA32_EFER_LMA_BIT) && diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index bedf4cfea..f978650c7 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -304,11 +304,11 @@ int reset_vm(struct vm *vm) foreach_vcpu(i, vm, vcpu) { reset_vcpu(vcpu); + + vcpu->arch_vcpu.cpu_mode = CPU_MODE_REAL; if (is_vcpu_bsp(vcpu)) { vm_sw_loader(vm, vcpu); } - - vcpu->arch_vcpu.cpu_mode = CPU_MODE_REAL; } vioapic_reset(vm_ioapic(vm)); diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index 90faead5a..864a34a60 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -673,8 +673,7 @@ static void init_guest_state(struct vcpu *vcpu) { struct cpu_context *ctx = &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context]; - struct acrn_vcpu_regs* init_ctx = - (struct acrn_vcpu_regs*)(&vm0_boot_context); + struct acrn_vcpu_regs* init_ctx = &vm0_boot_context; enum vm_cpu_mode vcpu_mode = get_vcpu_mode(vcpu); vcpu_set_rflags(vcpu, 0x2UL); /* Bit 1 is a active high reserved bit */ diff --git a/hypervisor/bsp/uefi/uefi.c b/hypervisor/bsp/uefi/uefi.c index dda032f9f..50af6e95a 100644 --- a/hypervisor/bsp/uefi/uefi.c +++ b/hypervisor/bsp/uefi/uefi.c @@ -39,8 +39,7 @@ void efi_spurious_handler(int vector) int uefi_sw_loader(struct vm *vm, struct vcpu *vcpu) { int ret = 0; - struct acrn_vcpu_regs *vcpu_regs = - (struct acrn_vcpu_regs *)&vm0_boot_context; + struct acrn_vcpu_regs *vcpu_regs = &vm0_boot_context; ASSERT(vm != NULL, "Incorrect argument"); diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index 87565705e..681d08c8a 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -88,21 +88,22 @@ static uint64_t create_zero_page(struct vm *vm) int load_guest(struct vm *vm, struct vcpu *vcpu) { int32_t ret = 0; - uint32_t i; void *hva; uint64_t lowmem_gpa_top; hva = gpa2hva(vm, GUEST_CFG_OFFSET); lowmem_gpa_top = *(uint64_t *)hva; - /* hardcode vcpu entry addr(kernel entry) & rsi (zeropage)*/ - for (i = 0U; i < NUM_GPRS; i++) { - vcpu_set_gpreg(vcpu, i, 0UL); - } - hva = gpa2hva(vm, lowmem_gpa_top - MEM_4K - MEM_2K); vcpu->entry_addr = (void *)(*((uint64_t *)hva)); + + if (get_vcpu_mode(vcpu) == CPU_MODE_REAL) { + set_bsp_real_mode_entry(vcpu); + } else { + set_bsp_protect_mode_regs(vcpu); + } + vcpu_set_gpreg(vcpu, CPU_REG_RSI, lowmem_gpa_top - MEM_4K); pr_info("%s, Set config according to predefined offset:", @@ -138,7 +139,7 @@ int general_sw_loader(struct vm *vm, struct vcpu *vcpu) } #endif - set_vcpu_regs(vcpu, (struct acrn_vcpu_regs *)&vm0_boot_context); + set_vcpu_regs(vcpu, &vm0_boot_context); /* calculate the kernel entry point */ zeropage = (struct zero_page *)sw_kernel->kernel_src_addr; diff --git a/hypervisor/include/arch/x86/guest/guest.h b/hypervisor/include/arch/x86/guest/guest.h index 9ea1430c0..de89d83e8 100644 --- a/hypervisor/include/arch/x86/guest/guest.h +++ b/hypervisor/include/arch/x86/guest/guest.h @@ -163,7 +163,7 @@ int copy_to_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva, uint32_t size, uint32_t *err_code, uint64_t *fault_addr); uint64_t create_guest_init_gdt(struct vm *vm, uint32_t *limit); -extern uint8_t vm0_boot_context; +extern struct acrn_vcpu_regs vm0_boot_context; #endif /* !ASSEMBLER */ diff --git a/hypervisor/include/arch/x86/guest/vcpu.h b/hypervisor/include/arch/x86/guest/vcpu.h index 1c4d3e1bd..9312bfaa0 100644 --- a/hypervisor/include/arch/x86/guest/vcpu.h +++ b/hypervisor/include/arch/x86/guest/vcpu.h @@ -288,6 +288,8 @@ void vcpu_set_pat_ext(struct vcpu *vcpu, uint64_t val); void set_vcpu_regs(struct vcpu *vcpu, struct acrn_vcpu_regs *vcpu_regs); void reset_vcpu_regs(struct vcpu *vcpu); void set_ap_entry(struct vcpu *vcpu, uint64_t entry); +void set_bsp_real_mode_entry(struct vcpu *vcpu); +void set_bsp_protect_mode_regs(struct vcpu *vcpu); static inline bool is_long_mode(struct vcpu *vcpu) {