On 26.04.2012, at 23:45, Benjamin Herrenschmidt wrote: > >> +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 ? Yeah, on ppc64 these are local_irq_en/disable. On ppc32, they are nops, because there we don't distinguish between soft and hard irq enabled. > > 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. I jump through this hoop because in kernel/posix-cpu-timers.c:1288 the BUG_ON triggers, since irqs_disabled() is false, because they are hard, but not soft disabled (which is a combination that iiuc doesn't happen in normal Linux). > >> + 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 ? This is to actually enable interrupts for real, regardless of ppc64 and ppc32. In fact, the previous code was pretty buggy - it was running the handlers with interrupts disabled ;). Alex -- 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