> +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; > +} That is -very- gross ... I suppose it works but yuck :-) > +static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, > + unsigned int exit_nr) > +{ > + struct pt_regs regs; > + > + switch (exit_nr) { > + case BOOK3S_INTERRUPT_EXTERNAL: > + case BOOK3S_INTERRUPT_EXTERNAL_LEVEL: > + case BOOK3S_INTERRUPT_EXTERNAL_HV: > + kvmppc_fill_pt_regs(®s); > + soft_irq_disable(); > + do_IRQ(®s); > + soft_irq_enable(); What are those soft_irq_disable/enable ? They look like sometimes local_irq_disable/enable and sometimes something else ? If you are hard disabled already (which you should be) and want to "mark" things as soft disabled, I suppose that will work except that you'll be missing PACA_IRQ_HARD_DIS in irq_happened, so local_irq_enable() will not hard-enable. > + break; > + case BOOK3S_INTERRUPT_DECREMENTER: > + case BOOK3S_INTERRUPT_HV_DECREMENTER: > + kvmppc_fill_pt_regs(®s); > + soft_irq_disable(); > + timer_interrupt(®s); > + soft_irq_enable(); > + break; Same. > + case BOOK3S_INTERRUPT_MACHINE_CHECK: > + /* FIXME */ > + break; > + case BOOK3S_INTERRUPT_PERFMON: > + kvmppc_fill_pt_regs(®s); > + soft_irq_disable(); > + performance_monitor_exception(®s); > + soft_irq_enable(); > + break; Same. > + } > +} > + > int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, > unsigned int exit_nr) > { > @@ -548,6 +602,10 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, > run->exit_reason = KVM_EXIT_UNKNOWN; > run->ready_for_interrupt_injection = 1; > > + /* restart interrupts if they were meant for the host */ > + kvmppc_restart_interrupt(vcpu, exit_nr); > + __hard_irq_enable(); > + I suppose that's to work around the above comment about missing PACA_IRQ_HARD_DIS ? > trace_kvm_book3s_exit(exit_nr, vcpu); > preempt_enable(); > kvm_resched(vcpu); > diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S > index 6bae0a9..3a78b46 100644 > --- a/arch/powerpc/kvm/book3s_segment.S > +++ b/arch/powerpc/kvm/book3s_segment.S > @@ -308,28 +308,6 @@ no_dcbz32_off: > > #endif /* CONFIG_PPC_BOOK3S_64 */ > > - /* > - * For some interrupts, we need to call the real Linux > - * handler, so it can do work for us. This has to happen > - * as if the interrupt arrived from the kernel though, > - * so let's fake it here where most state is restored. > - * > - * Having set up SRR0/1 with the address where we want > - * to continue with relocation on (potentially in module > - * space), we either just go straight there with rfi[d], > - * or we jump to an interrupt handler with bctr if there > - * is an interrupt to be handled first. In the latter > - * case, the rfi[d] at the end of the interrupt handler > - * will get us back to where we want to continue. > - */ > - > - cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL > - beq 1f > - cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER > - beq 1f > - cmpwi r12, BOOK3S_INTERRUPT_PERFMON > -1: mtctr r12 > - > /* Register usage at this point: > * > * R1 = host R1 > @@ -348,7 +326,6 @@ no_dcbz32_off: > /* Load highmem handler address */ > mtsrr0 r8 > > - /* RFI into the highmem handler, or jump to interrupt handler */ > - beqctr > + /* RFI into the highmem handler */ > RFI > kvmppc_handler_trampoline_exit_end: Cheers, Ben. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html