Skip to contentSkip to conversation

qemu-kvm.git uq/master queue

GIT PULL In review Marcelo Tosatti 3 participants 23 messages Jan 20, 2012 – Nov 28, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

The following changes since commit 8c4ec5c0269bda18bb777a64b2008088d1c632dc:

pxa2xx_keypad: fix unbalanced parenthesis. (2012-01-17 02:14:42 +0100)

are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master

Jan Kiszka (18):
msi: Generalize msix_supported to msi_supported
kvm: Move kvmclock into hw/kvm folder
apic: Stop timer on reset
apic: Inject external NMI events via LINT1
apic: Introduce apic_report_irq_delivered
apic: Factor out base class for KVM reuse
apic: Open-code timer save/restore
i8259: Completely privatize PicState
i8259: Factor out base class for KVM reuse
ioapic: Drop post-load irr initialization
ioapic: Factor out base class for KVM reuse
memory: Introduce memory_region_init_reservation
kvm: Introduce core services for in-kernel irqchip support
kvm: x86: Establish IRQ0 override control
kvm: x86: Add user space part for in-kernel APIC
kvm: x86: Add user space part for in-kernel i8259
kvm: x86: Add user space part for in-kernel IOAPIC
kvm: Activate in-kernel irqchip support

Vadim Rozenfeld (2):
hyper-v: introduce Hyper-V support infrastructure.
hyper-v: initialize Hyper-V CPUID leaves.

 Makefile.objs                  |    2 +-
 Makefile.target                |    8 +-
 configure                      |    1 +
 cpus.c                         |    6 +-
 hw/apic.c                      |  356 ++++++----------------------------------
 hw/apic.h                      |    1 +
 hw/apic_common.c               |  302 ++++++++++++++++++++++++++++++++++
 hw/apic_internal.h             |  115 +++++++++++++
 hw/i8259.c                     |  163 ++++--------------
 hw/i8259_common.c              |  147 +++++++++++++++++
 hw/i8259_internal.h            |   76 +++++++++
 hw/ioapic.c                    |  142 ++--------------
 hw/ioapic_common.c             |  104 ++++++++++++
 hw/ioapic_internal.h           |   97 +++++++++++
 hw/kvm/apic.c                  |  138 ++++++++++++++++
 hw/{kvmclock.c => kvm/clock.c} |    4 +-
 hw/{kvmclock.h => kvm/clock.h} |    0
 hw/kvm/i8259.c                 |  128 ++++++++++++++
 hw/kvm/ioapic.c                |  114 +++++++++++++
 hw/msi.c                       |    8 +
 hw/msi.h                       |    2 +
 hw/msix.c                      |    9 +-
 hw/msix.h                      |    2 -
 hw/pc.c                        |   20 ++-
 hw/pc.h                        |    8 +-
 hw/pc_piix.c                   |   69 +++++++-
 kvm-all.c                      |  154 +++++++++++++++++
 kvm-stub.c                     |    5 +
 kvm.h                          |   14 ++
 memory.c                       |   36 ++++
 memory.h                       |   16 ++
 qemu-config.c                  |    4 +
 qemu-options.hx                |    5 +-
 sysemu.h                       |    1 -
 target-i386/cpuid.c            |   14 ++
 target-i386/hyperv.c           |   64 +++++++
 target-i386/hyperv.h           |   43 +++++
 target-i386/kvm.c              |  114 +++++++++++++-
 trace-events                   |    2 +-
 vl.c                           |    1 -
 40 files changed, 1902 insertions(+), 593 deletions(-)
 create mode 100644 hw/apic_common.c
 create mode 100644 hw/apic_internal.h
 create mode 100644 hw/i8259_common.c
 create mode 100644 hw/i8259_internal.h
 create mode 100644 hw/ioapic_common.c
 create mode 100644 hw/ioapic_internal.h
 create mode 100644 hw/kvm/apic.c
 rename hw/{kvmclock.c => kvm/clock.c} (98%)
 rename hw/{kvmclock.h => kvm/clock.h} (100%)
 create mode 100644 hw/kvm/i8259.c
 create mode 100644 hw/kvm/ioapic.c
 create mode 100644 target-i386/hyperv.c
 create mode 100644 target-i386/hyperv.h
#1 lore raw

PATCH 1/20 hyper-v: introduce Hyper-V support infrastructure.

From: Vadim Rozenfeld <[email protected]>

[Jan: fix build with CONFIG_USER_ONLY]

---
 Makefile.target      |    2 +
 target-i386/cpuid.c  |   14 +++++++++++
 target-i386/hyperv.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/hyperv.h |   43 +++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+), 0 deletions(-)
 create mode 100644 target-i386/hyperv.c
 create mode 100644 target-i386/hyperv.h
Makefile.target +2 -0
index 06d79b8..798dd30 100644
@@ -199,6 +199,8 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o savevm.o
 LIBS+=-lz
 
