From 404fb280b7119e7120d0dd225b40d2cb29fb202f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 5 Mar 2013 03:18:00 +0000 Subject: [PATCH] --- yaml --- r: 373142 b: refs/heads/master c: 210552c1bfe83122a480673660d5ca9821c944ae h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/virtual/kvm/api.txt | 8 - .../virtual/kvm/devices/mpic.txt | 3 + .../virtual/kvm/devices/xics.txt | 66 ------ trunk/arch/arm/include/asm/kvm_host.h | 3 + trunk/arch/arm/kvm/Makefile | 2 +- trunk/arch/arm/kvm/arm.c | 4 + trunk/arch/arm/kvm/perf.c | 68 +++++++ trunk/arch/ia64/kvm/kvm-ia64.c | 2 - trunk/arch/powerpc/include/asm/kvm_ppc.h | 2 - trunk/arch/powerpc/include/uapi/asm/kvm.h | 12 -- trunk/arch/powerpc/kvm/book3s_xics.c | 190 +++--------------- trunk/arch/powerpc/kvm/book3s_xics.h | 1 - trunk/arch/powerpc/kvm/irq.h | 3 - trunk/arch/powerpc/kvm/mpic.c | 56 +++--- trunk/arch/powerpc/kvm/powerpc.c | 45 +---- trunk/arch/x86/include/asm/kvm_host.h | 2 +- trunk/arch/x86/kvm/svm.c | 5 +- trunk/arch/x86/kvm/vmx.c | 16 +- trunk/arch/x86/kvm/x86.c | 5 +- trunk/include/linux/kvm_host.h | 1 - trunk/include/uapi/linux/kvm.h | 2 - trunk/virt/kvm/kvm_main.c | 5 - 23 files changed, 145 insertions(+), 358 deletions(-) delete mode 100644 trunk/Documentation/virtual/kvm/devices/xics.txt create mode 100644 trunk/arch/arm/kvm/perf.c diff --git a/[refs] b/[refs] index 3c152117b6e0..9d431a38d8a3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 03b28f8133165dbe4cd922054d599e26b8119508 +refs/heads/master: 210552c1bfe83122a480673660d5ca9821c944ae diff --git a/trunk/Documentation/virtual/kvm/api.txt b/trunk/Documentation/virtual/kvm/api.txt index 03492f95ed39..c09d1832e935 100644 --- a/trunk/Documentation/virtual/kvm/api.txt +++ b/trunk/Documentation/virtual/kvm/api.txt @@ -2772,11 +2772,3 @@ Parameters: args[0] is the MPIC device fd args[1] is the MPIC CPU number for this vcpu This capability connects the vcpu to an in-kernel MPIC device. - -6.7 KVM_CAP_IRQ_XICS - -Architectures: ppc -Parameters: args[0] is the XICS device fd - args[1] is the XICS CPU number (server ID) for this vcpu - -This capability connects the vcpu to an in-kernel XICS device. diff --git a/trunk/Documentation/virtual/kvm/devices/mpic.txt b/trunk/Documentation/virtual/kvm/devices/mpic.txt index 8257397adc3c..ad0ac778f20a 100644 --- a/trunk/Documentation/virtual/kvm/devices/mpic.txt +++ b/trunk/Documentation/virtual/kvm/devices/mpic.txt @@ -50,4 +50,7 @@ IRQ Routing: regard to any subdivisions in chip documentation such as "internal" or "external" interrupts. + Default routes are established for these pins, with the GSI being equal + to the pin number. + Access to non-SRC interrupts is not implemented through IRQ routing mechanisms. diff --git a/trunk/Documentation/virtual/kvm/devices/xics.txt b/trunk/Documentation/virtual/kvm/devices/xics.txt deleted file mode 100644 index 42864935ac5d..000000000000 --- a/trunk/Documentation/virtual/kvm/devices/xics.txt +++ /dev/null @@ -1,66 +0,0 @@ -XICS interrupt controller - -Device type supported: KVM_DEV_TYPE_XICS - -Groups: - KVM_DEV_XICS_SOURCES - Attributes: One per interrupt source, indexed by the source number. - -This device emulates the XICS (eXternal Interrupt Controller -Specification) defined in PAPR. The XICS has a set of interrupt -sources, each identified by a 20-bit source number, and a set of -Interrupt Control Presentation (ICP) entities, also called "servers", -each associated with a virtual CPU. - -The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH -capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and -the interrupt server number (i.e. the vcpu number from the XICS's -point of view) in args[1] of the kvm_enable_cap struct. Each ICP has -64 bits of state which can be read and written using the -KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu. The 64 bit -state word has the following bitfields, starting at the -least-significant end of the word: - -* Unused, 16 bits - -* Pending interrupt priority, 8 bits - Zero is the highest priority, 255 means no interrupt is pending. - -* Pending IPI (inter-processor interrupt) priority, 8 bits - Zero is the highest priority, 255 means no IPI is pending. - -* Pending interrupt source number, 24 bits - Zero means no interrupt pending, 2 means an IPI is pending - -* Current processor priority, 8 bits - Zero is the highest priority, meaning no interrupts can be - delivered, and 255 is the lowest priority. - -Each source has 64 bits of state that can be read and written using -the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the -KVM_DEV_XICS_SOURCES attribute group, with the attribute number being -the interrupt source number. The 64 bit state word has the following -bitfields, starting from the least-significant end of the word: - -* Destination (server number), 32 bits - This specifies where the interrupt should be sent, and is the - interrupt server number specified for the destination vcpu. - -* Priority, 8 bits - This is the priority specified for this interrupt source, where 0 is - the highest priority and 255 is the lowest. An interrupt with a - priority of 255 will never be delivered. - -* Level sensitive flag, 1 bit - This bit is 1 for a level-sensitive interrupt source, or 0 for - edge-sensitive (or MSI). - -* Masked flag, 1 bit - This bit is set to 1 if the interrupt is masked (cannot be delivered - regardless of its priority), for example by the ibm,int-off RTAS - call, or 0 if it is not masked. - -* Pending flag, 1 bit - This bit is 1 if the source has a pending interrupt, otherwise 0. - -Only one XICS instance may be created per VM. diff --git a/trunk/arch/arm/include/asm/kvm_host.h b/trunk/arch/arm/include/asm/kvm_host.h index 0c4e643d939e..78813b8fad32 100644 --- a/trunk/arch/arm/include/asm/kvm_host.h +++ b/trunk/arch/arm/include/asm/kvm_host.h @@ -207,4 +207,7 @@ static inline void __cpu_init_hyp_mode(unsigned long long pgd_ptr, kvm_call_hyp((void *)pgd_low, pgd_high, hyp_stack_ptr, vector_ptr); } +int kvm_perf_init(void); +int kvm_perf_teardown(void); + #endif /* __ARM_KVM_HOST_H__ */ diff --git a/trunk/arch/arm/kvm/Makefile b/trunk/arch/arm/kvm/Makefile index 8dc5e76cb789..53c5ed83d16f 100644 --- a/trunk/arch/arm/kvm/Makefile +++ b/trunk/arch/arm/kvm/Makefile @@ -18,6 +18,6 @@ kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) obj-y += kvm-arm.o init.o interrupts.o obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o -obj-y += coproc.o coproc_a15.o mmio.o psci.o +obj-y += coproc.o coproc_a15.o mmio.o psci.o perf.o obj-$(CONFIG_KVM_ARM_VGIC) += vgic.o obj-$(CONFIG_KVM_ARM_TIMER) += arch_timer.o diff --git a/trunk/arch/arm/kvm/arm.c b/trunk/arch/arm/kvm/arm.c index 1497e18a9e2a..7403f884a545 100644 --- a/trunk/arch/arm/kvm/arm.c +++ b/trunk/arch/arm/kvm/arm.c @@ -920,7 +920,10 @@ static int init_hyp_mode(void) if (err) goto out_free_mappings; + kvm_perf_init(); + kvm_info("Hyp mode initialized successfully\n"); + return 0; out_free_vfp: free_percpu(kvm_host_vfp_state); @@ -964,6 +967,7 @@ int kvm_arch_init(void *opaque) /* NOP: Compiling as a module not supported */ void kvm_arch_exit(void) { + kvm_perf_teardown(); } static int arm_init(void) diff --git a/trunk/arch/arm/kvm/perf.c b/trunk/arch/arm/kvm/perf.c new file mode 100644 index 000000000000..1a3849da0b4b --- /dev/null +++ b/trunk/arch/arm/kvm/perf.c @@ -0,0 +1,68 @@ +/* + * Based on the x86 implementation. + * + * Copyright (C) 2012 ARM Ltd. + * Author: Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include + +static int kvm_is_in_guest(void) +{ + return kvm_arm_get_running_vcpu() != NULL; +} + +static int kvm_is_user_mode(void) +{ + struct kvm_vcpu *vcpu; + + vcpu = kvm_arm_get_running_vcpu(); + + if (vcpu) + return !vcpu_mode_priv(vcpu); + + return 0; +} + +static unsigned long kvm_get_guest_ip(void) +{ + struct kvm_vcpu *vcpu; + + vcpu = kvm_arm_get_running_vcpu(); + + if (vcpu) + return *vcpu_pc(vcpu); + + return 0; +} + +static struct perf_guest_info_callbacks kvm_guest_cbs = { + .is_in_guest = kvm_is_in_guest, + .is_user_mode = kvm_is_user_mode, + .get_guest_ip = kvm_get_guest_ip, +}; + +int kvm_perf_init(void) +{ + return perf_register_guest_info_callbacks(&kvm_guest_cbs); +} + +int kvm_perf_teardown(void) +{ + return perf_unregister_guest_info_callbacks(&kvm_guest_cbs); +} diff --git a/trunk/arch/ia64/kvm/kvm-ia64.c b/trunk/arch/ia64/kvm/kvm-ia64.c index 5b2dc0d10c8f..dcc560729c20 100644 --- a/trunk/arch/ia64/kvm/kvm-ia64.c +++ b/trunk/arch/ia64/kvm/kvm-ia64.c @@ -204,11 +204,9 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; -#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT case KVM_CAP_IOMMU: r = iommu_present(&pci_bus_type); break; -#endif default: r = 0; } diff --git a/trunk/arch/powerpc/include/asm/kvm_ppc.h b/trunk/arch/powerpc/include/asm/kvm_ppc.h index a5287fe03d77..d7339df19259 100644 --- a/trunk/arch/powerpc/include/asm/kvm_ppc.h +++ b/trunk/arch/powerpc/include/asm/kvm_ppc.h @@ -315,8 +315,6 @@ extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args); extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd); extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu); extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval); -extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev, - struct kvm_vcpu *vcpu, u32 cpu); #else static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu) { return 0; } diff --git a/trunk/arch/powerpc/include/uapi/asm/kvm.h b/trunk/arch/powerpc/include/uapi/asm/kvm.h index 0fb1a6e9ff90..427b9aca2a0f 100644 --- a/trunk/arch/powerpc/include/uapi/asm/kvm.h +++ b/trunk/arch/powerpc/include/uapi/asm/kvm.h @@ -499,16 +499,4 @@ struct kvm_get_htab_header { #define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a) #define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b) -/* PPC64 eXternal Interrupt Controller Specification */ -#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */ - -/* Layout of 64-bit source attribute values */ -#define KVM_XICS_DESTINATION_SHIFT 0 -#define KVM_XICS_DESTINATION_MASK 0xffffffffULL -#define KVM_XICS_PRIORITY_SHIFT 32 -#define KVM_XICS_PRIORITY_MASK 0xff -#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40) -#define KVM_XICS_MASKED (1ULL << 41) -#define KVM_XICS_PENDING (1ULL << 42) - #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/trunk/arch/powerpc/kvm/book3s_xics.c b/trunk/arch/powerpc/kvm/book3s_xics.c index f7a103756618..ee841ed8a690 100644 --- a/trunk/arch/powerpc/kvm/book3s_xics.c +++ b/trunk/arch/powerpc/kvm/book3s_xics.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -56,6 +55,8 @@ * * - Make ICS lockless as well, or at least a per-interrupt lock or hashed * locks array to improve scalability + * + * - ioctl's to save/restore the entire state for snapshot & migration */ /* -- ICS routines -- */ @@ -63,8 +64,7 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, u32 new_irq); -static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, - bool report_status) +static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level) { struct ics_irq_state *state; struct kvmppc_ics *ics; @@ -81,9 +81,6 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, if (!state->exists) return -EINVAL; - if (report_status) - return state->asserted; - /* * We set state->asserted locklessly. This should be fine as * we are the only setter, thus concurrent access is undefined @@ -99,7 +96,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, /* Attempt delivery */ icp_deliver_irq(xics, NULL, irq); - return state->asserted; + return 0; } static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics, @@ -894,8 +891,8 @@ static void xics_debugfs_init(struct kvmppc_xics *xics) kfree(name); } -static struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm, - struct kvmppc_xics *xics, int irq) +struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm, + struct kvmppc_xics *xics, int irq) { struct kvmppc_ics *ics; int i, icsid; @@ -1047,138 +1044,34 @@ int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval) return 0; } -static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr) -{ - int ret; - struct kvmppc_ics *ics; - struct ics_irq_state *irqp; - u64 __user *ubufp = (u64 __user *) addr; - u16 idx; - u64 val, prio; - - ics = kvmppc_xics_find_ics(xics, irq, &idx); - if (!ics) - return -ENOENT; - - irqp = &ics->irq_state[idx]; - mutex_lock(&ics->lock); - ret = -ENOENT; - if (irqp->exists) { - val = irqp->server; - prio = irqp->priority; - if (prio == MASKED) { - val |= KVM_XICS_MASKED; - prio = irqp->saved_priority; - } - val |= prio << KVM_XICS_PRIORITY_SHIFT; - if (irqp->asserted) - val |= KVM_XICS_LEVEL_SENSITIVE | KVM_XICS_PENDING; - else if (irqp->masked_pending || irqp->resend) - val |= KVM_XICS_PENDING; - ret = 0; - } - mutex_unlock(&ics->lock); - - if (!ret && put_user(val, ubufp)) - ret = -EFAULT; - - return ret; -} - -static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr) -{ - struct kvmppc_ics *ics; - struct ics_irq_state *irqp; - u64 __user *ubufp = (u64 __user *) addr; - u16 idx; - u64 val; - u8 prio; - u32 server; - - if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS) - return -ENOENT; - - ics = kvmppc_xics_find_ics(xics, irq, &idx); - if (!ics) { - ics = kvmppc_xics_create_ics(xics->kvm, xics, irq); - if (!ics) - return -ENOMEM; - } - irqp = &ics->irq_state[idx]; - if (get_user(val, ubufp)) - return -EFAULT; - - server = val & KVM_XICS_DESTINATION_MASK; - prio = val >> KVM_XICS_PRIORITY_SHIFT; - if (prio != MASKED && - kvmppc_xics_find_server(xics->kvm, server) == NULL) - return -EINVAL; - - mutex_lock(&ics->lock); - irqp->server = server; - irqp->saved_priority = prio; - if (val & KVM_XICS_MASKED) - prio = MASKED; - irqp->priority = prio; - irqp->resend = 0; - irqp->masked_pending = 0; - irqp->asserted = 0; - if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE)) - irqp->asserted = 1; - irqp->exists = 1; - mutex_unlock(&ics->lock); - - if (val & KVM_XICS_PENDING) - icp_deliver_irq(xics, NULL, irqp->number); - - return 0; -} - -int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status) -{ - struct kvmppc_xics *xics = kvm->arch.xics; - - return ics_deliver_irq(xics, irq, level, line_status); -} +/* -- ioctls -- */ -static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args) { - struct kvmppc_xics *xics = dev->private; + struct kvmppc_xics *xics; + int r; - switch (attr->group) { - case KVM_DEV_XICS_GRP_SOURCES: - return xics_set_source(xics, attr->attr, attr->addr); - } - return -ENXIO; -} + /* locking against multiple callers? */ -static int xics_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) -{ - struct kvmppc_xics *xics = dev->private; - - switch (attr->group) { - case KVM_DEV_XICS_GRP_SOURCES: - return xics_get_source(xics, attr->attr, attr->addr); - } - return -ENXIO; -} + xics = kvm->arch.xics; + if (!xics) + return -ENODEV; -static int xics_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) -{ - switch (attr->group) { - case KVM_DEV_XICS_GRP_SOURCES: - if (attr->attr >= KVMPPC_XICS_FIRST_IRQ && - attr->attr < KVMPPC_XICS_NR_IRQS) - return 0; + switch (args->level) { + case KVM_INTERRUPT_SET: + case KVM_INTERRUPT_SET_LEVEL: + case KVM_INTERRUPT_UNSET: + r = ics_deliver_irq(xics, args->irq, args->level); break; + default: + r = -EINVAL; } - return -ENXIO; + + return r; } -static void kvmppc_xics_free(struct kvm_device *dev) +void kvmppc_xics_free(struct kvmppc_xics *xics) { - struct kvmppc_xics *xics = dev->private; int i; struct kvm *kvm = xics->kvm; @@ -1190,21 +1083,17 @@ static void kvmppc_xics_free(struct kvm_device *dev) for (i = 0; i <= xics->max_icsid; i++) kfree(xics->ics[i]); kfree(xics); - kfree(dev); } -static int kvmppc_xics_create(struct kvm_device *dev, u32 type) +int kvm_xics_create(struct kvm *kvm, u32 type) { struct kvmppc_xics *xics; - struct kvm *kvm = dev->kvm; int ret = 0; xics = kzalloc(sizeof(*xics), GFP_KERNEL); if (!xics) return -ENOMEM; - dev->private = xics; - xics->dev = dev; xics->kvm = kvm; /* Already there ? */ @@ -1231,35 +1120,6 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type) return 0; } -struct kvm_device_ops kvm_xics_ops = { - .name = "kvm-xics", - .create = kvmppc_xics_create, - .destroy = kvmppc_xics_free, - .set_attr = xics_set_attr, - .get_attr = xics_get_attr, - .has_attr = xics_has_attr, -}; - -int kvmppc_xics_connect_vcpu(struct kvm_device *dev, struct kvm_vcpu *vcpu, - u32 xcpu) -{ - struct kvmppc_xics *xics = dev->private; - int r = -EBUSY; - - if (dev->ops != &kvm_xics_ops) - return -EPERM; - if (xics->kvm != vcpu->kvm) - return -EPERM; - if (vcpu->arch.irq_type) - return -EBUSY; - - r = kvmppc_xics_create_icp(vcpu, xcpu); - if (!r) - vcpu->arch.irq_type = KVMPPC_IRQ_XICS; - - return r; -} - void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { if (!vcpu->arch.icp) diff --git a/trunk/arch/powerpc/kvm/book3s_xics.h b/trunk/arch/powerpc/kvm/book3s_xics.h index dd9326c5c19b..e4fdec3dde77 100644 --- a/trunk/arch/powerpc/kvm/book3s_xics.h +++ b/trunk/arch/powerpc/kvm/book3s_xics.h @@ -88,7 +88,6 @@ struct kvmppc_ics { struct kvmppc_xics { struct kvm *kvm; - struct kvm_device *dev; struct dentry *dentry; u32 max_icsid; bool real_mode; diff --git a/trunk/arch/powerpc/kvm/irq.h b/trunk/arch/powerpc/kvm/irq.h index 5a9a10b90762..f1e27fdc8c2e 100644 --- a/trunk/arch/powerpc/kvm/irq.h +++ b/trunk/arch/powerpc/kvm/irq.h @@ -9,9 +9,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm) #ifdef CONFIG_KVM_MPIC ret = ret || (kvm->arch.mpic != NULL); -#endif -#ifdef CONFIG_KVM_XICS - ret = ret || (kvm->arch.xics != NULL); #endif smp_rmb(); return ret; diff --git a/trunk/arch/powerpc/kvm/mpic.c b/trunk/arch/powerpc/kvm/mpic.c index 2861ae9eaae6..f3148f8cdc12 100644 --- a/trunk/arch/powerpc/kvm/mpic.c +++ b/trunk/arch/powerpc/kvm/mpic.c @@ -184,14 +184,12 @@ struct irq_dest { uint32_t outputs_active[NUM_OUTPUTS]; }; -#define MAX_MMIO_REGIONS 10 - struct openpic { struct kvm *kvm; struct kvm_device *dev; struct kvm_io_device mmio; - const struct mem_reg *mmio_regions[MAX_MMIO_REGIONS]; - int num_mmio_regions; + struct list_head mmio_regions; + atomic_t users; gpa_t reg_base; spinlock_t lock; @@ -1240,71 +1238,62 @@ static int openpic_cpu_read(void *opaque, gpa_t addr, u32 *ptr) } struct mem_reg { + struct list_head list; int (*read)(void *opaque, gpa_t addr, u32 *ptr); int (*write)(void *opaque, gpa_t addr, u32 val); gpa_t start_addr; int size; }; -static const struct mem_reg openpic_gbl_mmio = { +static struct mem_reg openpic_gbl_mmio = { .write = openpic_gbl_write, .read = openpic_gbl_read, .start_addr = OPENPIC_GLB_REG_START, .size = OPENPIC_GLB_REG_SIZE, }; -static const struct mem_reg openpic_tmr_mmio = { +static struct mem_reg openpic_tmr_mmio = { .write = openpic_tmr_write, .read = openpic_tmr_read, .start_addr = OPENPIC_TMR_REG_START, .size = OPENPIC_TMR_REG_SIZE, }; -static const struct mem_reg openpic_cpu_mmio = { +static struct mem_reg openpic_cpu_mmio = { .write = openpic_cpu_write, .read = openpic_cpu_read, .start_addr = OPENPIC_CPU_REG_START, .size = OPENPIC_CPU_REG_SIZE, }; -static const struct mem_reg openpic_src_mmio = { +static struct mem_reg openpic_src_mmio = { .write = openpic_src_write, .read = openpic_src_read, .start_addr = OPENPIC_SRC_REG_START, .size = OPENPIC_SRC_REG_SIZE, }; -static const struct mem_reg openpic_msi_mmio = { +static struct mem_reg openpic_msi_mmio = { .read = openpic_msi_read, .write = openpic_msi_write, .start_addr = OPENPIC_MSI_REG_START, .size = OPENPIC_MSI_REG_SIZE, }; -static const struct mem_reg openpic_summary_mmio = { +static struct mem_reg openpic_summary_mmio = { .read = openpic_summary_read, .write = openpic_summary_write, .start_addr = OPENPIC_SUMMARY_REG_START, .size = OPENPIC_SUMMARY_REG_SIZE, }; -static void add_mmio_region(struct openpic *opp, const struct mem_reg *mr) -{ - if (opp->num_mmio_regions >= MAX_MMIO_REGIONS) { - WARN(1, "kvm mpic: too many mmio regions\n"); - return; - } - - opp->mmio_regions[opp->num_mmio_regions++] = mr; -} - static void fsl_common_init(struct openpic *opp) { int i; int virq = MAX_SRC; - add_mmio_region(opp, &openpic_msi_mmio); - add_mmio_region(opp, &openpic_summary_mmio); + list_add(&openpic_msi_mmio.list, &opp->mmio_regions); + list_add(&openpic_summary_mmio.list, &opp->mmio_regions); opp->vid = VID_REVISION_1_2; opp->vir = VIR_GENERIC; @@ -1341,10 +1330,10 @@ static void fsl_common_init(struct openpic *opp) static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) { - int i; + struct list_head *node; - for (i = 0; i < opp->num_mmio_regions; i++) { - const struct mem_reg *mr = opp->mmio_regions[i]; + list_for_each(node, &opp->mmio_regions) { + struct mem_reg *mr = list_entry(node, struct mem_reg, list); if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) continue; @@ -1357,10 +1346,10 @@ static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val) { - int i; + struct list_head *node; - for (i = 0; i < opp->num_mmio_regions; i++) { - const struct mem_reg *mr = opp->mmio_regions[i]; + list_for_each(node, &opp->mmio_regions) { + struct mem_reg *mr = list_entry(node, struct mem_reg, list); if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) continue; @@ -1486,8 +1475,8 @@ static int set_base_addr(struct openpic *opp, struct kvm_device_attr *attr) map_mmio(opp); -out: mutex_unlock(&opp->kvm->slots_lock); +out: return 0; } @@ -1671,10 +1660,11 @@ static int mpic_create(struct kvm_device *dev, u32 type) opp->model = type; spin_lock_init(&opp->lock); - add_mmio_region(opp, &openpic_gbl_mmio); - add_mmio_region(opp, &openpic_tmr_mmio); - add_mmio_region(opp, &openpic_src_mmio); - add_mmio_region(opp, &openpic_cpu_mmio); + INIT_LIST_HEAD(&opp->mmio_regions); + list_add(&openpic_gbl_mmio.list, &opp->mmio_regions); + list_add(&openpic_tmr_mmio.list, &opp->mmio_regions); + list_add(&openpic_src_mmio.list, &opp->mmio_regions); + list_add(&openpic_cpu_mmio.list, &opp->mmio_regions); switch (opp->model) { case KVM_DEV_TYPE_FSL_MPIC_20: diff --git a/trunk/arch/powerpc/kvm/powerpc.c b/trunk/arch/powerpc/kvm/powerpc.c index 6316ee336e88..31084c6335c9 100644 --- a/trunk/arch/powerpc/kvm/powerpc.c +++ b/trunk/arch/powerpc/kvm/powerpc.c @@ -342,9 +342,6 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_SPAPR_TCE: case KVM_CAP_PPC_ALLOC_HTAB: case KVM_CAP_PPC_RTAS: -#ifdef CONFIG_KVM_XICS - case KVM_CAP_IRQ_XICS: -#endif r = 1; break; #endif /* CONFIG_PPC_BOOK3S_64 */ @@ -625,8 +622,6 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned int rt, unsigned int bytes, int is_bigendian) { - int idx, ret; - if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); @@ -642,14 +637,8 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, vcpu->mmio_is_write = 0; vcpu->arch.mmio_sign_extend = 0; - idx = srcu_read_lock(&vcpu->kvm->srcu); - - ret = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, - bytes, &run->mmio.data); - - srcu_read_unlock(&vcpu->kvm->srcu, idx); - - if (!ret) { + if (!kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, + bytes, &run->mmio.data)) { kvmppc_complete_mmio_load(vcpu, run); vcpu->mmio_needed = 0; return EMULATE_DONE; @@ -674,7 +663,6 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u64 val, unsigned int bytes, int is_bigendian) { void *data = run->mmio.data; - int idx, ret; if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, @@ -704,14 +692,8 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, } } - idx = srcu_read_lock(&vcpu->kvm->srcu); - - ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, - bytes, &run->mmio.data); - - srcu_read_unlock(&vcpu->kvm->srcu, idx); - - if (!ret) { + if (!kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, + bytes, &run->mmio.data)) { vcpu->mmio_needed = 0; return EMULATE_DONE; } @@ -840,25 +822,6 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, break; } #endif -#ifdef CONFIG_KVM_XICS - case KVM_CAP_IRQ_XICS: { - struct file *filp; - struct kvm_device *dev; - - r = -EBADF; - filp = fget(cap->args[0]); - if (!filp) - break; - - r = -EPERM; - dev = kvm_device_from_filp(filp); - if (dev) - r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]); - - fput(filp); - break; - } -#endif /* CONFIG_KVM_XICS */ default: r = -EINVAL; break; diff --git a/trunk/arch/x86/include/asm/kvm_host.h b/trunk/arch/x86/include/asm/kvm_host.h index 3741c653767c..ec14b7245a4e 100644 --- a/trunk/arch/x86/include/asm/kvm_host.h +++ b/trunk/arch/x86/include/asm/kvm_host.h @@ -695,7 +695,7 @@ struct kvm_x86_ops { int (*nmi_allowed)(struct kvm_vcpu *vcpu); bool (*get_nmi_mask)(struct kvm_vcpu *vcpu); void (*set_nmi_mask)(struct kvm_vcpu *vcpu, bool masked); - int (*enable_nmi_window)(struct kvm_vcpu *vcpu); + void (*enable_nmi_window)(struct kvm_vcpu *vcpu); int (*enable_irq_window)(struct kvm_vcpu *vcpu); void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr); int (*vm_has_apicv)(struct kvm *kvm); diff --git a/trunk/arch/x86/kvm/svm.c b/trunk/arch/x86/kvm/svm.c index 3421d5a92c06..7f896cbe717f 100644 --- a/trunk/arch/x86/kvm/svm.c +++ b/trunk/arch/x86/kvm/svm.c @@ -3649,13 +3649,13 @@ static int enable_irq_window(struct kvm_vcpu *vcpu) return 0; } -static int enable_nmi_window(struct kvm_vcpu *vcpu) +static void enable_nmi_window(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); if ((svm->vcpu.arch.hflags & (HF_NMI_MASK | HF_IRET_MASK)) == HF_NMI_MASK) - return 0; /* IRET will cause a vm exit */ + return; /* IRET will cause a vm exit */ /* * Something prevents NMI from been injected. Single step over possible @@ -3664,7 +3664,6 @@ static int enable_nmi_window(struct kvm_vcpu *vcpu) svm->nmi_singlestep = true; svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF); update_db_bp_intercept(vcpu); - return 0; } static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index e53a5f7aa8a9..e10217e99d2c 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -4417,20 +4417,22 @@ static int enable_irq_window(struct kvm_vcpu *vcpu) return 0; } -static int enable_nmi_window(struct kvm_vcpu *vcpu) +static void enable_nmi_window(struct kvm_vcpu *vcpu) { u32 cpu_based_vm_exec_control; - if (!cpu_has_virtual_nmis()) - return enable_irq_window(vcpu); - - if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) - return enable_irq_window(vcpu); + if (!cpu_has_virtual_nmis()) { + enable_irq_window(vcpu); + return; + } + if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) { + enable_irq_window(vcpu); + return; + } cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING; vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); - return 0; } static void vmx_inject_irq(struct kvm_vcpu *vcpu) diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index 94f35d22c5fb..8747fef7fd59 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -2544,11 +2544,9 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_PV_MMU: /* obsolete */ r = 0; break; -#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT case KVM_CAP_IOMMU: r = iommu_present(&pci_bus_type); break; -#endif case KVM_CAP_MCE: r = KVM_MAX_MCE_BANKS; break; @@ -5756,8 +5754,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) /* enable NMI/IRQ window open exits if needed */ if (vcpu->arch.nmi_pending) - req_immediate_exit = - kvm_x86_ops->enable_nmi_window(vcpu) != 0; + kvm_x86_ops->enable_nmi_window(vcpu); else if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win) req_immediate_exit = kvm_x86_ops->enable_irq_window(vcpu) != 0; diff --git a/trunk/include/linux/kvm_host.h b/trunk/include/linux/kvm_host.h index 7823b6369c5e..996661eb8e99 100644 --- a/trunk/include/linux/kvm_host.h +++ b/trunk/include/linux/kvm_host.h @@ -1086,7 +1086,6 @@ void kvm_device_put(struct kvm_device *dev); struct kvm_device *kvm_device_from_filp(struct file *filp); extern struct kvm_device_ops kvm_mpic_ops; -extern struct kvm_device_ops kvm_xics_ops; #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT diff --git a/trunk/include/uapi/linux/kvm.h b/trunk/include/uapi/linux/kvm.h index a5c86fc34a37..965e5b52dee0 100644 --- a/trunk/include/uapi/linux/kvm.h +++ b/trunk/include/uapi/linux/kvm.h @@ -665,7 +665,6 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_DEVICE_CTRL 89 #define KVM_CAP_IRQ_MPIC 90 #define KVM_CAP_PPC_RTAS 91 -#define KVM_CAP_IRQ_XICS 92 #ifdef KVM_CAP_IRQ_ROUTING @@ -838,7 +837,6 @@ struct kvm_device_attr { #define KVM_DEV_TYPE_FSL_MPIC_20 1 #define KVM_DEV_TYPE_FSL_MPIC_42 2 -#define KVM_DEV_TYPE_XICS 3 /* * ioctls for VM fds diff --git a/trunk/virt/kvm/kvm_main.c b/trunk/virt/kvm/kvm_main.c index e6e7abe16d05..5da9f02a2a67 100644 --- a/trunk/virt/kvm/kvm_main.c +++ b/trunk/virt/kvm/kvm_main.c @@ -2246,11 +2246,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm, case KVM_DEV_TYPE_FSL_MPIC_42: ops = &kvm_mpic_ops; break; -#endif -#ifdef CONFIG_KVM_XICS - case KVM_DEV_TYPE_XICS: - ops = &kvm_xics_ops; - break; #endif default: return -ENODEV;