All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power kernel
@ 2008-01-22 22:58 Jerone Young
  2008-01-23 23:31 ` [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power Hollis Blanchard
  0 siblings, 1 reply; 2+ messages in thread
From: Jerone Young @ 2008-01-22 22:58 UTC (permalink / raw)
  To: kvm-ppc

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1201042425 21600
# Node ID 7398b53dfa146c5d6931a2849bd597f43515f90c
# Parent  420601e87d0e0b09f0fbafd0c48ff67e5ac0bd46
Add Interrupt handling to kvm power kernel.

This patch adds initial interrupt handling code to the kvm
powerpc port.

The code works, but it a little slow. Need to do more debugging.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
--- a/arch/powerpc/boot/dts/bamboo.dts
+++ b/arch/powerpc/boot/dts/bamboo.dts
@@ -139,7 +139,7 @@
 		   		clock-frequency = <0>; /* Filled in by zImage */
 		   		current-speed = <1c200>;
 		   		interrupt-parent = <&UIC0>;
-		   		/* interrupts = <0 4>; */
+		   		interrupts = <0 4>;
 	   		};
 
 			UART1: serial@ef600400 {
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -632,5 +632,8 @@ int kvmppc_emulate_instruction(struct kv
 	if ((emulated = EMULATE_DONE) && advance)
 		vcpu->arch.pc += 4; /* Advance past emulated instruction. */
 
+	if (vcpu->arch.pending_ee && (vcpu->arch.guest_msr & MSR_EE))
+		kvmppc_sync_interrupt(vcpu, PPC44x_INTERRUPT_EXTERNAL);
+	
 	return emulated;
 }
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -26,6 +26,7 @@
 #include <linux/vmalloc.h>
 #include <asm/cputable.h>
 #include <asm/cacheflush.h>
+#include <asm/uaccess.h>
 
 #include "44x_tlb.h"
 
@@ -129,13 +130,13 @@ int kvm_handle_exit(struct kvm_run *run,
 	int r = RESUME_HOST;
 
 	run->exit_reason = KVM_EXIT_UNKNOWN;
+	
+	run->ready_for_interrupt_injection = 1;
 
 	/* XXX need to enable interrupts for all this code */
 
 #if 0
 	printk("%d @ %x\n", exit_nr, vcpu->arch.pc);
-	if (vcpu->arch.pc = 0x55550000) {
-		kvmppc_dump_vcpu(vcpu);
 		return RESUME_HOST;
 	}
 #endif
@@ -814,8 +815,47 @@ int kvm_arch_vcpu_ioctl_translate(struct
 	return -ENOTSUPP;
 }
 
+void kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, 
+				struct kvm_interrupt *irq)
+{
+	if (vcpu->arch.guest_msr & MSR_EE) 
+		kvmppc_sync_interrupt(vcpu, PPC44x_INTERRUPT_EXTERNAL);	
+	else
+		vcpu->arch.pending_ee=1;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg)
+{
+	struct kvm_vcpu *vcpu = filp->private_data;
+	void __user *argp = (void __user *)arg;
+	long r;
+
+	switch (ioctl) {
+	case KVM_INTERRUPT: {
+		struct kvm_interrupt irq;
+		r = -EFAULT;
+		if (copy_from_user(&irq, argp, sizeof(irq)))
+			goto out;
+		kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+		r = 0;
+		break; 
+	}
+	default:
+		r = -EINVAL;
+	}
+
+out:
+	return r;
+}
+
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
+{
+	return -ENOTSUPP;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+                       unsigned int ioctl, unsigned long arg)
 {
 	long r;
 
@@ -827,24 +867,6 @@ long kvm_arch_vcpu_ioctl(struct file *fi
 	return r;
 }
 
-int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
-{
-	return -ENOTSUPP;
-}
-
-long kvm_arch_vm_ioctl(struct file *filp,
-                       unsigned int ioctl, unsigned long arg)
-{
-	long r;
-
-	switch (ioctl) {
-	default:
-		r = -EINVAL;
-	}
-
-	return r;
-}
-
 int kvm_arch_init(void *opaque)
 {
 	return 0;
diff --git a/include/asm-powerpc/kvm_host.h b/include/asm-powerpc/kvm_host.h
--- a/include/asm-powerpc/kvm_host.h
+++ b/include/asm-powerpc/kvm_host.h
@@ -125,6 +125,8 @@ struct kvm_vcpu_arch {
 
 	struct timer_list dec_timer;
 	int pending_dec;
+	int pending_ee; /* endicate pending external interrupts */
+
 };
 
 struct kvm_tlb {

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power
  2008-01-22 22:58 [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power kernel Jerone Young
@ 2008-01-23 23:31 ` Hollis Blanchard
  0 siblings, 0 replies; 2+ messages in thread
From: Hollis Blanchard @ 2008-01-23 23:31 UTC (permalink / raw)
  To: kvm-ppc

I'm concerned about taking two interrupts at once, which would clobber
SRR0/1. Consider this case (all within a single exit):

        PC = foo (somewhere in guest)
        <external interrupt>
        SRR0 = foo
        PC = 0x500
        <decrementer interrupt>
        SRR0 = 0x500
        PC = 0x900
        resume guest

Now you can never get back to PC=foo, since SRR0 was overwritten.

So we should probably only deliver an interrupt when considering all
pending interrupts. In other words, extend the test at the bottom of
kvm_handle_exit() that checks pending_dec.

We probably need to remove all callers of kvmppc_sync_interrupt() and
instead set the appropriate flag in a "pending" mask. Then, just before
returning to the guest, do something like this:

        can_deliver(vcpu, priority) {
                return vcpu->arch.msr & priority_enabled[priority];
        }

        priority = find_first_bit(vcpu->arch.pending);
        while (priority) {
                if (can_deliver(vcpu, priority)) {
                        interrupt = priority_to_interrupt[priority];
                        kvmppc_deliver_interrupt(interrupt);
                        break;
                }
                        
                priority = find_next_bit(vcpu->arch.pending, priority);
        }
        
"arch.pending" would need to be in priority order. According to the
architecture, when there are multiple exceptions pending (e.g. program
interrupt and decrementer and external all fire at the same time), there
is a well-defined list of priorities. Of course, we'd also need a table
of MSR masks to check, since you can disable all these things in the
MSR.

(Rename kvmppc_sync_interrupt() to kvmppc_deliver_interrupt(), since I
was wrong in thinking that we could handle synchronous interrupts
immediately and only defer asynchronous ones.)

Once you do that, kvm_vcpu_ioctl_interrupt() just becomes
        vcpu->arch.pending |= PRIORITY_EXTERNAL;
and all the magic happens on the subsequent KVM_RUN command. Well, I
guess we'd need to insert similar magic on the RUN path (the above was
on the "handle exit" path).

-- 
Hollis Blanchard
IBM Linux Technology Center



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-01-23 23:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-22 22:58 [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power kernel Jerone Young
2008-01-23 23:31 ` [kvm-ppc-devel] [PATCH] Add Interrupt handling to kvm power Hollis Blanchard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.