+obj-i386-y +=hyperv.o
+
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
target-i386/cpuid.c +14 -0
index 91a104b..b9bfeaf 100644
@@ -27,6 +27,8 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 
+#include "hyperv.h"
+
 /* feature flags taken from "Intel Processor Identification and the CPUID
  * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
  * between feature naming conventions, aliases may be added.
@@ -716,6 +718,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                     goto error;
                 }
                 x86_cpu_def->tsc_khz = tsc_freq / 1000;
+            } else if (!strcmp(featurestr, "hv_spinlocks")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                hyperv_set_spinlock_retries(numvalue);
             } else {
                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
                 goto error;
@@ -724,6 +734,10 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
             check_cpuid = 1;
         } else if (!strcmp(featurestr, "enforce")) {
             check_cpuid = enforce_cpuid = 1;
+        } else if (!strcmp(featurestr, "hv_relaxed")) {
+            hyperv_enable_relaxed_timing(true);
+        } else if (!strcmp(featurestr, "hv_vapic")) {
+            hyperv_enable_vapic_recommended(true);
         } else {
             fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
             goto error;
target-i386/hyperv.c new file +64 -0

64 lines not on this page · raw message

target-i386/hyperv.h new file +43 -0

43 lines not on this page · raw message

Signature · 1 line
1.7.6.4
#2 lore raw

kvm: let's add HYPERV capabilities (was Re: [PATCH 01/20] hyper-v: introduce Hyper-V support infrastructure.)

Quoted 187 lines · Marcelo Tosatti

From: Vadim Rozenfeld <[email protected]>

[Jan: fix build with CONFIG_USER_ONLY]

---
 Makefile.target      |    2 +
 target-i386/cpuid.c  |   14 +++++++++++
 target-i386/hyperv.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/hyperv.h |   43 +++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+), 0 deletions(-)
 create mode 100644 target-i386/hyperv.c
 create mode 100644 target-i386/hyperv.h
Makefile.target +2 -0
index 06d79b8..798dd30 100644
@@ -199,6 +199,8 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o savevm.o
 LIBS+=-lz
 
+obj-i386-y +=hyperv.o
+
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
target-i386/cpuid.c +14 -0
index 91a104b..b9bfeaf 100644
@@ -27,6 +27,8 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 
+#include "hyperv.h"
+
 /* feature flags taken from "Intel Processor Identification and the CPUID
  * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
  * between feature naming conventions, aliases may be added.
@@ -716,6 +718,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                     goto error;
                 }
                 x86_cpu_def->tsc_khz = tsc_freq / 1000;
+            } else if (!strcmp(featurestr, "hv_spinlocks")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                hyperv_set_spinlock_retries(numvalue);
             } else {
                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
                 goto error;
@@ -724,6 +734,10 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
             check_cpuid = 1;
         } else if (!strcmp(featurestr, "enforce")) {
             check_cpuid = enforce_cpuid = 1;
+        } else if (!strcmp(featurestr, "hv_relaxed")) {
+            hyperv_enable_relaxed_timing(true);
+        } else if (!strcmp(featurestr, "hv_vapic")) {
+            hyperv_enable_vapic_recommended(true);
         } else {
             fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
             goto error;
target-i386/hyperv.c new file +64 -0
new file mode 100644
index 0000000..f284e99
@@ -0,0 +1,64 @@
+/*
+ * QEMU Hyper-V support
+ *
+ * Copyright Red Hat, Inc. 2011
+ *
+ * Author: Vadim Rozenfeld     <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hyperv.h"
+
+static bool hyperv_vapic;
+static bool hyperv_relaxed_timing;
+static int hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
+
+void hyperv_enable_vapic_recommended(bool val)
+{
+    hyperv_vapic = val;
+}
+
+void hyperv_enable_relaxed_timing(bool val)
+{
+    hyperv_relaxed_timing = val;
+}
+
+void hyperv_set_spinlock_retries(int val)
+{
+    hyperv_spinlock_attempts = val;
+    if (hyperv_spinlock_attempts < 0xFFF) {
+        hyperv_spinlock_attempts = 0xFFF;
+    }
+}
+
+bool hyperv_enabled(void)
+{
+    return hyperv_hypercall_available() || hyperv_relaxed_timing_enabled();
+}
+
+bool hyperv_hypercall_available(void)
+{
+    if (hyperv_vapic ||
+        (hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY)) {
+      return true;
+    }
+    return false;
+}
+
+bool hyperv_vapic_recommended(void)
+{
+    return hyperv_vapic;
+}
+
+bool hyperv_relaxed_timing_enabled(void)
+{
+    return hyperv_relaxed_timing;
+}
+
+int hyperv_get_spinlock_retries(void)
+{
+    return hyperv_spinlock_attempts;
+}
target-i386/hyperv.h new file +43 -0
new file mode 100644
index 0000000..15467bf
@@ -0,0 +1,43 @@
+/*
+ * QEMU Hyper-V support
+ *
+ * Copyright Red Hat, Inc. 2011
+ *
+ * Author: Vadim Rozenfeld     <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_HW_HYPERV_H
+#define QEMU_HW_HYPERV_H 1
+
+#include "qemu-common.h"
+#include <asm/hyperv.h>
+
+#ifndef HYPERV_SPINLOCK_NEVER_RETRY
+#define HYPERV_SPINLOCK_NEVER_RETRY             0xFFFFFFFF
+#endif
+
+#ifndef KVM_CPUID_SIGNATURE_NEXT
+#define KVM_CPUID_SIGNATURE_NEXT                0x40000100
+#endif
+
+#ifndef CONFIG_USER_ONLY
+void hyperv_enable_vapic_recommended(bool val);
+void hyperv_enable_relaxed_timing(bool val);
+void hyperv_set_spinlock_retries(int val);
+#else
+static inline void hyperv_enable_vapic_recommended(bool val) { }
+static inline void hyperv_enable_relaxed_timing(bool val) { }
+static inline void hyperv_set_spinlock_retries(int val) { }
+#endif
+
+bool hyperv_enabled(void);
+bool hyperv_hypercall_available(void);
+bool hyperv_vapic_recommended(void);
+bool hyperv_relaxed_timing_enabled(void);
+int hyperv_get_spinlock_retries(void);
+
+#endif /* QEMU_HW_HYPERV_H */
Signature · 1 line
1.7.6.4

So basically, this means that you enable hyperv
features unconditionally when user requests them.
If you run qemu on an old kernel without hyperv support and request hyperv features through flags, guest will crash.

This is not a friendly way to do this.

Linux currently exposes:

linux-headers/linux/kvm.h:#define KVM_CAP_HYPERV 44 linux-headers/linux/kvm.h:#define KVM_CAP_HYPERV_VAPIC 45 linux-headers/linux/kvm.h:#define KVM_CAP_HYPERV_SPIN 46

I think qemu should be fixed to check the appropriate capability before enabling features:
KVM_CAP_HYPERV for relaxed KVM_CAP_HYPERV_VAPIC for vapic KVM_CAP_HYPERV_SPIN for spinlocks

As we will add more features we will have to add more capabilities.
Are there any features implemented now that lack a capability? It doesn't look like there are any ...

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

PATCH 2/20 hyper-v: initialize Hyper-V CPUID leaves.

In reply to Marcelo Tosatti

From: Vadim Rozenfeld <[email protected]>

---
 target-i386/kvm.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 63 insertions(+), 2 deletions(-)
target-i386/kvm.c +63 -2
index 04e65c5..1f56492 100644
@@ -29,6 +29,7 @@
 #include "hw/pc.h"
 #include "hw/apic.h"
 #include "ioport.h"
+#include "hyperv.h"
 
 //#define DEBUG_KVM
 
@@ -373,11 +374,16 @@ int kvm_arch_init_vcpu(CPUState *env)
     cpuid_i = 0;
 
     /* Paravirtualization CPUIDs */
-    memcpy(signature, "KVMKVMKVM\0\0\0", 12);
     c = &cpuid_data.entries[cpuid_i++];
     memset(c, 0, sizeof(*c));
     c->function = KVM_CPUID_SIGNATURE;
-    c->eax = 0;
+    if (!hyperv_enabled()) {
+        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+        c->eax = 0;
+    } else {
+        memcpy(signature, "Microsoft Hv", 12);
+        c->eax = HYPERV_CPUID_MIN;
+    }
     c->ebx = signature[0];
     c->ecx = signature[1];
     c->edx = signature[2];
@@ -388,6 +394,54 @@ int kvm_arch_init_vcpu(CPUState *env)
     c->eax = env->cpuid_kvm_features &
         kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
 
+    if (hyperv_enabled()) {
+        memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
+        c->eax = signature[0];
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_VERSION;
+        c->eax = 0x00001bbc;
+        c->ebx = 0x00060001;
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_FEATURES;
+        if (hyperv_relaxed_timing_enabled()) {
+            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+        }
+        if (hyperv_vapic_recommended()) {
+            c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
+            c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
+        }
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
+        if (hyperv_relaxed_timing_enabled()) {
+            c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
+        }
+        if (hyperv_vapic_recommended()) {
+            c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
+        }
+        c->ebx = hyperv_get_spinlock_retries();
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
+        c->eax = 0x40;
+        c->ebx = 0x40;
+
+        c = &cpuid_data.entries[cpuid_i++];
+        memset(c, 0, sizeof(*c));
+        c->function = KVM_CPUID_SIGNATURE_NEXT;
+        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+        c->eax = 0;
+        c->ebx = signature[0];
+        c->ecx = signature[1];
+        c->edx = signature[2];
+    }
+
     has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
 
     cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@@ -933,6 +987,13 @@ static int kvm_put_msrs(CPUState *env, int level)
             kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
                               env->async_pf_en_msr);
         }
