mirror of https://github.com/xqemu/xqemu.git
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
* qemu-kvm/uq/master: kvm: Add documentation comment for kvm_irqchip_in_kernel() kvm: Decouple 'GSI routing' from 'kernel irqchip' kvm: Decouple 'MSI routing via irqfds' from 'kernel irqchip' kvm: Decouple 'irqfds usable' from 'kernel irqchip' kvm: Move kvm_allows_irq0_override() to target-i386, fix return type kvm: Rename kvm_irqchip_set_irq() to kvm_set_irq() kvm: Decouple 'async interrupt delivery' from 'kernel irqchip' configure: Don't implicitly hardcode list of KVM architectures kvm: Check if smp_cpus exceeds max cpus supported by kvm
This commit is contained in:
commit
d517872ec2
|
@ -3563,15 +3563,23 @@ if test "$linux" = "yes" ; then
|
|||
mkdir -p linux-headers
|
||||
case "$cpu" in
|
||||
i386|x86_64)
|
||||
symlink "$source_path/linux-headers/asm-x86" linux-headers/asm
|
||||
linux_arch=x86
|
||||
;;
|
||||
ppcemb|ppc|ppc64)
|
||||
symlink "$source_path/linux-headers/asm-powerpc" linux-headers/asm
|
||||
linux_arch=powerpc
|
||||
;;
|
||||
s390x)
|
||||
symlink "$source_path/linux-headers/asm-s390" linux-headers/asm
|
||||
linux_arch=s390
|
||||
;;
|
||||
*)
|
||||
# For most CPUs the kernel architecture name and QEMU CPU name match.
|
||||
linux_arch="$cpu"
|
||||
;;
|
||||
esac
|
||||
# For non-KVM architectures we will not have asm headers
|
||||
if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then
|
||||
symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm
|
||||
fi
|
||||
fi
|
||||
|
||||
for target in $target_list; do
|
||||
|
|
3
cpus.c
3
cpus.c
|
@ -70,7 +70,8 @@ static bool cpu_thread_is_idle(CPUArchState *env)
|
|||
if (env->stopped || !runstate_is_running()) {
|
||||
return true;
|
||||
}
|
||||
if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) {
|
||||
if (!env->halted || qemu_cpu_has_work(env) ||
|
||||
kvm_async_interrupts_enabled()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -94,7 +94,7 @@ static void kvm_pic_set_irq(void *opaque, int irq, int level)
|
|||
{
|
||||
int delivered;
|
||||
|
||||
delivered = kvm_irqchip_set_irq(kvm_state, irq, level);
|
||||
delivered = kvm_set_irq(kvm_state, irq, level);
|
||||
apic_report_irq_delivered(delivered);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
|
|||
KVMIOAPICState *s = opaque;
|
||||
int delivered;
|
||||
|
||||
delivered = kvm_irqchip_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
|
||||
delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
|
||||
apic_report_irq_delivered(delivered);
|
||||
}
|
||||
|
||||
|
|
1
hw/pc.c
1
hw/pc.c
|
@ -42,6 +42,7 @@
|
|||
#include "sysbus.h"
|
||||
#include "sysemu.h"
|
||||
#include "kvm.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "xen.h"
|
||||
#include "blockdev.h"
|
||||
#include "hw/block-common.h"
|
||||
|
|
|
@ -627,7 +627,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
|||
int r, n;
|
||||
|
||||
/* Must unset vector notifier while guest notifier is still assigned */
|
||||
if (kvm_irqchip_in_kernel() && !assign) {
|
||||
if (kvm_msi_via_irqfd_enabled() && !assign) {
|
||||
msix_unset_vector_notifiers(&proxy->pci_dev);
|
||||
g_free(proxy->vector_irqfd);
|
||||
proxy->vector_irqfd = NULL;
|
||||
|
@ -645,7 +645,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
|||
}
|
||||
|
||||
/* Must set vector notifier after guest notifier has been assigned */
|
||||
if (kvm_irqchip_in_kernel() && assign) {
|
||||
if (kvm_msi_via_irqfd_enabled() && assign) {
|
||||
proxy->vector_irqfd =
|
||||
g_malloc0(sizeof(*proxy->vector_irqfd) *
|
||||
msix_nr_vectors_allocated(&proxy->pci_dev));
|
||||
|
|
54
kvm-all.c
54
kvm-all.c
|
@ -100,6 +100,10 @@ struct KVMState
|
|||
|
||||
KVMState *kvm_state;
|
||||
bool kvm_kernel_irqchip;
|
||||
bool kvm_async_interrupts_allowed;
|
||||
bool kvm_irqfds_allowed;
|
||||
bool kvm_msi_via_irqfd_allowed;
|
||||
bool kvm_gsi_routing_allowed;
|
||||
|
||||
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_INFO(USER_MEMORY),
|
||||
|
@ -852,18 +856,18 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask)
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
|
||||
int kvm_set_irq(KVMState *s, int irq, int level)
|
||||
{
|
||||
struct kvm_irq_level event;
|
||||
int ret;
|
||||
|
||||
assert(kvm_irqchip_in_kernel());
|
||||
assert(kvm_async_interrupts_enabled());
|
||||
|
||||
event.level = level;
|
||||
event.irq = irq;
|
||||
ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event);
|
||||
if (ret < 0) {
|
||||
perror("kvm_set_irqchip_line");
|
||||
perror("kvm_set_irq");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -1088,7 +1092,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
|
|||
|
||||
assert(route->kroute.type == KVM_IRQ_ROUTING_MSI);
|
||||
|
||||
return kvm_irqchip_set_irq(s, route->kroute.gsi, 1);
|
||||
return kvm_set_irq(s, route->kroute.gsi, 1);
|
||||
}
|
||||
|
||||
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
|
||||
|
@ -1096,7 +1100,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
|
|||
struct kvm_irq_routing_entry kroute;
|
||||
int virq;
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
if (!kvm_gsi_routing_enabled()) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
@ -1125,7 +1129,7 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
|
|||
.flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
|
||||
};
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
if (!kvm_irqfds_enabled()) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
@ -1201,12 +1205,36 @@ static int kvm_irqchip_create(KVMState *s)
|
|||
s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
|
||||
}
|
||||
kvm_kernel_irqchip = true;
|
||||
/* If we have an in-kernel IRQ chip then we must have asynchronous
|
||||
* interrupt delivery (though the reverse is not necessarily true)
|
||||
*/
|
||||
kvm_async_interrupts_allowed = true;
|
||||
|
||||
kvm_init_irq_routing(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_max_vcpus(KVMState *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Find number of supported CPUs using the recommended
|
||||
* procedure from the kernel API documentation to cope with
|
||||
* older kernels that may be missing capabilities.
|
||||
*/
|
||||
ret = kvm_check_extension(s, KVM_CAP_MAX_VCPUS);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_check_extension(s, KVM_CAP_NR_VCPUS);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int kvm_init(void)
|
||||
{
|
||||
static const char upgrade_note[] =
|
||||
|
@ -1216,6 +1244,7 @@ int kvm_init(void)
|
|||
const KVMCapabilityInfo *missing_cap;
|
||||
int ret;
|
||||
int i;
|
||||
int max_vcpus;
|
||||
|
||||
s = g_malloc0(sizeof(KVMState));
|
||||
|
||||
|
@ -1256,6 +1285,14 @@ int kvm_init(void)
|
|||
goto err;
|
||||
}
|
||||
|
||||
max_vcpus = kvm_max_vcpus(s);
|
||||
if (smp_cpus > max_vcpus) {
|
||||
ret = -EINVAL;
|
||||
fprintf(stderr, "Number of SMP cpus requested (%d) exceeds max cpus "
|
||||
"supported by KVM (%d)\n", smp_cpus, max_vcpus);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0);
|
||||
if (s->vmfd < 0) {
|
||||
#ifdef TARGET_S390X
|
||||
|
@ -1667,11 +1704,6 @@ int kvm_has_gsi_routing(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
int kvm_allows_irq0_override(void)
|
||||
{
|
||||
return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
|
||||
}
|
||||
|
||||
void *kvm_vmalloc(ram_addr_t size)
|
||||
{
|
||||
#ifdef TARGET_S390X
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
KVMState *kvm_state;
|
||||
bool kvm_kernel_irqchip;
|
||||
bool kvm_async_interrupts_allowed;
|
||||
bool kvm_irqfds_allowed;
|
||||
bool kvm_msi_via_irqfd_allowed;
|
||||
bool kvm_gsi_routing_allowed;
|
||||
|
||||
int kvm_init_vcpu(CPUArchState *env)
|
||||
{
|
||||
|
@ -71,11 +75,6 @@ int kvm_has_many_ioeventfds(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_allows_irq0_override(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_has_pit_state2(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
60
kvm.h
60
kvm.h
|
@ -24,13 +24,69 @@
|
|||
|
||||
extern int kvm_allowed;
|
||||
extern bool kvm_kernel_irqchip;
|
||||
extern bool kvm_async_interrupts_allowed;
|
||||
extern bool kvm_irqfds_allowed;
|
||||
extern bool kvm_msi_via_irqfd_allowed;
|
||||
extern bool kvm_gsi_routing_allowed;
|
||||
|
||||
#if defined CONFIG_KVM || !defined NEED_CPU_H
|
||||
#define kvm_enabled() (kvm_allowed)
|
||||
/**
|
||||
* kvm_irqchip_in_kernel:
|
||||
*
|
||||
* Returns: true if the user asked us to create an in-kernel
|
||||
* irqchip via the "kernel_irqchip=on" machine option.
|
||||
* What this actually means is architecture and machine model
|
||||
* specific: on PC, for instance, it means that the LAPIC,
|
||||
* IOAPIC and PIT are all in kernel. This function should never
|
||||
* be used from generic target-independent code: use one of the
|
||||
* following functions or some other specific check instead.
|
||||
*/
|
||||
#define kvm_irqchip_in_kernel() (kvm_kernel_irqchip)
|
||||
|
||||
/**
|
||||
* kvm_async_interrupts_enabled:
|
||||
*
|
||||
* Returns: true if we can deliver interrupts to KVM
|
||||
* asynchronously (ie by ioctl from any thread at any time)
|
||||
* rather than having to do interrupt delivery synchronously
|
||||
* (where the vcpu must be stopped at a suitable point first).
|
||||
*/
|
||||
#define kvm_async_interrupts_enabled() (kvm_async_interrupts_allowed)
|
||||
|
||||
/**
|
||||
* kvm_irqfds_enabled:
|
||||
*
|
||||
* Returns: true if we can use irqfds to inject interrupts into
|
||||
* a KVM CPU (ie the kernel supports irqfds and we are running
|
||||
* with a configuration where it is meaningful to use them).
|
||||
*/
|
||||
#define kvm_irqfds_enabled() (kvm_irqfds_allowed)
|
||||
|
||||
/**
|
||||
* kvm_msi_via_irqfd_enabled:
|
||||
*
|
||||
* Returns: true if we can route a PCI MSI (Message Signaled Interrupt)
|
||||
* to a KVM CPU via an irqfd. This requires that the kernel supports
|
||||
* this and that we're running in a configuration that permits it.
|
||||
*/
|
||||
#define kvm_msi_via_irqfd_enabled() (kvm_msi_via_irqfd_allowed)
|
||||
|
||||
/**
|
||||
* kvm_gsi_routing_enabled:
|
||||
*
|
||||
* Returns: true if GSI routing is enabled (ie the kernel supports
|
||||
* it and we're running in a configuration that permits it).
|
||||
*/
|
||||
#define kvm_gsi_routing_enabled() (kvm_gsi_routing_allowed)
|
||||
|
||||
#else
|
||||
#define kvm_enabled() (0)
|
||||
#define kvm_irqchip_in_kernel() (false)
|
||||
#define kvm_async_interrupts_enabled() (false)
|
||||
#define kvm_irqfds_enabled() (false)
|
||||
#define kvm_msi_via_irqfd_enabled() (false)
|
||||
#define kvm_gsi_routing_allowed() (false)
|
||||
#endif
|
||||
|
||||
struct kvm_run;
|
||||
|
@ -62,8 +118,6 @@ int kvm_has_pit_state2(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(CPUArchState *env);
|
||||
|
||||
|
@ -133,7 +187,7 @@ 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);
|
||||
int kvm_set_irq(KVMState *s, int irq, int level);
|
||||
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
|
||||
|
||||
void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
|
||||
|
|
|
@ -3,6 +3,7 @@ obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
|
|||
obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
|
||||
obj-$(CONFIG_KVM) += kvm.o hyperv.o
|
||||
obj-$(CONFIG_NO_KVM) += kvm-stub.o
|
||||
obj-$(CONFIG_LINUX_USER) += ioport-user.o
|
||||
obj-$(CONFIG_BSD_USER) += ioport-user.o
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* QEMU KVM x86 specific function stubs
|
||||
*
|
||||
* Copyright Linaro Limited 2012
|
||||
*
|
||||
* Author: Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* 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 "qemu-common.h"
|
||||
#include "kvm_i386.h"
|
||||
|
||||
bool kvm_allows_irq0_override(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include "qemu-common.h"
|
||||
#include "sysemu.h"
|
||||
#include "kvm.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "cpu.h"
|
||||
#include "gdbstub.h"
|
||||
#include "host-utils.h"
|
||||
|
@ -65,6 +66,11 @@ static bool has_msr_async_pf_en;
|
|||
static bool has_msr_misc_enable;
|
||||
static int lm_capable_kernel;
|
||||
|
||||
bool kvm_allows_irq0_override(void)
|
||||
{
|
||||
return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
|
||||
}
|
||||
|
||||
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
|
||||
{
|
||||
struct kvm_cpuid2 *cpuid;
|
||||
|
@ -2041,4 +2047,11 @@ void kvm_arch_init_irq_routing(KVMState *s)
|
|||
*/
|
||||
no_hpet = 1;
|
||||
}
|
||||
/* We know at this point that we're using the in-kernel
|
||||
* irqchip, so we can use irqfds, and on x86 we know
|
||||
* we can use msi via irqfd and GSI routing.
|
||||
*/
|
||||
kvm_irqfds_allowed = true;
|
||||
kvm_msi_via_irqfd_allowed = true;
|
||||
kvm_gsi_routing_allowed = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* QEMU KVM support -- x86 specific functions.
|
||||
*
|
||||
* Copyright (c) 2012 Linaro Limited
|
||||
*
|
||||
* 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_KVM_I386_H
|
||||
#define QEMU_KVM_I386_H
|
||||
|
||||
bool kvm_allows_irq0_override(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue