diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 26e055f1d..9b28b622f 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1608,6 +1608,31 @@ vlapic_init(struct vlapic *vlapic) vlapic_reset(vlapic); } +void vlapic_restore(struct vlapic *vlapic, struct lapic_regs *regs) +{ + struct lapic *lapic; + int i; + + lapic = vlapic->apic_page; + + lapic->tpr = regs->tpr; + lapic->apr = regs->apr; + lapic->ppr = regs->ppr; + lapic->ldr = regs->ldr; + lapic->dfr = regs->dfr; + for (i = 0; i < 8; i++) + lapic->tmr[i].val = regs->tmr[i]; + lapic->svr = regs->svr; + vlapic_svr_write_handler(vlapic); + lapic->lvt_timer = regs->lvtt; + lapic->lvt_lint0 = regs->lvt0; + lapic->lvt_lint1 = regs->lvt1; + lapic->lvt_error = regs->lvterr; + lapic->icr_timer = regs->ticr; + lapic->ccr_timer = regs->tccr; + lapic->dcr_timer = regs->tdcr; +} + void vlapic_cleanup(__unused struct vlapic *vlapic) { diff --git a/hypervisor/arch/x86/intr_lapic.c b/hypervisor/arch/x86/intr_lapic.c index 65e1ee526..f9eb07e39 100644 --- a/hypervisor/arch/x86/intr_lapic.c +++ b/hypervisor/arch/x86/intr_lapic.c @@ -266,6 +266,32 @@ int init_lapic(uint32_t cpu_id) return 0; } +void save_lapic(struct lapic_regs *regs) +{ + regs->id = read_lapic_reg32(LAPIC_ID_REGISTER); + regs->tpr = read_lapic_reg32(LAPIC_TASK_PRIORITY_REGISTER); + regs->apr = read_lapic_reg32(LAPIC_ARBITRATION_PRIORITY_REGISTER); + regs->ppr = read_lapic_reg32(LAPIC_PROCESSOR_PRIORITY_REGISTER); + regs->ldr = read_lapic_reg32(LAPIC_LOGICAL_DESTINATION_REGISTER); + regs->dfr = read_lapic_reg32(LAPIC_DESTINATION_FORMAT_REGISTER); + regs->tmr[0] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_0); + regs->tmr[1] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_1); + regs->tmr[2] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_2); + regs->tmr[3] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_3); + regs->tmr[4] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_4); + regs->tmr[5] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_5); + regs->tmr[6] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_6); + regs->tmr[7] = read_lapic_reg32(LAPIC_TRIGGER_MODE_REGISTER_7); + regs->svr = read_lapic_reg32(LAPIC_SPURIOUS_VECTOR_REGISTER); + regs->lvtt = read_lapic_reg32(LAPIC_LVT_TIMER_REGISTER); + regs->lvt0 = read_lapic_reg32(LAPIC_LVT_LINT0_REGISTER); + regs->lvt1 = read_lapic_reg32(LAPIC_LVT_LINT1_REGISTER); + regs->lvterr = read_lapic_reg32(LAPIC_LVT_ERROR_REGISTER); + regs->ticr = read_lapic_reg32(LAPIC_INITIAL_COUNT_REGISTER); + regs->tccr = read_lapic_reg32(LAPIC_CURRENT_COUNT_REGISTER); + regs->tdcr = read_lapic_reg32(LAPIC_DIVIDE_CONFIGURATION_REGISTER); +} + int send_lapic_eoi(void) { write_lapic_reg32(LAPIC_EOI_REGISTER, 0); diff --git a/hypervisor/arch/x86/intr_main.c b/hypervisor/arch/x86/intr_main.c index 7c824126a..8ee77391a 100644 --- a/hypervisor/arch/x86/intr_main.c +++ b/hypervisor/arch/x86/intr_main.c @@ -51,7 +51,9 @@ int interrupt_init(uint32_t cpu_id) if (status != 0) return -ENODEV; +#ifndef CONFIG_EFI_STUB CPU_IRQ_ENABLE(); +#endif return status; } diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index 91ff349fd..bf61b8743 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -1282,9 +1282,10 @@ static void override_uefi_vmcs(struct vcpu *vcpu) /* Interrupt */ field = VMX_GUEST_RFLAGS; - cur_context->rflags = 0x2; - cur_context->rflags |= 1 << 9; /* enable intr for efi stub */ + /* clear flags for CF/PF/AF/ZF/SF/OF */ + cur_context->rflags = efi_ctx->rflags & ~(0x8d5); exec_vmwrite(field, cur_context->rflags); + pr_dbg("VMX_GUEST_RFLAGS: 0x%016llx ", cur_context->rflags); } #endif diff --git a/hypervisor/bsp/uefi/uefi.c b/hypervisor/bsp/uefi/uefi.c index 44aa9a18c..0a1611283 100644 --- a/hypervisor/bsp/uefi/uefi.c +++ b/hypervisor/bsp/uefi/uefi.c @@ -56,11 +56,28 @@ uint32_t efi_physical_available_ap_bitmap = 0; uint32_t efi_wake_up_ap_bitmap = 0; struct efi_ctx* efi_ctx = NULL; +struct lapic_regs uefi_lapic_regs; extern uint32_t up_count; extern unsigned long pcpu_sync; void efi_spurious_handler(int vector) { + struct vcpu* vcpu; + int ret; + + if (get_cpu_id() != 0) + return; + + vcpu = per_cpu(vcpu, 0); + if (vcpu && vcpu->arch_vcpu.vlapic) { + ret = vlapic_set_intr(vcpu, vector, 0); + if (ret) + pr_err("%s vlapic set intr fail, interrupt lost\n", + __func__); + } else + pr_err("%s vcpu or vlapic is not ready, interrupt lost\n", + __func__); + return; } @@ -116,10 +133,15 @@ int uefi_sw_loader(struct vm *vm, struct vcpu *vcpu) if (!is_vm0(vm)) return load_guest(vm, vcpu); + vlapic_restore(vcpu->arch_vcpu.vlapic, &uefi_lapic_regs); + vcpu->entry_addr = efi_ctx->entry; cur_context->guest_cpu_regs.regs.rcx = efi_ctx->handle; cur_context->guest_cpu_regs.regs.rdx = efi_ctx->table; + /* defer irq enabling till vlapic is ready */ + CPU_IRQ_ENABLE(); + return ret; } #endif @@ -135,5 +157,7 @@ void init_bsp(void) vm_sw_loader = uefi_sw_loader; spurious_handler = efi_spurious_handler; + + save_lapic(&uefi_lapic_regs); #endif } diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index 752d3c0b1..0ef8eb93c 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -119,6 +119,7 @@ uint8_t vlapic_get_apicid(struct vlapic *vlapic); int vlapic_create(struct vcpu *vcpu); void vlapic_free(struct vcpu *vcpu); void vlapic_init(struct vlapic *vlapic); +void vlapic_restore(struct vlapic *vlapic, struct lapic_regs *regs); bool vlapic_enabled(struct vlapic *vlapic); uint64_t apicv_get_apic_access_addr(struct vm *vm); uint64_t apicv_get_apic_page_addr(struct vlapic *vlapic); diff --git a/hypervisor/include/arch/x86/lapic.h b/hypervisor/include/arch/x86/lapic.h index 494ffd5b0..9f955b5e5 100644 --- a/hypervisor/include/arch/x86/lapic.h +++ b/hypervisor/include/arch/x86/lapic.h @@ -161,6 +161,25 @@ union lapic_id { } x2apic; }; +struct lapic_regs { + uint32_t id; + uint32_t tpr; + uint32_t apr; + uint32_t ppr; + uint32_t ldr; + uint32_t dfr; + uint32_t tmr[8]; + uint32_t svr; + uint32_t lvtt; + uint32_t lvt0; + uint32_t lvt1; + uint32_t lvterr; + uint32_t ticr; + uint32_t tccr; + uint32_t tdcr; +}; + +void save_lapic(struct lapic_regs *regs); int early_init_lapic(void); int init_lapic(uint32_t cpu_id); int send_lapic_eoi(void);