+        if (hyperv_hypercall_available()) {
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
+        }
+        if (hyperv_vapic_recommended()) {
+            kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
+        }
     }
     if (env->mcg_cap) {
         int i;
Signature · 1 line
1.7.6.4
#4 lore raw

PATCH 3/20 msi: Generalize msix_supported to msi_supported

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Rename msix_supported to msi_supported and control MSI and MSI-X activation this way. That was likely to original intention for this flag, but MSI support came after MSI-X.

---
 hw/msi.c  |    8 ++++++++
 hw/msi.h  |    2 ++
 hw/msix.c |    9 ++++-----
 hw/msix.h |    2 --
 hw/pc.c   |    4 ++--
 5 files changed, 16 insertions(+), 9 deletions(-)
hw/msi.c +8 -0
index f214fcf..5d6ceb6 100644
@@ -36,6 +36,9 @@
 
 #define PCI_MSI_VECTORS_MAX     32
 
+/* Flag for interrupt controller to declare MSI/MSI-X support */
+bool msi_supported;
+
 /* If we get rid of cap allocator, we won't need this. */
 static inline uint8_t msi_cap_sizeof(uint16_t flags)
 {
@@ -116,6 +119,11 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
     uint16_t flags;
     uint8_t cap_size;
     int config_offset;
+
+    if (!msi_supported) {
+        return -ENOTSUP;
+    }
+
     MSI_DEV_PRINTF(dev,
                    "init offset: 0x%"PRIx8" vector: %"PRId8
                    " 64bit %d mask %d\n",
hw/msi.h +2 -0
index 5766018..3040bb0 100644
@@ -24,6 +24,8 @@
 #include "qemu-common.h"
 #include "pci.h"
 
+extern bool msi_supported;
+
 bool msi_enabled(const PCIDevice *dev);
 int msi_init(struct PCIDevice *dev, uint8_t offset,
              unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask);
hw/msix.c +4 -5
index f47d26b..3835eaa 100644
@@ -15,6 +15,7 @@
  */
 
 #include "hw.h"
+#include "msi.h"
 #include "msix.h"
 #include "pci.h"
 #include "range.h"
@@ -35,9 +36,6 @@
 #define MSIX_MAX_ENTRIES 32
 
 
-/* Flag for interrupt controller to declare MSI-X support */
-int msix_supported;
-
 /* Add MSI-X capability to the config space for the device. */
 /* Given a bar and its size, add MSI-X table on top of it
  * and fill MSI-X capability in the config space.
@@ -238,10 +236,11 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
               unsigned bar_nr, unsigned bar_size)
 {
     int ret;
+
     /* Nothing to do if MSI is not supported by interrupt controller */
-    if (!msix_supported)
+    if (!msi_supported) {
         return -ENOTSUP;
-
+    }
     if (nentries > MSIX_MAX_ENTRIES)
         return -EINVAL;
 
hw/msix.h +0 -2
index 7e04336..5aba22b 100644
@@ -29,6 +29,4 @@ void msix_notify(PCIDevice *dev, unsigned vector);
 
 void msix_reset(PCIDevice *dev);
 
-extern int msix_supported;
-
 #endif
hw/pc.c +2 -2
index 85304cf..04304e0 100644
@@ -36,7 +36,7 @@
 #include "elf.h"
 #include "multiboot.h"
 #include "mc146818rtc.h"
-#include "msix.h"
+#include "msi.h"
 #include "sysbus.h"
 #include "sysemu.h"
 #include "blockdev.h"
@@ -896,7 +896,7 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
         apic_mapped = 1;
     }
 
-    msix_supported = 1;
+    msi_supported = true;
 
     return dev;
 }
Signature · 1 line
1.7.6.4
#5 lore raw

PATCH 4/20 kvm: Move kvmclock into hw/kvm folder

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

More KVM-specific devices will come, so let's start with moving the kvmclock into a dedicated folder.

---
 Makefile.target |    4 +-
 configure       |    1 +
 hw/kvm/clock.c  |  120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/kvm/clock.h  |   24 +++++++++++
 hw/kvmclock.c   |  120 -------------------------------------------------------
 hw/kvmclock.h   |   24 -----------
 hw/pc_piix.c    |    2 +-
 7 files changed, 148 insertions(+), 147 deletions(-)
 create mode 100644 hw/kvm/clock.c
 create mode 100644 hw/kvm/clock.h
 delete mode 100644 hw/kvmclock.c
 delete mode 100644 hw/kvmclock.h
Makefile.target +2 -2
index 798dd30..0451b63 100644
@@ -233,7 +233,7 @@ obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
-obj-i386-$(CONFIG_KVM) += kvmclock.o
+obj-i386-$(CONFIG_KVM) += kvm/clock.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
@@ -424,7 +424,7 @@ qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
 
 clean:
 	rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
-	rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
+	rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o kvm/*.o
 	rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
 ifdef CONFIG_TRACE_SYSTEMTAP
 	rm -f *.stp
configure +1 -0
index 467e87b..9d5175b 100755
@@ -3363,6 +3363,7 @@ mkdir -p $target_dir/fpu
 mkdir -p $target_dir/tcg
 mkdir -p $target_dir/ide
 mkdir -p $target_dir/9pfs
+mkdir -p $target_dir/kvm
 if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
   mkdir -p $target_dir/nwfpe
 fi
hw/kvm/clock.c new file +120 -0

120 lines not on this page · raw message

hw/kvm/clock.h new file +24 -0
new file mode 100644
index 0000000..252ea13
@@ -0,0 +1,24 @@
+/*
+ * QEMU KVM support, paravirtual clock device
+ *
+ * Copyright (C) 2011 Siemens AG
+ *
+ * Authors:
+ *  Jan Kiszka        <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifdef CONFIG_KVM
+
+void kvmclock_create(void);
+
+#else /* CONFIG_KVM */
+
+static inline void kvmclock_create(void)
+{
+}
+
+#endif /* !CONFIG_KVM */
hw/kvmclock.c deleted +0 -120

120 lines not on this page · raw message

hw/kvmclock.h deleted +0 -24
deleted file mode 100644
index 252ea13..0000000
@@ -1,24 +0,0 @@
-/*
- * QEMU KVM support, paravirtual clock device
- *
- * Copyright (C) 2011 Siemens AG
- *
- * Authors:
- *  Jan Kiszka        <[email protected]>
- *
- * This work is licensed under the terms of the GNU GPL version 2.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifdef CONFIG_KVM
-
-void kvmclock_create(void);
-
-#else /* CONFIG_KVM */
-
-static inline void kvmclock_create(void)
-{
-}
-
-#endif /* !CONFIG_KVM */
hw/pc_piix.c +1 -1
index 3aea3cc..cde810d 100644
@@ -34,7 +34,7 @@
 #include "boards.h"
 #include "ide.h"
 #include "kvm.h"
-#include "kvmclock.h"
+#include "kvm/clock.h"
 #include "sysemu.h"
 #include "sysbus.h"
 #include "arch_init.h"
Signature · 1 line
1.7.6.4
#6 lore raw

PATCH 5/20 apic: Stop timer on reset

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

All LVTs are masked on reset, so the timer becomes ineffective. Letting it tick nevertheless is harmless, but will at least create a spurious trace event.

---
 hw/apic.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
hw/apic.c +2 -0
index 9d0f460..4b97b17 100644
@@ -528,6 +528,8 @@ void apic_init_reset(DeviceState *d)
     s->initial_count_load_time = 0;
     s->next_time = 0;
     s->wait_for_sipi = 1;
+
+    qemu_del_timer(s->timer);
 }
 
 static void apic_startup(APICState *s, int vector_num)
Signature · 1 line
1.7.6.4
#7 lore raw

PATCH 6/20 apic: Inject external NMI events via LINT1

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

