mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 04:02:05 +00:00
uefi: init vlapic according to native lapic
this patch save native lapic configuration and restore it to vm0's vlapic before its running, then doing hpet timer interrupt injection through vlapic interface -- this will not mess up vlapic and we can see hpet timer interrupt coming continuously. Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
parent
a87757d602
commit
fcb95d02d6
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user