Skip to content

Commit

Permalink
uefi: init vlapic according to native lapic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
JasonChenCJ authored and jren1 committed May 15, 2018
1 parent a87757d commit fcb95d0
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 2 deletions.
25 changes: 25 additions & 0 deletions hypervisor/arch/x86/guest/vlapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
26 changes: 26 additions & 0 deletions hypervisor/arch/x86/intr_lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions hypervisor/arch/x86/intr_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
5 changes: 3 additions & 2 deletions hypervisor/arch/x86/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
24 changes: 24 additions & 0 deletions hypervisor/bsp/uefi/uefi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand All @@ -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
}
1 change: 1 addition & 0 deletions hypervisor/include/arch/x86/guest/vlapic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions hypervisor/include/arch/x86/lapic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit fcb95d0

Please sign in to comment.