On real hardware, NMI button events are injected via the LINT1 line of the APICs. E.g. kdump expect this wiring and gets upset if the per-APIC LINT1 mask is not respected, i.e. if NMIs are injected to VCPUs that should not receive them. Change the APIC emulation code to reflect this.

Based on qemu-kvm patch by Lai Jiangshan.

---
 cpus.c    |    6 +++++-
 hw/apic.c |    7 +++++++
 hw/apic.h |    1 +
 3 files changed, 13 insertions(+), 1 deletions(-)
cpus.c +5 -1
index 2dae549..f45a438 100644
@@ -1217,7 +1217,11 @@ void qmp_inject_nmi(Error **errp)
     CPUState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu_interrupt(env, CPU_INTERRUPT_NMI);
+        if (!env->apic_state) {
+            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+        } else {
+            apic_deliver_nmi(env->apic_state);
+        }
     }
 #else
     error_set(errp, QERR_UNSUPPORTED);
hw/apic.c +7 -0
index 4b97b17..b9d733c 100644
@@ -205,6 +205,13 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
     }
 }
 
+void apic_deliver_nmi(DeviceState *d)
+{
+    APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+
+    apic_local_deliver(s, APIC_LVT_LINT1);
+}
+
 #define foreach_apic(apic, deliver_bitmask, code) \
 {\
     int __i, __j, __mask;\
hw/apic.h +1 -0
index a5c910f..a62d83b 100644
@@ -8,6 +8,7 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
                       uint8_t vector_num, uint8_t trigger_mode);
 int apic_accept_pic_intr(DeviceState *s);
 void apic_deliver_pic_intr(DeviceState *s, int level);
+void apic_deliver_nmi(DeviceState *d);
 int apic_get_interrupt(DeviceState *s);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
Signature · 1 line
1.7.6.4
#8 lore raw

PATCH 7/20 apic: Introduce apic_report_irq_delivered

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

The in-kernel i8259 and IOAPIC backends for KVM will need this, so encapsulate the shared bits.

---
 hw/apic.c    |   11 ++++++++---
 hw/apic.h    |    1 +
 trace-events |    2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)
hw/apic.c +8 -3
index b9d733c..bec493b 100644
@@ -413,6 +413,13 @@ static void apic_update_irq(APICState *s)
     }
 }
 
