From: Christoffer Dall <c.dall@virtualopensystems.com>
To: android-virt@lists.cs.columbia.edu, kvm@vger.kernel.org
Cc: tech@virtualopensystems.com
Subject: [PATCH v7 07/12] ARM: KVM: Inject IRQs and FIQs from userspace
Date: Mon, 12 Mar 2012 02:52:34 -0400 [thread overview]
Message-ID: <20120312065234.8074.29760.stgit@ubuntu> (raw)
In-Reply-To: <20120312065134.8074.36949.stgit@ubuntu>
From: Christoffer Dall <cdall@cs.columbia.edu>
Userspace can inject IRQs and FIQs through the KVM_IRQ_LINE VM ioctl.
This ioctl is used since the sematics are in fact two lines that can be
either raised or lowered on the VCPU - the IRQ and FIQ lines.
KVM needs to know which VCPU it must operate on and whether the FIQ or
IRQ line is raised/lowered. Hence both pieces of information is packed
in the kvm_irq_level->irq field. The irq fild value will be:
IRQ: vcpu_index << 1
FIQ: (vcpu_index << 1) | 1
This is documented in Documentation/kvm/api.txt.
The effect of the ioctl is simply to simply raise/lower the
corresponding irq_line field on the VCPU struct, which will cause the
world-switch code to raise/lower virtual interrupts when running the
guest on next switch. The wait_for_interrupt flag is also cleared for
raised IRQs or FIQs causing an idle VCPU to become active again. CPUs
in guest mode are kicked to make sure they refresh their interrupt status.
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
Documentation/virtual/kvm/api.txt | 12 +++++--
arch/arm/include/asm/kvm.h | 9 +++++
arch/arm/include/asm/kvm_arm.h | 1 +
arch/arm/kvm/arm.c | 62 ++++++++++++++++++++++++++++++++++++-
include/linux/kvm.h | 1 +
5 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 6386f8c..610e71b 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -582,15 +582,19 @@ only go to the IOAPIC. On ia64, a IOSAPIC is created.
4.25 KVM_IRQ_LINE
Capability: KVM_CAP_IRQCHIP
-Architectures: x86, ia64
+Architectures: x86, ia64, arm
Type: vm ioctl
Parameters: struct kvm_irq_level
Returns: 0 on success, -1 on error
Sets the level of a GSI input to the interrupt controller model in the kernel.
-Requires that an interrupt controller model has been previously created with
-KVM_CREATE_IRQCHIP. Note that edge-triggered interrupts require the level
-to be set to 1 and then back to 0.
+On some architectures it is required that an interrupt controller model has
+been previously created with KVM_CREATE_IRQCHIP. Note that edge-triggered
+interrupts require the level to be set to 1 and then back to 0.
+
+ARM uses two types of interrupt lines per CPU: IRQ and FIQ. The value of the
+irq field should be (vcpu_index << 1) for IRQs and ((vcpu_index << 1) | 1) for
+FIQs. Level is used to raise/lower the line.
struct kvm_irq_level {
union {
diff --git a/arch/arm/include/asm/kvm.h b/arch/arm/include/asm/kvm.h
index c8466b7..38ff1d6 100644
--- a/arch/arm/include/asm/kvm.h
+++ b/arch/arm/include/asm/kvm.h
@@ -20,6 +20,15 @@
#include <asm/types.h>
#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_IRQ_LINE
+
+/*
+ * KVM_IRQ_LINE macros to set/read IRQ/FIQ for specific VCPU index.
+ */
+enum KVM_ARM_IRQ_LINE_TYPE {
+ KVM_ARM_IRQ_LINE = 0,
+ KVM_ARM_FIQ_LINE = 1,
+};
/*
* Modes used for short-hand mode determinition in the world-switch code and
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 835abd1..e378a37 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -49,6 +49,7 @@
#define HCR_VM 1
#define HCR_GUEST_MASK (HCR_TSC | HCR_TWE | HCR_TWI | HCR_VM | HCR_AMO | \
HCR_AMO | HCR_IMO | HCR_FMO | HCR_SWIO)
+#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
/* Hyp System Control Register (HSCTLR) bits */
#define HSCTLR_TE (1 << 30)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 6926b01..a797984 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/mman.h>
#include <linux/sched.h>
+#include <linux/kvm.h>
#include <trace/events/kvm.h>
#define CREATE_TRACE_POINTS
@@ -244,6 +245,7 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
+ vcpu->cpu = cpu;
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -284,6 +286,51 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
return -EINVAL;
}
+static int kvm_arch_vm_ioctl_irq_line(struct kvm *kvm,
+ struct kvm_irq_level *irq_level)
+{
+ int mask;
+ unsigned int vcpu_idx;
+ struct kvm_vcpu *vcpu;
+ unsigned long old, new, *ptr;
+
+ vcpu_idx = irq_level->irq >> 1;
+ if (vcpu_idx >= KVM_MAX_VCPUS)
+ return -EINVAL;
+
+ vcpu = kvm_get_vcpu(kvm, vcpu_idx);
+ if (!vcpu)
+ return -EINVAL;
+
+ if ((irq_level->irq & 1) == KVM_ARM_IRQ_LINE)
+ mask = HCR_VI;
+ else /* KVM_ARM_FIQ_LINE */
+ mask = HCR_VF;
+
+ trace_kvm_set_irq(irq_level->irq, irq_level->level, 0);
+
+ ptr = (unsigned long *)&vcpu->arch.irq_lines;
+ do {
+ old = ACCESS_ONCE(*ptr);
+ if (irq_level->level)
+ new = old | mask;
+ else
+ new = old & ~mask;
+
+ if (new == old)
+ return 0; /* no change */
+ } while (cmpxchg(ptr, old, new) != old);
+
+ /*
+ * The vcpu irq_lines field was updated, wake up sleeping VCPUs and
+ * trigger a world-switch round on the running physical CPU to set the
+ * virtual IRQ/FIQ fields in the HCR appropriately.
+ */
+ kvm_vcpu_kick(vcpu);
+
+ return 0;
+}
+
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -298,7 +345,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
- return -EINVAL;
+ struct kvm *kvm = filp->private_data;
+ void __user *argp = (void __user *)arg;
+
+ switch (ioctl) {
+ case KVM_IRQ_LINE: {
+ struct kvm_irq_level irq_event;
+
+ if (copy_from_user(&irq_event, argp, sizeof irq_event))
+ return -EFAULT;
+ return kvm_arch_vm_ioctl_irq_line(kvm, &irq_event);
+ }
+ default:
+ return -EINVAL;
+ }
}
static void cpu_set_vector(void *vector)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 6c322a9..c012396 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -111,6 +111,7 @@ struct kvm_irq_level {
* ACPI gsi notion of irq.
* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
+ * For ARM: IRQ: irq = (2*vcpu_index). FIQ: irq = (2*vcpu_indx + 1).
*/
union {
__u32 irq;
next prev parent reply other threads:[~2012-03-12 6:52 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-12 6:51 [PATCH v7 00/12] KVM/ARM Implementation Christoffer Dall
2012-03-12 6:51 ` [PATCH v7 01/12] KVM: Introduce __KVM_HAVE_IRQ_LINE Christoffer Dall
2012-03-23 0:41 ` [PATCH] ARM: KVM: Check the cpuid we're being asked to emulate Rusty Russell
2012-05-14 22:57 ` Christoffer Dall
2012-05-16 23:58 ` Rusty Russell
2012-05-20 18:34 ` Christoffer Dall
2012-05-21 1:13 ` Rusty Russell
2012-03-12 6:52 ` [PATCH v7 02/12] KVM: Guard mmu_notifier specific code with CONFIG_MMU_NOTIFIER Christoffer Dall
2012-03-12 15:50 ` Avi Kivity
2012-03-12 6:52 ` [PATCH v7 03/12] ARM: KVM: Initial skeleton to compile KVM support Christoffer Dall
2012-03-12 6:52 ` [PATCH v7 04/12] ARM: KVM: Hypervisor identity mapping Christoffer Dall
2012-03-12 6:52 ` [PATCH v7 05/12] ARM: KVM: Hypervisor inititalization Christoffer Dall
2012-03-12 6:52 ` [PATCH v7 06/12] ARM: KVM: Memory virtualization setup Christoffer Dall
2012-03-12 6:52 ` Christoffer Dall [this message]
2012-03-12 6:52 ` [PATCH v7 08/12] ARM: KVM: World-switch implementation Christoffer Dall
2012-03-23 0:23 ` Rusty Russell
2012-03-28 13:05 ` Avi Kivity
2012-03-28 21:57 ` Rusty Russell
2012-03-29 10:49 ` Avi Kivity
2012-05-14 18:08 ` Christoffer Dall
2012-03-12 6:52 ` [PATCH v7 09/12] ARM: KVM: Emulation framework and CP15 emulation Christoffer Dall
2012-03-12 6:52 ` [PATCH v7 10/12] ARM: KVM: Handle guest faults in KVM Christoffer Dall
2012-03-12 15:31 ` [Android-virt] " Marc Zyngier
2012-03-12 16:23 ` Christoffer Dall
2012-03-12 16:28 ` Marc Zyngier
2012-03-12 6:53 ` [PATCH v7 11/12] ARM: KVM: Handle I/O aborts Christoffer Dall
2012-03-12 6:53 ` [PATCH v7 12/12] ARM: KVM: Guest wait-for-interrupts (WFI) support Christoffer Dall
2012-03-12 17:36 ` [PATCH v7 00/12] KVM/ARM Implementation Avi Kivity
2012-03-23 0:40 ` [PATCH] ARM: KVM: Remove l2ctlr write Rusty Russell
2012-05-14 22:59 ` Christoffer Dall
2012-03-29 5:11 ` [PATCH 0/3] Emulation cleanups Rusty, Russell <rusty.russell
2012-03-29 5:15 ` [PATCH 1/3] ARM: KVM: Remove l2ctlr write Rusty Russell
2012-03-29 5:17 ` [PATCH 2/3] ARM: KVM: Fake up performance counters a little more precisely Rusty Russell
2012-05-14 22:49 ` Christoffer Dall
2012-05-17 0:12 ` Rusty Russell
2012-03-29 5:17 ` [PATCH 3/3] ARM: KVM: Check the cpuid we're being asked to emulate Rusty Russell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120312065234.8074.29760.stgit@ubuntu \
--to=c.dall@virtualopensystems.com \
--cc=android-virt@lists.cs.columbia.edu \
--cc=kvm@vger.kernel.org \
--cc=tech@virtualopensystems.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).