qemu-kvm.git uq/master queue
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.hPATCH 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
@@ -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
@@ -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
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]Signed-off-by Marcelo Tosatti <[email protected]>--- 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.hMakefile.target +2
-0@@ -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@@ -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@@ -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@@ -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
PATCH 2/20 hyper-v: initialize Hyper-V CPUID leaves.
In reply to Marcelo TosattiFrom: Vadim Rozenfeld <[email protected]>
--- target-i386/kvm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 63 insertions(+), 2 deletions(-)
target-i386/kvm.c +63 -2
@@ -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
PATCH 3/20 msi: Generalize msix_supported to msi_supported
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 4/20 kvm: Move kvmclock into hw/kvm folder
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 5/20 apic: Stop timer on reset
In reply to Marcelo TosattiFrom: 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
@@ -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
PATCH 6/20 apic: Inject external NMI events via LINT1
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
@@ -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
PATCH 7/20 apic: Introduce apic_report_irq_delivered
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
@@ -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
PATCH 8/20 apic: Factor out base class for KVM reuse
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 9/20 apic: Open-code timer save/restore
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 10/20 i8259: Completely privatize PicState
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 11/20 i8259: Factor out base class for KVM reuse
In reply to Marcelo TosattiFrom: 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
@@ -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
PATCH 12/20 ioapic: Drop post-load irr initialization
In reply to Marcelo TosattiFrom: 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
@@ -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
PATCH 13/20 ioapic: Factor out base class for KVM reuse
In reply to Marcelo TosattiFrom: 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
@@ -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
PATCH 14/20 memory: Introduce memory_region_init_reservation
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 15/20 kvm: Introduce core services for in-kernel irqchip support
In reply to Marcelo TosattiFrom: 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
@@ -78,6 +78,13 @@ struct KVMStateint 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
@@ -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
@@ -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
PATCH 16/20 kvm: x86: Establish IRQ0 override control
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 17/20 kvm: x86: Add user space part for in-kernel APIC
In reply to Marcelo TosattiFrom: 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 18/20 kvm: x86: Add user space part for in-kernel i8259
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 19/20 kvm: x86: Add user space part for in-kernel IOAPIC
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
PATCH 20/20 kvm: Activate in-kernel irqchip support
In reply to Marcelo TosattiFrom: 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
@@ -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
@@ -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
Anthony Liguori
AppliedQuoted 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.gituq/master
Applied. Thanks.
Regards,
Anthony Liguori
Quoted 81 lines
Jan Kiszka (18):
msi: Generalizemsix_supportedtomsi_supported
kvm: Move kvmclock into hw/kvm folder
apic: Stop timer on reset
apic: Inject external NMI events via LINT1
apic: Introduceapic_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: Introducememory_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 supportVadim 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 100644hw/apic_internal.h
create mode 100644hw/i8259_common.c
create mode 100644hw/i8259_internal.h
create mode 100644hw/ioapic_common.c
create mode 100644hw/ioapic_internal.h
create mode 100644hw/kvm/apic.c
renamehw/{kvmclock.c=>kvm/clock.c} (98%)
renamehw/{kvmclock.h=>kvm/clock.h} (100%)
create mode 100644hw/kvm/i8259.c
create mode 100644hw/kvm/ioapic.c
create mode 100644target-i386/hyperv.c
create mode 100644target-i386/hyperv.h