KVM: PPC: booke: expose good state on irq reinject
When reinjecting an interrupt into the host interrupt handler after we're back in host kernel land, we need to tell the kernel where the interrupt happened. We can't tell it that we were in guest state, because that might lead to random code walking host addresses. So instead, we tell it that we came from the interrupt reinject code. This helps getting reasonable numbers out of perf. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Родитель
95f2e92144
Коммит
4e642ccbd6
|
@ -595,6 +595,48 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
|||
}
|
||||
}
|
||||
|
||||
static void kvmppc_fill_pt_regs(struct pt_regs *regs)
|
||||
{
|
||||
ulong r1, ip, msr, lr;
|
||||
|
||||
asm("mr %0, 1" : "=r"(r1));
|
||||
asm("mflr %0" : "=r"(lr));
|
||||
asm("mfmsr %0" : "=r"(msr));
|
||||
asm("bl 1f; 1: mflr %0" : "=r"(ip));
|
||||
|
||||
memset(regs, 0, sizeof(*regs));
|
||||
regs->gpr[1] = r1;
|
||||
regs->nip = ip;
|
||||
regs->msr = msr;
|
||||
regs->link = lr;
|
||||
}
|
||||
|
||||
static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu,
|
||||
unsigned int exit_nr)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
switch (exit_nr) {
|
||||
case BOOKE_INTERRUPT_EXTERNAL:
|
||||
kvmppc_fill_pt_regs(®s);
|
||||
do_IRQ(®s);
|
||||
break;
|
||||
case BOOKE_INTERRUPT_DECREMENTER:
|
||||
kvmppc_fill_pt_regs(®s);
|
||||
timer_interrupt(®s);
|
||||
break;
|
||||
#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64)
|
||||
case BOOKE_INTERRUPT_DOORBELL:
|
||||
kvmppc_fill_pt_regs(®s);
|
||||
doorbell_exception(®s);
|
||||
break;
|
||||
#endif
|
||||
case BOOKE_INTERRUPT_MACHINE_CHECK:
|
||||
/* FIXME */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* kvmppc_handle_exit
|
||||
*
|
||||
|
@ -608,24 +650,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|||
/* update before a new last_exit_type is rewritten */
|
||||
kvmppc_update_timing_stats(vcpu);
|
||||
|
||||
switch (exit_nr) {
|
||||
case BOOKE_INTERRUPT_EXTERNAL:
|
||||
do_IRQ(current->thread.regs);
|
||||
break;
|
||||
|
||||
case BOOKE_INTERRUPT_DECREMENTER:
|
||||
timer_interrupt(current->thread.regs);
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64)
|
||||
case BOOKE_INTERRUPT_DOORBELL:
|
||||
doorbell_exception(current->thread.regs);
|
||||
break;
|
||||
#endif
|
||||
case BOOKE_INTERRUPT_MACHINE_CHECK:
|
||||
/* FIXME */
|
||||
break;
|
||||
}
|
||||
/* restart interrupts if they were meant for the host */
|
||||
kvmppc_restart_interrupt(vcpu, exit_nr);
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче