From: Jan Kiszka <jan.kiszka@web.de>
To: Avi Kivity <avi@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: Blue Swirl <blauwirbel@gmail.com>,
Anthony Liguori <aliguori@us.ibm.com>,
qemu-devel <qemu-devel@nongnu.org>,
kvm@vger.kernel.org, "Michael S. Tsirkin" <mst@redhat.com>
Subject: [Qemu-devel] [RFC][PATCH 11/16] kvm: Introduce core services for in-kernel irqchip support
Date: Sat, 3 Dec 2011 12:17:36 +0100 [thread overview]
Message-ID: <e9e216ca54c76650382ff5f02f77a49b7cbd0af8.1322910904.git.jan.kiszka@web.de> (raw)
In-Reply-To: <cover.1322910904.git.jan.kiszka@web.de>
In-Reply-To: <cover.1322910904.git.jan.kiszka@web.de>
From: Jan Kiszka <jan.kiszka@siemens.com>
Add the basic infrastructure to active in-kernel irqchip support, inject
interrupts into these models, and maintain IRQ routes.
Routing is optional and depends on the host arch supporting
KVM_CAP_IRQ_ROUTING. When it's not available on x86, we loose the HPET
as we can't route GSI0 to IOAPIC pin 2.
In-kernel irqchip support will once be controlled by the machine
property 'kernel_irqchip', but this is not yet wired up.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
kvm.h | 8 +++
target-i386/kvm.c | 11 ++++
3 files changed, 168 insertions(+), 0 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index e7faf5c..a85e14f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -76,6 +76,13 @@ struct KVMState
int pit_in_kernel;
int xsave, xcrs;
int many_ioeventfds;
+ int irqchip_inject_ioctl;
+#ifdef KVM_CAP_IRQ_ROUTING
+ struct kvm_irq_routing *irq_routes;
+ int nr_allocated_irq_routes;
+ uint32_t *used_gsi_bitmap;
+ unsigned int max_gsi;
+#endif
};
KVMState *kvm_state;
@@ -692,6 +699,138 @@ static void kvm_handle_interrupt(CPUState *env, int mask)
}
}
+int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
+{
+ struct kvm_irq_level event;
+ int ret;
+
+ assert(s->irqchip_in_kernel);
+
+ event.level = level;
+ event.irq = irq;
+ ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event);
+ if (ret < 0) {
+ perror("kvm_set_irqchip_line");
+ abort();
+ }
+
+ return (s->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status;
+}
+
+#ifdef KVM_CAP_IRQ_ROUTING
+static void set_gsi(KVMState *s, unsigned int gsi)
+{
+ assert(gsi < s->max_gsi);
+
+ s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32);
+}
+
+static void kvm_init_irq_routing(KVMState *s)
+{
+ int gsi_count;
+
+ gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
+ if (gsi_count > 0) {
+ unsigned int gsi_bits, i;
+
+ /* Round up so we can search ints using ffs */
+ gsi_bits = (gsi_count + 31) / 32;
+ s->used_gsi_bitmap = g_malloc0(gsi_bits / 8);
+ s->max_gsi = gsi_bits;
+
+ /* Mark any over-allocated bits as already in use */
+ for (i = gsi_count; i < gsi_bits; i++) {
+ set_gsi(s, i);
+ }
+ }
+
+ s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
+ s->nr_allocated_irq_routes = 0;
+
+ kvm_arch_init_irq_routing(s);
+}
+
+static void kvm_add_routing_entry(KVMState *s,
+ struct kvm_irq_routing_entry *entry)
+{
+ struct kvm_irq_routing_entry *new;
+ int n, size;
+
+ if (s->irq_routes->nr == s->nr_allocated_irq_routes) {
+ n = s->nr_allocated_irq_routes * 2;
+ if (n < 64) {
+ n = 64;
+ }
+ size = sizeof(struct kvm_irq_routing);
+ size += n * sizeof(*new);
+ s->irq_routes = g_realloc(s->irq_routes, size);
+ s->nr_allocated_irq_routes = n;
+ }
+ n = s->irq_routes->nr++;
+ new = &s->irq_routes->entries[n];
+ memset(new, 0, sizeof(*new));
+ new->gsi = entry->gsi;
+ new->type = entry->type;
+ new->flags = entry->flags;
+ new->u = entry->u;
+
+ set_gsi(s, entry->gsi);
+}
+
+void kvm_irqchip_add_route(KVMState *s, int irq, int irqchip, int pin)
+{
+ struct kvm_irq_routing_entry e;
+
+ e.gsi = irq;
+ e.type = KVM_IRQ_ROUTING_IRQCHIP;
+ e.flags = 0;
+ e.u.irqchip.irqchip = irqchip;
+ e.u.irqchip.pin = pin;
+ kvm_add_routing_entry(s, &e);
+}
+
+int kvm_irqchip_commit_routes(KVMState *s)
+{
+ s->irq_routes->flags = 0;
+ return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
+}
+
+#else /* !KVM_CAP_IRQ_ROUTING */
+
+static void kvm_init_irq_routing(KVMState *s)
+{
+}
+#endif /* !KVM_CAP_IRQ_ROUTING */
+
+static int kvm_irqchip_create(KVMState *s)
+{
+ QemuOptsList *list = qemu_find_opts("machine");
+ int ret;
+
+ if (QTAILQ_EMPTY(&list->head) ||
+ !qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+ "kernel_irqchip", false) ||
+ !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
+ return 0;
+ }
+
+ ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
+ if (ret < 0) {
+ fprintf(stderr, "Create kernel irqchip failed\n");
+ return ret;
+ }
+
+ s->irqchip_inject_ioctl = KVM_IRQ_LINE;
+ if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) {
+ s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
+ }
+ s->irqchip_in_kernel = 1;
+
+ kvm_init_irq_routing(s);
+
+ return 0;
+}
+
int kvm_init(void)
{
static const char upgrade_note[] =
@@ -786,6 +925,11 @@ int kvm_init(void)
goto err;
}
+ ret = kvm_irqchip_create(s);
+ if (ret < 0) {
+ goto err;
+ }
+
kvm_state = s;
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
@@ -1111,6 +1255,11 @@ int kvm_has_many_ioeventfds(void)
return kvm_state->many_ioeventfds;
}
+int kvm_has_gsi_routing(void)
+{
+ return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index 243b063..0d6c453 100644
--- a/kvm.h
+++ b/kvm.h
@@ -51,6 +51,7 @@ int kvm_has_debugregs(void);
int kvm_has_xsave(void);
int kvm_has_xcrs(void);
int kvm_has_many_ioeventfds(void);
+int kvm_has_gsi_routing(void);
#ifdef NEED_CPU_H
int kvm_init_vcpu(CPUState *env);
@@ -124,6 +125,13 @@ void kvm_arch_reset_vcpu(CPUState *env);
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr);
int kvm_arch_on_sigbus(int code, void *addr);
+void kvm_arch_init_irq_routing(KVMState *s);
+
+int kvm_irqchip_set_irq(KVMState *s, int irq, int level);
+
+void kvm_irqchip_add_route(KVMState *s, int gsi, int irqchip, int pin);
+int kvm_irqchip_commit_routes(KVMState *s);
+
struct kvm_guest_debug;
struct kvm_debug_exit_arch;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9f07786..232c897 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1864,3 +1864,14 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env)
return !(env->cr[0] & CR0_PE_MASK) ||
((env->segs[R_CS].selector & 3) != 3);
}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+ if (!kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
+ /* If kernel can't do irq routing, interrupt source
+ * override 0->2 cannot be set up as required by HPET.
+ * So we have to disable it.
+ */
+ no_hpet = 1;
+ }
+}
--
1.7.3.4
next prev parent reply other threads:[~2011-12-03 11:18 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-03 11:17 [Qemu-devel] [RFC][PATCH 00/16] uq/master: Introduce basic irqchip support Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 01/16] msi: Generalize msix_supported to msi_supported Jan Kiszka
2011-12-04 10:42 ` Michael S. Tsirkin
2011-12-04 10:42 ` Jan Kiszka
2011-12-04 13:12 ` Avi Kivity
2011-12-04 13:16 ` Jan Kiszka
2011-12-04 13:26 ` Avi Kivity
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 02/16] kvm: Move kvmclock into hw/kvm folder Jan Kiszka
2011-12-03 19:00 ` Andreas Färber
2011-12-03 22:33 ` Jan Kiszka
2011-12-04 10:43 ` Avi Kivity
2011-12-04 10:46 ` Jan Kiszka
2011-12-05 10:43 ` Andreas Färber
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 03/16] apic: Stop timer on reset Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 04/16] apic: Factor out core for KVM reuse Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 05/16] apic: Open-code timer save/restore Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 06/16] i8259: Factor out core for KVM reuse Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 07/16] ioapic: Convert to memory API Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 08/16] ioapic: Reject non-dword accesses to IOWIN register Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 09/16] ioapic: Factor out core for KVM reuse Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 10/16] memory: Introduce memory_region_init_reservation Jan Kiszka
2011-12-04 13:20 ` Avi Kivity
2011-12-04 13:24 ` Jan Kiszka
2011-12-03 11:17 ` Jan Kiszka [this message]
2011-12-04 13:23 ` [Qemu-devel] [RFC][PATCH 11/16] kvm: Introduce core services for in-kernel irqchip support Avi Kivity
2011-12-04 13:27 ` Jan Kiszka
2011-12-04 13:28 ` Avi Kivity
2011-12-04 13:30 ` Jan Kiszka
2011-12-04 13:32 ` Avi Kivity
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 12/16] kvm: x86: Establish IRQ0 override control Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 13/16] kvm: x86: Add user space part for in-kernel APIC Jan Kiszka
2011-12-04 13:24 ` Avi Kivity
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 14/16] kvm: x86: Add user space part for in-kernel i8259 Jan Kiszka
2011-12-04 13:31 ` Avi Kivity
2011-12-04 13:42 ` Jan Kiszka
2011-12-04 13:49 ` Avi Kivity
2011-12-04 13:51 ` Jan Kiszka
2011-12-04 14:04 ` Avi Kivity
2011-12-04 14:06 ` Jan Kiszka
2011-12-04 15:12 ` Avi Kivity
2011-12-04 15:19 ` Jan Kiszka
2011-12-04 16:35 ` Avi Kivity
2011-12-04 21:31 ` Blue Swirl
2011-12-04 21:38 ` Jan Kiszka
2011-12-05 10:01 ` Avi Kivity
2011-12-05 11:37 ` Jan Kiszka
2011-12-05 12:36 ` Avi Kivity
2011-12-05 12:47 ` Jan Kiszka
2011-12-05 13:14 ` Avi Kivity
2011-12-05 13:29 ` Jan Kiszka
2011-12-05 13:36 ` Avi Kivity
2011-12-05 13:55 ` Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 15/16] kvm: x86: Add user space part for in-kernel IOAPIC Jan Kiszka
2011-12-03 11:17 ` [Qemu-devel] [RFC][PATCH 16/16] kvm: Arm in-kernel irqchip support Jan Kiszka
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=e9e216ca54c76650382ff5f02f77a49b7cbd0af8.1322910904.git.jan.kiszka@web.de \
--to=jan.kiszka@web.de \
--cc=aliguori@us.ibm.com \
--cc=avi@redhat.com \
--cc=blauwirbel@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=mst@redhat.com \
--cc=mtosatti@redhat.com \
--cc=qemu-devel@nongnu.org \
/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).