+void apic_report_irq_delivered(int delivered)
+{
+    apic_irq_delivered += delivered;
+
+    trace_apic_report_irq_delivered(apic_irq_delivered);
+}
+
 void apic_reset_irq_delivered(void)
 {
     trace_apic_reset_irq_delivered(apic_irq_delivered);
@@ -429,9 +436,7 @@ int apic_get_irq_delivered(void)
 
 static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
 {
-    apic_irq_delivered += !get_bit(s->irr, vector_num);
-
-    trace_apic_set_irq(apic_irq_delivered);
+    apic_report_irq_delivered(!get_bit(s->irr, vector_num));
 
     set_bit(s->irr, vector_num);
     if (trigger_mode)
hw/apic.h +1 -0
index a62d83b..8173d8a 100644
@@ -10,6 +10,7 @@ int apic_accept_pic_intr(DeviceState *s);
 void apic_deliver_pic_intr(DeviceState *s, int level);
 void apic_deliver_nmi(DeviceState *d);
 int apic_get_interrupt(DeviceState *s);
+void apic_report_irq_delivered(int delivered);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 void cpu_set_apic_base(DeviceState *s, uint64_t val);
trace-events +1 -1
index c18435b..5a260d6 100644
@@ -95,9 +95,9 @@ cpu_get_apic_base(uint64_t val) "%016"PRIx64
 apic_mem_readl(uint64_t addr, uint32_t val)  "%"PRIx64" = %08x"
 apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x"
 # coalescing
+apic_report_irq_delivered(int apic_irq_delivered) "coalescing %d"
 apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d"
 apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d"
-apic_set_irq(int apic_irq_delivered) "coalescing %d"
 
 # hw/cs4231.c
 cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x"
Signature · 1 line
1.7.6.4
#9 lore raw

PATCH 8/20 apic: Factor out base class for KVM reuse

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

The KVM in-kernel APIC model will reuse parts of the user space model while providing the same frontend view to guest and most management interfaces.

Factor out an APIC base class to encapsulate those parts that will be shared by user space and KVM model. This class offers callback hooks for init, base/tpr setting, and the external NMI delivery that will be set via APICCommonInfo structure and implemented specifically in the subclasses.

---
 Makefile.target    |    2 +-
 hw/apic.c          |  338 +++++++---------------------------------------------
 hw/apic.h          |    1 -
 hw/apic_common.c   |  252 ++++++++++++++++++++++++++++++++++++++
 hw/apic_internal.h |  112 +++++++++++++++++
 5 files changed, 406 insertions(+), 299 deletions(-)
 create mode 100644 hw/apic_common.c
 create mode 100644 hw/apic_internal.h
Makefile.target +1 -1
index 0451b63..4446273 100644
@@ -228,7 +228,7 @@ obj-y += device-hotplug.o
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
+obj-i386-y += cirrus_vga.o sga.o apic_common.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
hw/apic.c +41 -297

544 lines not on this page · raw message

hw/apic.h +0 -1
index 8173d8a..a62d83b 100644
@@ -10,7 +10,6 @@ int apic_accept_pic_intr(DeviceState *s);
 void apic_deliver_pic_intr(DeviceState *s, int level);
 void apic_deliver_nmi(DeviceState *d);
 int apic_get_interrupt(DeviceState *s);
-void apic_report_irq_delivered(int delivered);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 void cpu_set_apic_base(DeviceState *s, uint64_t val);
hw/apic_common.c new file +252 -0

252 lines not on this page · raw message

hw/apic_internal.h new file +112 -0

112 lines not on this page · raw message

Signature · 1 line
1.7.6.4
#10 lore raw

PATCH 9/20 apic: Open-code timer save/restore

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

To enable migration between accelerated and non-accelerated APIC models, we will need to handle the timer saving and restoring specially and can no longer rely on the automatics of VMSTATE_TIMER. Specifically, accelerated model will not start any QEMUTimer.

This patch therefore factors out the generic bits into apic_next_timer and use a post-load callback to implemented model-specific logic.

---
 hw/apic.c          |   30 +++++++++++-----------------
 hw/apic_common.c   |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 hw/apic_internal.h |    3 ++
 3 files changed, 67 insertions(+), 20 deletions(-)
hw/apic.c +12 -18
index 387a469..e59c964 100644
@@ -521,25 +521,9 @@ static uint32_t apic_get_current_count(APICCommonState *s)
 
 static void apic_timer_update(APICCommonState *s, int64_t current_time)
 {
-    int64_t next_time, d;
-
-    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
-        d = (current_time - s->initial_count_load_time) >>
-            s->count_shift;
-        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
-            if (!s->initial_count)
-                goto no_timer;
-            d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
-        } else {
-            if (d >= s->initial_count)
-                goto no_timer;
-            d = (uint64_t)s->initial_count + 1;
-        }
-        next_time = s->initial_count_load_time + (d << s->count_shift);
-        qemu_mod_timer(s->timer, next_time);
-        s->next_time = next_time;
+    if (apic_next_timer(s, current_time)) {
+        qemu_mod_timer(s->timer, s->next_time);
     } else {
-    no_timer:
         qemu_del_timer(s->timer);
     }
 }
@@ -753,6 +737,15 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
+static void apic_post_load(APICCommonState *s)
+{
+    if (s->timer_expiry != -1) {
+        qemu_mod_timer(s->timer, s->timer_expiry);
+    } else {
+        qemu_del_timer(s->timer);
+    }
+}
+
 static const MemoryRegionOps apic_io_ops = {
     .old_mmio = {
         .read = { apic_mem_readb, apic_mem_readw, apic_mem_readl, },
@@ -776,6 +769,7 @@ static APICCommonInfo apic_info = {
     .set_base = apic_set_base,
     .set_tpr = apic_set_tpr,
     .external_nmi = apic_external_nmi,
+    .post_load = apic_post_load,
 };
 
 static void apic_register_devices(void)
hw/apic_common.c +52 -2

84 lines not on this page · raw message

hw/apic_internal.h +3 -0
index a7433fb..1db4f06 100644
@@ -92,6 +92,7 @@ struct APICCommonState {
     int64_t next_time;
     int idx;
     QEMUTimer *timer;
+    int64_t timer_expiry;
     int sipi_vector;
     int wait_for_sipi;
 };
@@ -104,9 +105,11 @@ struct APICCommonInfo {
     void (*set_base)(APICCommonState *s, uint64_t val);
     void (*set_tpr)(APICCommonState *s, uint8_t val);
     void (*external_nmi)(APICCommonState *s);
+    void (*post_load)(APICCommonState *s);
 };
 
 void apic_report_irq_delivered(int delivered);
 void apic_qdev_register(APICCommonInfo *info);
+bool apic_next_timer(APICCommonState *s, int64_t current_time);
 
 #endif /* !QEMU_APIC_INTERNAL_H */
Signature · 1 line
1.7.6.4
#11 lore raw

PATCH 10/20 i8259: Completely privatize PicState

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Use DeviceState instead of PicState in the public i8259 API. This is cleaner and allows to reorganize the PIC data structures for KVM reuse.

---
 hw/i8259.c |   17 +++++++++++------
 hw/pc.h    |    7 +++----
 2 files changed, 14 insertions(+), 10 deletions(-)
hw/i8259.c +11 -6
index 7331e0e..cfaa35c 100644
@@ -40,6 +40,8 @@
 //#define DEBUG_IRQ_LATENCY
 //#define DEBUG_IRQ_COUNT
 
+typedef struct PicState PicState;
+
 struct PicState {
     ISADevice dev;
     uint8_t last_irr; /* edge detection */
@@ -76,7 +78,7 @@ static uint64_t irq_count[16];
 #ifdef DEBUG_IRQ_LATENCY
 static int64_t irq_time[16];
 #endif
-PicState *isa_pic;
+DeviceState *isa_pic;
 static PicState *slave_pic;
 
 /* return the highest priority found in mask (highest = smallest
@@ -206,8 +208,9 @@ static void pic_intack(PicState *s, int irq)
     pic_update_irq(s);
 }
 
-int pic_read_irq(PicState *s)
+int pic_read_irq(DeviceState *d)
 {
+    PicState *s = DO_UPCAST(PicState, dev.qdev, d);
     int irq, irq2, intno;
 
     irq = pic_get_irq(s);
@@ -269,7 +272,7 @@ static void pic_init_reset(PicState *s)
 
 static void pic_reset(DeviceState *dev)
 {
-    PicState *s = container_of(dev, PicState, dev.qdev);
+    PicState *s = DO_UPCAST(PicState, dev.qdev, dev);
 
     pic_init_reset(s);
     s->elcr = 0;
@@ -399,8 +402,10 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
     return ret;
 }
 
-int pic_get_output(PicState *s)
+int pic_get_output(DeviceState *d)
 {
+    PicState *s = DO_UPCAST(PicState, dev.qdev, d);
+
     return (pic_get_irq(s) >= 0);
 }
 
@@ -491,7 +496,7 @@ void pic_info(Monitor *mon)
         return;
     }
     for (i = 0; i < 2; i++) {
-        s = i == 0 ? isa_pic : slave_pic;
+        s = i == 0 ? DO_UPCAST(PicState, dev.qdev, isa_pic) : slave_pic;
         monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
                        "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
                        i, s->irr, s->imr, s->isr, s->priority_add,
@@ -538,7 +543,7 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq)
         irq_set[i] = qdev_get_gpio_in(&dev->qdev, i);
     }
 
-    isa_pic = DO_UPCAST(PicState, dev, dev);
+    isa_pic = &dev->qdev;
 
     dev = isa_create(bus, "isa-i8259");
     qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
hw/pc.h +3 -4
index 13e41f1..ece069a 100644
@@ -62,11 +62,10 @@ bool parallel_mm_init(MemoryRegion *address_space,
 
 /* i8259.c */
 
-typedef struct PicState PicState;
-extern PicState *isa_pic;
+extern DeviceState *isa_pic;
 qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
-int pic_read_irq(PicState *s);
-int pic_get_output(PicState *s);
+int pic_read_irq(DeviceState *d);
+int pic_get_output(DeviceState *d);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
Signature · 1 line
1.7.6.4
#12 lore raw

PATCH 11/20 i8259: Factor out base class for KVM reuse

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Analogously to the APIC, we will reuse some parts of the user space i8259 model for KVM. The base class provides a common device state, the vmstate, the property list, a reset core and some shared init bits.

This also introduces a common helper to instantiate a single i8259 chip from the cascade-creating i8259_init function.

---
 Makefile.objs       |    2 +-
 hw/i8259.c          |  158 ++++++++++-----------------------------------------
 hw/i8259_common.c   |  147 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/i8259_internal.h |   76 ++++++++++++++++++++++++
 4 files changed, 254 insertions(+), 129 deletions(-)
 create mode 100644 hw/i8259_common.c
 create mode 100644 hw/i8259_internal.h
Makefile.objs +1 -1
index 4f6d26c..6270a95 100644
@@ -220,7 +220,7 @@ hw-obj-$(CONFIG_APPLESMC) += applesmc.o
 hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
 hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
-hw-obj-$(CONFIG_I8259) += i8259.o
+hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 
 # PPC devices
 hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
hw/i8259.c +30 -128

299 lines not on this page · raw message

hw/i8259_common.c new file +147 -0

147 lines not on this page · raw message

hw/i8259_internal.h new file +76 -0

76 lines not on this page · raw message

Signature · 1 line
1.7.6.4
#13 lore raw

PATCH 12/20 ioapic: Drop post-load irr initialization

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

As all devices undergo a reset prior to vmloa, and the reset value of irr is 0, we do not need to do this clearing for older vmstates explicitly. Dropping this redundant code will also make KVM integration a bit simpler.

---
 hw/ioapic.c |   12 ------------
 1 files changed, 0 insertions(+), 12 deletions(-)
hw/ioapic.c +0 -12
index 27b07c6..0743af6 100644
@@ -278,21 +278,9 @@ ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
     }
 }
 
-static int ioapic_post_load(void *opaque, int version_id)
-{
-    IOAPICState *s = opaque;
-
-    if (version_id == 1) {
-        /* set sane value */
-        s->irr = 0;
-    }
-    return 0;
-}
-
 static const VMStateDescription vmstate_ioapic = {
     .name = "ioapic",
     .version_id = 3,
-    .post_load = ioapic_post_load,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields = (VMStateField[]) {
Signature · 1 line
1.7.6.4
#14 lore raw

PATCH 13/20 ioapic: Factor out base class for KVM reuse

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Split up the IOAPIC analogously to APIC and i8259. KVM will share the IOAPICCommonState, the vmstate, reset logic and certain init parts with the user space model.

---
 Makefile.target      |    2 +-
 hw/ioapic.c          |  130 ++++++-------------------------------------------
 hw/ioapic_common.c   |  104 ++++++++++++++++++++++++++++++++++++++++
 hw/ioapic_internal.h |   97 +++++++++++++++++++++++++++++++++++++
 4 files changed, 218 insertions(+), 115 deletions(-)
 create mode 100644 hw/ioapic_common.c
 create mode 100644 hw/ioapic_internal.h
Makefile.target +1 -1
index 4446273..556942d 100644
@@ -228,7 +228,7 @@ obj-y += device-hotplug.o
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += cirrus_vga.o sga.o apic_common.o apic.o ioapic.o piix_pci.o
+obj-i386-y += cirrus_vga.o sga.o apic_common.o apic.o ioapic_common.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
hw/ioapic.c +16 -114

189 lines not on this page · raw message

hw/ioapic_common.c new file +104 -0

104 lines not on this page · raw message

hw/ioapic_internal.h new file +97 -0

97 lines not on this page · raw message

Signature · 1 line
1.7.6.4
#15 lore raw

PATCH 14/20 memory: Introduce memory_region_init_reservation

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Introduce a memory region type that can reserve I/O space. Such regions are useful for modeling I/O that is only handled outside of QEMU, i.e. in the context of an accelerator like KVM.

Any access to such a region from QEMU is a bug, but could theoretically be triggered by guest code (DMA to reserved region). So only warning about such events once, then ignore them.

---
 memory.c |   36 ++++++++++++++++++++++++++++++++++++
 memory.h |   16 ++++++++++++++++
 2 files changed, 52 insertions(+), 0 deletions(-)
memory.c +36 -0
index 6201a37..68e5cdf 100644
@@ -1049,6 +1049,42 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_addr |= cpu_register_io_memory(mr);
 }
 
+static uint64_t invalid_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
+{
+    MemoryRegion *mr = opaque;
+
+    if (!mr->warning_printed) {
+        fprintf(stderr, "Invalid read from memory region %s\n", mr->name);
+        mr->warning_printed = true;
+    }
+    return -1U;
+}
+
+static void invalid_write(void *opaque, target_phys_addr_t addr, uint64_t data,
+                          unsigned size)
+{
+    MemoryRegion *mr = opaque;
+
+    if (!mr->warning_printed) {
+        fprintf(stderr, "Invalid write to memory region %s\n", mr->name);
+        mr->warning_printed = true;
+    }
+}
+
+static const MemoryRegionOps reservation_ops = {
+    .read = invalid_read,
+    .write = invalid_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+void memory_region_init_reservation(MemoryRegion *mr,
+                                    const char *name,
+                                    uint64_t size)
+{
+    memory_region_init_io(mr, &reservation_ops, mr, name, size);
+}
+
 void memory_region_destroy(MemoryRegion *mr)
 {
     assert(QTAILQ_EMPTY(&mr->subregions));
memory.h +16 -0
index d48b08b..34c69cf 100644
@@ -126,6 +126,7 @@ struct MemoryRegion {
     bool readonly; /* For RAM regions */
     bool enabled;
     bool rom_device;
+    bool warning_printed; /* For reservations */
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
@@ -280,6 +281,21 @@ void memory_region_init_rom_device(MemoryRegion *mr,
                                    uint64_t size);
 
 /**
+ * memory_region_init_reservation: Initialize a memory region that reserves
+ *                                 I/O space.
+ *
+ * A reservation region primariy serves debugging purposes.  It claims I/O
+ * space that is not supposed to be handled by QEMU itself.  Any access via
+ * the memory API will cause an abort().
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ */
+void memory_region_init_reservation(MemoryRegion *mr,
+                                    const char *name,
+                                    uint64_t size);
+/**
  * memory_region_destroy: Destroy a memory region and reclaim all resources.
  *
  * @mr: the region to be destroyed.  May not currently be a subregion
Signature · 1 line
1.7.6.4
#16 lore raw

PATCH 15/20 kvm: Introduce core services for in-kernel irqchip support

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

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 looe 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.

---
 kvm-all.c         |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 kvm.h             |    8 +++
 target-i386/kvm.c |   11 ++++
 3 files changed, 168 insertions(+), 0 deletions(-)
kvm-all.c +149 -0
index 2cc4562..fa9d92d 100644
@@ -78,6 +78,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;
@@ -728,6 +735,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[] =
@@ -823,6 +962,11 @@ int kvm_init(void)
         goto err;
     }
 
+    ret = kvm_irqchip_create(s);
+    if (ret < 0) {
+        goto err;
+    }
+
     kvm_state = s;
     memory_listener_register(&kvm_memory_listener);
 
@@ -1158,6 +1302,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()) {
kvm.h +8 -0
index c1de81a..dd2d4f0 100644
@@ -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;
 
target-i386/kvm.c +11 -0
index 1f56492..f6f4189 100644
@@ -1939,3 +1939,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;
+    }
+}
Signature · 1 line
1.7.6.4
#17 lore raw

PATCH 16/20 kvm: x86: Establish IRQ0 override control

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

KVM is forced to disable the IRQ0 override when we run with in-kernel irqchip but without IRQ routing support of the kernel. Set the fwcfg value correspondingly. This aligns us with qemu-kvm.

---
 hw/pc.c    |    3 ++-
 kvm-all.c  |    5 +++++
 kvm-stub.c |    5 +++++
 kvm.h      |    2 ++
 sysemu.h   |    1 -
 vl.c       |    1 -
 6 files changed, 14 insertions(+), 3 deletions(-)
hw/pc.c +2 -1
index 04304e0..38d787a 100644
@@ -39,6 +39,7 @@
 #include "msi.h"
 #include "sysbus.h"
 #include "sysemu.h"
+#include "kvm.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
 #include "memory.h"
@@ -609,7 +610,7 @@ static void *bochs_bios_init(void)
     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
     fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
                      acpi_tables_len);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_IRQ0_OVERRIDE, &irq0override, 1);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
 
     smbios_table = smbios_get_table(&smbios_len);
     if (smbios_table)
kvm-all.c +5 -0
index fa9d92d..88f1156 100644
@@ -1307,6 +1307,11 @@ int kvm_has_gsi_routing(void)
     return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
 }
 
+int kvm_allows_irq0_override(void)
+{
+    return !kvm_enabled() || !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
+}
+
 void kvm_setup_guest_memory(void *start, size_t size)
 {
     if (!kvm_has_sync_mmu()) {
kvm-stub.c +5 -0
index 06064b9..6c2b06b 100644
@@ -78,6 +78,11 @@ int kvm_has_many_ioeventfds(void)
     return 0;
 }
 
+int kvm_allows_irq0_override(void)
+{
+    return 1;
+}
+
 void kvm_setup_guest_memory(void *start, size_t size)
 {
 }
kvm.h +2 -0
index dd2d4f0..ad430fd 100644
@@ -53,6 +53,8 @@ int kvm_has_xcrs(void);
 int kvm_has_many_ioeventfds(void);
 int kvm_has_gsi_routing(void);
 
+int kvm_allows_irq0_override(void);
+
 #ifdef NEED_CPU_H
 int kvm_init_vcpu(CPUState *env);
 
sysemu.h +0 -1
index ddef2bb..caff268 100644
@@ -102,7 +102,6 @@ extern int vga_interface_type;
 extern int graphic_width;
 extern int graphic_height;
 extern int graphic_depth;
-extern uint8_t irq0override;
 extern DisplayType display_type;
 extern const char *keyboard_layout;
 extern int win2k_install_hack;
vl.c +0 -1
index ba55b35..132c387 100644
@@ -218,7 +218,6 @@ int no_reboot = 0;
 int no_shutdown = 0;
 int cursor_hide = 1;
 int graphic_rotate = 0;
-uint8_t irq0override = 1;
 const char *watchdog;
 QEMUOptionRom option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
Signature · 1 line
1.7.6.4
#18 lore raw

PATCH 17/20 kvm: x86: Add user space part for in-kernel APIC

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

This introduces the alternative APIC device which makes use of KVM's in-kernel device model. External NMI injection via LINT1 is emulated by checking the current state of the in-kernel APIC, only injecting a NMI into the VCPU if LINT1 is unmasked and configured to DM_NMI.

MSI is not yet supported, so we disable this when the in-kernel model is in use.

CC Lai Jiangshan <[email protected]>
---
 Makefile.target   |    2 +-
 hw/kvm/apic.c     |  138 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.c           |   15 ++++--
 kvm.h             |    4 ++
 target-i386/kvm.c |   38 +++++++++++++++
 5 files changed, 191 insertions(+), 6 deletions(-)
 create mode 100644 hw/kvm/apic.c
Makefile.target +1 -1
index 556942d..1a63a1c 100644
@@ -233,7 +233,7 @@ obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o
+obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
hw/kvm/apic.c new file +138 -0

138 lines not on this page · raw message

hw/pc.c +10 -5
index 38d787a..6a8a871 100644
@@ -879,25 +879,30 @@ DeviceState *cpu_get_current_apic(void)
 static DeviceState *apic_init(void *env, uint8_t apic_id)
 {
     DeviceState *dev;
-    SysBusDevice *d;
     static int apic_mapped;
 
-    dev = qdev_create(NULL, "apic");
+    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+        dev = qdev_create(NULL, "kvm-apic");
+    } else {
+        dev = qdev_create(NULL, "apic");
+    }
     qdev_prop_set_uint8(dev, "id", apic_id);
     qdev_prop_set_ptr(dev, "cpu_env", env);
     qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
 
     /* XXX: mapping more APICs at the same memory location */
     if (apic_mapped == 0) {
         /* NOTE: the APIC is directly connected to the CPU - it is not
            on the global memory bus. */
         /* XXX: what if the base changes? */
-        sysbus_mmio_map(d, 0, MSI_ADDR_BASE);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, MSI_ADDR_BASE);
         apic_mapped = 1;
     }
 
-    msi_supported = true;
+    /* KVM does not support MSI yet. */
+    if (!kvm_enabled() || !kvm_irqchip_in_kernel()) {
+        msi_supported = true;
+    }
 
     return dev;
 }
kvm.h +4 -0
index ad430fd..40b5ffc 100644
@@ -31,6 +31,7 @@ extern int kvm_allowed;
 #endif
 
 struct kvm_run;
+struct kvm_lapic_state;
 
 typedef struct KVMCapabilityInfo {
     const char *name;
@@ -134,6 +135,9 @@ 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);
 
+void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
+void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
+
 struct kvm_guest_debug;
 struct kvm_debug_exit_arch;
 
target-i386/kvm.c +38 -0
index f6f4189..e41de39 100644
@@ -1337,6 +1337,36 @@ static int kvm_get_mp_state(CPUState *env)
     return 0;
 }
 
+static int kvm_get_apic(CPUState *env)
+{
+    DeviceState *apic = env->apic_state;
+    struct kvm_lapic_state kapic;
+    int ret;
+
+    if (apic && kvm_enabled() && kvm_irqchip_in_kernel()) {
+        ret = kvm_vcpu_ioctl(env, KVM_GET_LAPIC, &kapic);
+        if (ret < 0) {
+            return ret;
+        }
+
+        kvm_get_apic_state(apic, &kapic);
+    }
+    return 0;
+}
+
+static int kvm_put_apic(CPUState *env)
+{
+    DeviceState *apic = env->apic_state;
+    struct kvm_lapic_state kapic;
+
+    if (apic && kvm_enabled() && kvm_irqchip_in_kernel()) {
+        kvm_put_apic_state(apic, &kapic);
+
+        return kvm_vcpu_ioctl(env, KVM_SET_LAPIC, &kapic);
+    }
+    return 0;
+}
+
 static int kvm_put_vcpu_events(CPUState *env, int level)
 {
     struct kvm_vcpu_events events;
@@ -1510,6 +1540,10 @@ int kvm_arch_put_registers(CPUState *env, int level)
         if (ret < 0) {
             return ret;
         }
+        ret = kvm_put_apic(env);
+        if (ret < 0) {
+            return ret;
+        }
     }
     ret = kvm_put_vcpu_events(env, level);
     if (ret < 0) {
@@ -1557,6 +1591,10 @@ int kvm_arch_get_registers(CPUState *env)
     if (ret < 0) {
         return ret;
     }
+    ret = kvm_get_apic(env);
+    if (ret < 0) {
+        return ret;
+    }
     ret = kvm_get_vcpu_events(env);
     if (ret < 0) {
         return ret;
Signature · 1 line
1.7.6.4
#19 lore raw

PATCH 18/20 kvm: x86: Add user space part for in-kernel i8259

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Introduce the alternative 'kvm-i8259' device model that exploits KVM in-kernel acceleration.

The PIIX3 initialization code is furthermore extended by KVM specific IRQ route setup. GSI injection differs in KVM mode from the user space model. As we can dispatch ISA-range IRQs to both IOAPIC and PIC inside the kernel, we do not need to inject them separately. This is reflected by a KVM-specific GSI handler.

---
 Makefile.target |    2 +-
 hw/kvm/i8259.c  |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.h         |    1 +
 hw/pc_piix.c    |   52 ++++++++++++++++++++--
 4 files changed, 178 insertions(+), 5 deletions(-)
 create mode 100644 hw/kvm/i8259.c
Makefile.target +1 -1
index 1a63a1c..701073d 100644
@@ -233,7 +233,7 @@ obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o
+obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
hw/kvm/i8259.c new file +128 -0

128 lines not on this page · raw message

hw/pc.h +1 -0
index ece069a..5e913db 100644
@@ -64,6 +64,7 @@ bool parallel_mm_init(MemoryRegion *address_space,
 
 extern DeviceState *isa_pic;
 qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
+qemu_irq *kvm_i8259_init(ISABus *bus);
 int pic_read_irq(DeviceState *d);
 int pic_get_output(DeviceState *d);
 void pic_info(Monitor *mon);
hw/pc_piix.c +48 -4

72 lines not on this page · raw message

Signature · 1 line
1.7.6.4
#20 lore raw

PATCH 19/20 kvm: x86: Add user space part for in-kernel IOAPIC

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

This introduces the KVM-accelerated IOAPIC model 'kvm-ioapic' and extends the IRQ routing setup by the 0->2 redirection when needed.

The kvm-ioapic model has a property that allows to define its GSI base for injecting interrupts into the kernel model. This will allow to disentangle PIC and IOAPIC pins for chipsets that support more sophisticated IRQ routes than the PIIX3. So far the base is kept at 0, i.e. PIC and IOAPIC share pins 0..15.

---
 Makefile.target |    2 +-
 hw/kvm/ioapic.c |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc_piix.c    |   15 +++++++-
 3 files changed, 129 insertions(+), 2 deletions(-)
 create mode 100644 hw/kvm/ioapic.c
Makefile.target +1 -1
index 701073d..98cb997 100644
@@ -233,7 +233,7 @@ obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o
+obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
hw/kvm/ioapic.c new file +114 -0

114 lines not on this page · raw message

hw/pc_piix.c +14 -1
index 297c04a..a285ad2 100644
@@ -69,6 +69,15 @@ static void kvm_piix3_setup_irq_routing(bool pci_enabled)
         for (i = 8; i < 16; ++i) {
             kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
         }
+        if (pci_enabled) {
+            for (i = 0; i < 24; ++i) {
+                if (i == 0) {
+                    kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
+                } else if (i != 2) {
+                    kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, i);
+                }
+            }
+        }
         ret = kvm_irqchip_commit_routes(s);
         if (ret < 0) {
             hw_error("KVM IRQ routing setup failed");
@@ -95,7 +104,11 @@ static void ioapic_init(GSIState *gsi_state)
     SysBusDevice *d;
     unsigned int i;
 
-    dev = qdev_create(NULL, "ioapic");
+    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+        dev = qdev_create(NULL, "kvm-ioapic");
+    } else {
+        dev = qdev_create(NULL, "ioapic");
+    }
     qdev_init_nofail(dev);
     d = sysbus_from_qdev(dev);
     sysbus_mmio_map(d, 0, 0xfec00000);
Signature · 1 line
1.7.6.4
#21 lore raw

PATCH 20/20 kvm: Activate in-kernel irqchip support

In reply to Marcelo Tosatti

From: Jan Kiszka <[email protected]>

Make the basic in-kernel irqchip support selectable via -machine ...,kernel_irqchip=on. Leave it off by default until it can fully replace user space models.

---
 qemu-config.c   |    4 ++++
 qemu-options.hx |    5 ++++-
 2 files changed, 8 insertions(+), 1 deletions(-)
qemu-config.c +4 -0
index ecc88e8..b030205 100644
@@ -531,6 +531,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "accel",
             .type = QEMU_OPT_STRING,
             .help = "accelerator list",
+        }, {
+            .name = "kernel_irqchip",
+            .type = QEMU_OPT_BOOL,
+            .help = "use KVM in-kernel irqchip",
         },
         { /* End of list */ }
     },
qemu-options.hx +4 -1
index 6295cde..3a07ae8 100644
@@ -31,7 +31,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
     "-machine [type=]name[,prop[=value][,...]]\n"
     "                selects emulated machine (-machine ? for list)\n"
     "                property accel=accel1[:accel2[:...]] selects accelerator\n"
-    "                supported accelerators are kvm, xen, tcg (default: tcg)\n",
+    "                supported accelerators are kvm, xen, tcg (default: tcg)\n"
+    "                kernel_irqchip=on|off controls accelerated irqchip support\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -machine [type=]@var{name}[,prop=@var{value}[,...]]
@@ -44,6 +45,8 @@ This is used to enable an accelerator. Depending on the target architecture,
 kvm, xen, or tcg can be available. By default, tcg is used. If there is more
 than one accelerator specified, the next one is used if the previous one fails
 to initialize.
+@item kernel_irqchip=on|off
+Enables in-kernel irqchip support for the chosen accelerator when available.
 @end table
 ETEXI
 
Signature · 1 line
1.7.6.4
#22 lore raw
In reply to Marcelo Tosatti
Quoted 6 lines · Marcelo Tosatti

The following changes since commit 8c4ec5c0269bda18bb777a64b2008088d1c632dc:

   pxa2xx_keypad: fix unbalanced parenthesis. (2012-01-17 02:14:42 +0100)

are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master

Applied. Thanks.

Regards,

Anthony Liguori

Quoted 81 lines

Jan Kiszka (18):
msi: Generalize msix_supported to msi_supported
kvm: Move kvmclock into hw/kvm folder
apic: Stop timer on reset
apic: Inject external NMI events via LINT1
apic: Introduce apic_report_irq_delivered
apic: Factor out base class for KVM reuse
apic: Open-code timer save/restore
i8259: Completely privatize PicState
i8259: Factor out base class for KVM reuse
ioapic: Drop post-load irr initialization
ioapic: Factor out base class for KVM reuse
memory: Introduce memory_region_init_reservation
kvm: Introduce core services for in-kernel irqchip support
kvm: x86: Establish IRQ0 override control
kvm: x86: Add user space part for in-kernel APIC
kvm: x86: Add user space part for in-kernel i8259
kvm: x86: Add user space part for in-kernel IOAPIC
kvm: Activate in-kernel irqchip support

Vadim Rozenfeld (2):
hyper-v: introduce Hyper-V support infrastructure.
hyper-v: initialize Hyper-V CPUID leaves.

  Makefile.objs                  |    2 +-
  Makefile.target                |    8 +-
  configure                      |    1 +
  cpus.c                         |    6 +-
  hw/apic.c                      |  356 ++++++----------------------------------
  hw/apic.h                      |    1 +
  hw/apic_common.c               |  302 ++++++++++++++++++++++++++++++++++
  hw/apic_internal.h             |  115 +++++++++++++
  hw/i8259.c                     |  163 ++++--------------
  hw/i8259_common.c              |  147 +++++++++++++++++
  hw/i8259_internal.h            |   76 +++++++++
  hw/ioapic.c                    |  142 ++--------------
  hw/ioapic_common.c             |  104 ++++++++++++
  hw/ioapic_internal.h           |   97 +++++++++++
  hw/kvm/apic.c                  |  138 ++++++++++++++++
  hw/{kvmclock.c =>  kvm/clock.c} |    4 +-
  hw/{kvmclock.h =>  kvm/clock.h} |    0
  hw/kvm/i8259.c                 |  128 ++++++++++++++
  hw/kvm/ioapic.c                |  114 +++++++++++++
  hw/msi.c                       |    8 +
  hw/msi.h                       |    2 +
  hw/msix.c                      |    9 +-
  hw/msix.h                      |    2 -
  hw/pc.c                        |   20 ++-
  hw/pc.h                        |    8 +-
  hw/pc_piix.c                   |   69 +++++++-
  kvm-all.c                      |  154 +++++++++++++++++
  kvm-stub.c                     |    5 +
  kvm.h                          |   14 ++
  memory.c                       |   36 ++++
  memory.h                       |   16 ++
  qemu-config.c                  |    4 +
  qemu-options.hx                |    5 +-
  sysemu.h                       |    1 -
  target-i386/cpuid.c            |   14 ++
  target-i386/hyperv.c           |   64 +++++++
  target-i386/hyperv.h           |   43 +++++
  target-i386/kvm.c              |  114 +++++++++++++-
  trace-events                   |    2 +-
  vl.c                           |    1 -
  40 files changed, 1902 insertions(+), 593 deletions(-)

create mode 100644 hw/apic_common.c
create mode 100644 hw/apic_internal.h
create mode 100644 hw/i8259_common.c
create mode 100644 hw/i8259_internal.h
create mode 100644 hw/ioapic_common.c
create mode 100644 hw/ioapic_internal.h
create mode 100644 hw/kvm/apic.c
rename hw/{kvmclock.c => kvm/clock.c} (98%)
rename hw/{kvmclock.h => kvm/clock.h} (100%)
create mode 100644 hw/kvm/i8259.c
create mode 100644 hw/kvm/ioapic.c
create mode 100644 target-i386/hyperv.c
create mode 100644 target-i386/hyperv.h