> +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-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[KVM Development]
[KVM ARM]
[KVM ia64]
[Linux USB Devel]
[Linux Video]
[Linux Audio Users]
[Photo]
[Video Projectors]
[PDAs]
[Free Online Dating]
[Linux Kernel]
[Linux SCSI]
[XFree86]
[Big List of Linux Books]