All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christian Borntraeger <borntraeger@de.ibm.com>
To: Cornelia Huck <cornelia.huck@de.ibm.com>,
	kvm@vger.kernel.org, linux-s390@vger.kernel.org,
	qemu-devel@nongnu.org
Cc: agraf@suse.de, pbonzini@redhat.com, gleb@kernel.org
Subject: Re: [PATCH v2 4/5] KVM: s390: irq routing for adapter interrupts.
Date: Fri, 21 Mar 2014 10:32:03 +0100	[thread overview]
Message-ID: <532C0713.7080208@de.ibm.com> (raw)
In-Reply-To: <1395079899-29239-5-git-send-email-cornelia.huck@de.ibm.com>

On 17/03/14 19:11, Cornelia Huck wrote:
> Introduce a new interrupt class for s390 adapter interrupts and enable
> irqfds for s390.
> 
> This is depending on a new s390 specific vm capability, KVM_CAP_S390_IRQCHIP,
> that needs to be enabled by userspace.
> 
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  Documentation/virtual/kvm/api.txt               |   21 +++-
>  Documentation/virtual/kvm/devices/s390_flic.txt |    6 +-
>  arch/s390/include/asm/kvm_host.h                |   10 ++
>  arch/s390/kvm/Kconfig                           |    2 +
>  arch/s390/kvm/Makefile                          |    2 +-
>  arch/s390/kvm/interrupt.c                       |  132 ++++++++++++++++++++++-
>  arch/s390/kvm/irq.h                             |   22 ++++
>  arch/s390/kvm/kvm-s390.c                        |   17 +++
>  include/linux/kvm_host.h                        |    9 ++
>  include/uapi/linux/kvm.h                        |   11 ++
>  10 files changed, 222 insertions(+), 10 deletions(-)
>  create mode 100644 arch/s390/kvm/irq.h
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index faf6fe9..2cb1640 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -586,8 +586,8 @@ struct kvm_fpu {
> 
>  4.24 KVM_CREATE_IRQCHIP
> 
> -Capability: KVM_CAP_IRQCHIP
> -Architectures: x86, ia64, ARM, arm64
> +Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
> +Architectures: x86, ia64, ARM, arm64, s390
>  Type: vm ioctl
>  Parameters: none
>  Returns: 0 on success, -1 on error
> @@ -596,7 +596,10 @@ Creates an interrupt controller model in the kernel.  On x86, creates a virtual
>  ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
>  local APIC.  IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
>  only go to the IOAPIC.  On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is
> -created.
> +created. On s390, a dummy irq routing table is created.
> +
> +Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
> +before KVM_CREATE_IRQCHIP can be used.
> 
> 
>  4.25 KVM_IRQ_LINE
> @@ -1336,7 +1339,7 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
>  4.52 KVM_SET_GSI_ROUTING
> 
>  Capability: KVM_CAP_IRQ_ROUTING
> -Architectures: x86 ia64
> +Architectures: x86 ia64 s390
>  Type: vm ioctl
>  Parameters: struct kvm_irq_routing (in)
>  Returns: 0 on success, -1 on error
> @@ -1359,6 +1362,7 @@ struct kvm_irq_routing_entry {
>  	union {
>  		struct kvm_irq_routing_irqchip irqchip;
>  		struct kvm_irq_routing_msi msi;
> +		struct kvm_irq_routing_s390_adapter adapter;
>  		__u32 pad[8];
>  	} u;
>  };
> @@ -1366,6 +1370,7 @@ struct kvm_irq_routing_entry {
>  /* gsi routing entry types */
>  #define KVM_IRQ_ROUTING_IRQCHIP 1
>  #define KVM_IRQ_ROUTING_MSI 2
> +#define KVM_IRQ_ROUTING_S390_ADAPTER 3
> 
>  No flags are specified so far, the corresponding field must be set to zero.
> 
> @@ -1381,6 +1386,14 @@ struct kvm_irq_routing_msi {
>  	__u32 pad;
>  };
> 
> +struct kvm_irq_routing_s390_adapter {
> +	__u64 ind_addr;
> +	__u64 summary_addr;
> +	__u64 ind_offset;
> +	__u32 summary_offset;
> +	__u32 adapter_id;
> +};
> +
> 
>  4.53 KVM_ASSIGN_SET_MSIX_NR
> 
> diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
> index db16111..4ceef53 100644
> --- a/Documentation/virtual/kvm/devices/s390_flic.txt
> +++ b/Documentation/virtual/kvm/devices/s390_flic.txt
> @@ -82,8 +82,10 @@ struct kvm_s390_io_adapter_req {
>        mask or unmask the adapter, as specified in mask
> 
>      KVM_S390_IO_ADAPTER_MAP
> -      pin a userspace page for the address provided in addr and add it to the
> +      perform a gmap translation for the guest address provided in addr,
> +      pin a userspace page for the translated address and add it to the
>        list of mappings
> 
>      KVM_S390_IO_ADAPTER_UNMAP
> -      release a userspace page as specified in addr from the list of mappings
> +      release a userspace page for the translated address specified in addr
> +      from the list of mappings
> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
> index 356f595..82bf697 100644
> --- a/arch/s390/include/asm/kvm_host.h
> +++ b/arch/s390/include/asm/kvm_host.h
> @@ -24,6 +24,14 @@
>  #define KVM_MAX_VCPUS 64
>  #define KVM_USER_MEM_SLOTS 32
> 
> +/*
> + * These seem to be used for allocating ->chip in the routing table,
> + * which we don't use. 4096 is an out-of-thin-air value. If we need
> + * to look at ->chip later on, we'll need to revisit this.
> + */
> +#define KVM_NR_IRQCHIPS 1
> +#define KVM_IRQCHIP_NUM_PINS 4096
> +
>  struct sca_entry {
>  	atomic_t scn;
>  	__u32	reserved;
> @@ -248,6 +256,7 @@ struct kvm_arch_memory_slot {
> 
>  struct s390_map_info {
>  	struct list_head list;
> +	__u64 guest_addr;
>  	__u64 addr;
>  	struct page *page;
>  };
> @@ -271,6 +280,7 @@ struct kvm_arch{
>  	struct kvm_device *flic;
>  	struct gmap *gmap;
>  	int css_support;
> +	int use_irqchip;
>  	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
>  };
> 
> diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
> index c8bacbc..10d529a 100644
> --- a/arch/s390/kvm/Kconfig
> +++ b/arch/s390/kvm/Kconfig
> @@ -25,6 +25,8 @@ config KVM
>  	select HAVE_KVM_EVENTFD
>  	select KVM_ASYNC_PF
>  	select KVM_ASYNC_PF_SYNC
> +	select HAVE_KVM_IRQCHIP
> +	select HAVE_KVM_IRQ_ROUTING
>  	---help---
>  	  Support hosting paravirtualized guest machines using the SIE
>  	  virtualization capability on the mainframe. This should work
> diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
> index a47d2c3..d3adb37 100644
> --- a/arch/s390/kvm/Makefile
> +++ b/arch/s390/kvm/Makefile
> @@ -7,7 +7,7 @@
>  # as published by the Free Software Foundation.
> 
>  KVM := ../../../virt/kvm
> -common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  $(KVM)/async_pf.o
> +common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  $(KVM)/async_pf.o $(KVM)/irqchip.o
> 
>  ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
> 
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 94b337e..8155bb4 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -13,6 +13,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/kvm_host.h>
>  #include <linux/hrtimer.h>
> +#include <linux/mmu_context.h>
>  #include <linux/signal.h>
>  #include <linux/slab.h>
>  #include <asm/asm-offsets.h>
> @@ -1118,8 +1119,13 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
>  		goto out;
>  	}
>  	INIT_LIST_HEAD(&map->list);
> -	map->addr = addr;
> -	ret = get_user_pages_fast(addr, 1, 1, &map->page);
> +	map->guest_addr = addr;
> +	map->addr = gmap_translate(addr, kvm->arch.gmap);
> +	if (map->addr == -EFAULT) {
> +		ret = -EFAULT;
> +		goto out;
> +	}
> +	ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
>  	if (ret < 0)
>  		goto out;
>  	BUG_ON(ret != 1);
> @@ -1144,7 +1150,7 @@ static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
> 
>  	down_write(&adapter->maps_lock);
>  	list_for_each_entry_safe(map, tmp, &adapter->maps, list) {
> -		if (map->addr == addr) {
> +		if (map->guest_addr == addr) {
>  			found = 1;
>  			list_del(&map->list);
>  			put_page(map->page);


Can't these two hunks be merged into the previous patch? 

Otherwise:
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>



> @@ -1272,3 +1278,123 @@ struct kvm_device_ops kvm_flic_ops = {
>  	.create = flic_create,
>  	.destroy = flic_destroy,
>  };
> +
> +static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
> +{
> +	unsigned long bit;
> +
> +	bit = bit_nr + (addr % PAGE_SIZE) * 8;
> +
> +	return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
> +}
> +
> +static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
> +					  u64 addr)
> +{
> +	struct s390_map_info *map;
> +
> +	if (!adapter)
> +		return NULL;
> +
> +	list_for_each_entry(map, &adapter->maps, list) {
> +		if (map->guest_addr == addr)
> +			return map;
> +	}
> +	return NULL;
> +}
> +
> +static int adapter_indicators_set(struct kvm *kvm,
> +				  struct s390_io_adapter *adapter,
> +				  struct kvm_s390_adapter_int *adapter_int)
> +{
> +	unsigned long bit;
> +	int summary_set, idx;
> +	struct s390_map_info *info;
> +	void *map;
> +
> +	info = get_map_info(adapter, adapter_int->ind_addr);
> +	if (!info)
> +		return -1;
> +	map = page_address(info->page);
> +	bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap);
> +	set_bit(bit, map);
> +	idx = srcu_read_lock(&kvm->srcu);
> +	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
> +	set_page_dirty_lock(info->page);
> +	info = get_map_info(adapter, adapter_int->summary_addr);
> +	if (!info) {
> +		srcu_read_unlock(&kvm->srcu, idx);
> +		return -1;
> +	}
> +	map = page_address(info->page);
> +	bit = get_ind_bit(info->addr, adapter_int->summary_offset,
> +			  adapter->swap);
> +	summary_set = test_and_set_bit(bit, map);
> +	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
> +	set_page_dirty_lock(info->page);
> +	srcu_read_unlock(&kvm->srcu, idx);
> +	return summary_set ? 0 : 1;
> +}
> +
> +/*
> + * < 0 - not injected due to error
> + * = 0 - coalesced, summary indicator already active
> + * > 0 - injected interrupt
> + */
> +static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
> +			   struct kvm *kvm, int irq_source_id, int level,
> +			   bool line_status)
> +{
> +	int ret;
> +	struct s390_io_adapter *adapter;
> +
> +	/* We're only interested in the 0->1 transition. */
> +	if (!level)
> +		return 0;
> +	adapter = get_io_adapter(kvm, e->adapter.adapter_id);
> +	if (!adapter)
> +		return -1;
> +	down_read(&adapter->maps_lock);
> +	ret = adapter_indicators_set(kvm, adapter, &e->adapter);
> +	up_read(&adapter->maps_lock);
> +	if ((ret > 0) && !adapter->masked) {
> +		struct kvm_s390_interrupt s390int = {
> +			.type = KVM_S390_INT_IO(1, 0, 0, 0),
> +			.parm = 0,
> +			.parm64 = (adapter->isc << 27) | 0x80000000,
> +		};
> +		ret = kvm_s390_inject_vm(kvm, &s390int);
> +		if (ret == 0)
> +			ret = 1;
> +	}
> +	return ret;
> +}
> +
> +int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
> +			  struct kvm_kernel_irq_routing_entry *e,
> +			  const struct kvm_irq_routing_entry *ue)
> +{
> +	int ret;
> +
> +	switch (ue->type) {
> +	case KVM_IRQ_ROUTING_S390_ADAPTER:
> +		e->set = set_adapter_int;
> +		e->adapter.summary_addr = ue->u.adapter.summary_addr;
> +		e->adapter.ind_addr = ue->u.adapter.ind_addr;
> +		e->adapter.summary_offset = ue->u.adapter.summary_offset;
> +		e->adapter.ind_offset = ue->u.adapter.ind_offset;
> +		e->adapter.adapter_id = ue->u.adapter.adapter_id;
> +		ret = 0;
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
> +		int irq_source_id, int level, bool line_status)
> +{
> +	return -EINVAL;
> +}
> diff --git a/arch/s390/kvm/irq.h b/arch/s390/kvm/irq.h
> new file mode 100644
> index 0000000..d98e415
> --- /dev/null
> +++ b/arch/s390/kvm/irq.h
> @@ -0,0 +1,22 @@
> +/*
> + * s390 irqchip routines
> + *
> + * Copyright IBM Corp. 2014
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License (version 2 only)
> + * as published by the Free Software Foundation.
> + *
> + *    Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
> + */
> +#ifndef __KVM_IRQ_H
> +#define __KVM_IRQ_H
> +
> +#include <linux/kvm_host.h>
> +
> +static inline int irqchip_in_kernel(struct kvm *kvm)
> +{
> +	return 1;
> +}
> +
> +#endif
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 2e6fbb0..ce5b659 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -196,6 +196,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
>  		return -EINVAL;
> 
>  	switch (cap->cap) {
> +	case KVM_CAP_S390_IRQCHIP:
> +		kvm->arch.use_irqchip = 1;
> +		r = 0;
> +		break;
>  	default:
>  		r = -EINVAL;
>  		break;
> @@ -228,6 +232,18 @@ long kvm_arch_vm_ioctl(struct file *filp,
>  		r = kvm_vm_ioctl_enable_cap(kvm, &cap);
>  		break;
>  	}
> +	case KVM_CREATE_IRQCHIP: {
> +		struct kvm_irq_routing_entry routing;
> +
> +		r = -EINVAL;
> +		if (kvm->arch.use_irqchip) {
> +			/* Set up dummy routing. */
> +			memset(&routing, 0, sizeof(routing));
> +			kvm_set_irq_routing(kvm, &routing, 0, 0);
> +			r = 0;
> +		}
> +		break;
> +	}
>  	default:
>  		r = -ENOTTY;
>  	}
> @@ -284,6 +300,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>  	}
> 
>  	kvm->arch.css_support = 0;
> +	kvm->arch.use_irqchip = 0;
> 
>  	return 0;
>  out_nogmap:
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 9816b68..da7510b 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -297,6 +297,14 @@ static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memsl
>  	return ALIGN(memslot->npages, BITS_PER_LONG) / 8;
>  }
> 
> +struct kvm_s390_adapter_int {
> +	u64 ind_addr;
> +	u64 summary_addr;
> +	u64 ind_offset;
> +	u32 summary_offset;
> +	u32 adapter_id;
> +};
> +
>  struct kvm_kernel_irq_routing_entry {
>  	u32 gsi;
>  	u32 type;
> @@ -309,6 +317,7 @@ struct kvm_kernel_irq_routing_entry {
>  			unsigned pin;
>  		} irqchip;
>  		struct msi_msg msi;
> +		struct kvm_s390_adapter_int adapter;
>  	};
>  	struct hlist_node link;
>  };
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 46ea1b4..a8f4ee5 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -742,6 +742,7 @@ struct kvm_ppc_smmu_info {
>  #define KVM_CAP_HYPERV_TIME 96
>  #define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
>  #define KVM_CAP_ENABLE_CAP_VM 98
> +#define KVM_CAP_S390_IRQCHIP 99
> 
>  #ifdef KVM_CAP_IRQ_ROUTING
> 
> @@ -757,9 +758,18 @@ struct kvm_irq_routing_msi {
>  	__u32 pad;
>  };
> 
> +struct kvm_irq_routing_s390_adapter {
> +	__u64 ind_addr;
> +	__u64 summary_addr;
> +	__u64 ind_offset;
> +	__u32 summary_offset;
> +	__u32 adapter_id;
> +};
> +
>  /* gsi routing entry types */
>  #define KVM_IRQ_ROUTING_IRQCHIP 1
>  #define KVM_IRQ_ROUTING_MSI 2
> +#define KVM_IRQ_ROUTING_S390_ADAPTER 3
> 
>  struct kvm_irq_routing_entry {
>  	__u32 gsi;
> @@ -769,6 +779,7 @@ struct kvm_irq_routing_entry {
>  	union {
>  		struct kvm_irq_routing_irqchip irqchip;
>  		struct kvm_irq_routing_msi msi;
> +		struct kvm_irq_routing_s390_adapter adapter;
>  		__u32 pad[8];
>  	} u;
>  };
> 

WARNING: multiple messages have this Message-ID (diff)
From: Christian Borntraeger <borntraeger@de.ibm.com>
To: Cornelia Huck <cornelia.huck@de.ibm.com>,
	kvm@vger.kernel.org, linux-s390@vger.kernel.org,
	qemu-devel@nongnu.org
Cc: gleb@kernel.org, pbonzini@redhat.com, agraf@suse.de
Subject: Re: [Qemu-devel] [PATCH v2 4/5] KVM: s390: irq routing for adapter interrupts.
Date: Fri, 21 Mar 2014 10:32:03 +0100	[thread overview]
Message-ID: <532C0713.7080208@de.ibm.com> (raw)
In-Reply-To: <1395079899-29239-5-git-send-email-cornelia.huck@de.ibm.com>

On 17/03/14 19:11, Cornelia Huck wrote:
> Introduce a new interrupt class for s390 adapter interrupts and enable
> irqfds for s390.
> 
> This is depending on a new s390 specific vm capability, KVM_CAP_S390_IRQCHIP,
> that needs to be enabled by userspace.
> 
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  Documentation/virtual/kvm/api.txt               |   21 +++-
>  Documentation/virtual/kvm/devices/s390_flic.txt |    6 +-
>  arch/s390/include/asm/kvm_host.h                |   10 ++
>  arch/s390/kvm/Kconfig                           |    2 +
>  arch/s390/kvm/Makefile                          |    2 +-
>  arch/s390/kvm/interrupt.c                       |  132 ++++++++++++++++++++++-
>  arch/s390/kvm/irq.h                             |   22 ++++
>  arch/s390/kvm/kvm-s390.c                        |   17 +++
>  include/linux/kvm_host.h                        |    9 ++
>  include/uapi/linux/kvm.h                        |   11 ++
>  10 files changed, 222 insertions(+), 10 deletions(-)
>  create mode 100644 arch/s390/kvm/irq.h
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index faf6fe9..2cb1640 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -586,8 +586,8 @@ struct kvm_fpu {
> 
>  4.24 KVM_CREATE_IRQCHIP
> 
> -Capability: KVM_CAP_IRQCHIP
> -Architectures: x86, ia64, ARM, arm64
> +Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
> +Architectures: x86, ia64, ARM, arm64, s390
>  Type: vm ioctl
>  Parameters: none
>  Returns: 0 on success, -1 on error
> @@ -596,7 +596,10 @@ Creates an interrupt controller model in the kernel.  On x86, creates a virtual
>  ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
>  local APIC.  IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
>  only go to the IOAPIC.  On ia64, a IOSAPIC is created. On ARM/arm64, a GIC is
> -created.
> +created. On s390, a dummy irq routing table is created.
> +
> +Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
> +before KVM_CREATE_IRQCHIP can be used.
> 
> 
>  4.25 KVM_IRQ_LINE
> @@ -1336,7 +1339,7 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
>  4.52 KVM_SET_GSI_ROUTING
> 
>  Capability: KVM_CAP_IRQ_ROUTING
> -Architectures: x86 ia64
> +Architectures: x86 ia64 s390
>  Type: vm ioctl
>  Parameters: struct kvm_irq_routing (in)
>  Returns: 0 on success, -1 on error
> @@ -1359,6 +1362,7 @@ struct kvm_irq_routing_entry {
>  	union {
>  		struct kvm_irq_routing_irqchip irqchip;
>  		struct kvm_irq_routing_msi msi;
> +		struct kvm_irq_routing_s390_adapter adapter;
>  		__u32 pad[8];
>  	} u;
>  };
> @@ -1366,6 +1370,7 @@ struct kvm_irq_routing_entry {
>  /* gsi routing entry types */
>  #define KVM_IRQ_ROUTING_IRQCHIP 1
>  #define KVM_IRQ_ROUTING_MSI 2
> +#define KVM_IRQ_ROUTING_S390_ADAPTER 3
> 
>  No flags are specified so far, the corresponding field must be set to zero.
> 
> @@ -1381,6 +1386,14 @@ struct kvm_irq_routing_msi {
>  	__u32 pad;
>  };
> 
> +struct kvm_irq_routing_s390_adapter {
> +	__u64 ind_addr;
> +	__u64 summary_addr;
> +	__u64 ind_offset;
> +	__u32 summary_offset;
> +	__u32 adapter_id;
> +};
> +
> 
>  4.53 KVM_ASSIGN_SET_MSIX_NR
> 
> diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
> index db16111..4ceef53 100644
> --- a/Documentation/virtual/kvm/devices/s390_flic.txt
> +++ b/Documentation/virtual/kvm/devices/s390_flic.txt
> @@ -82,8 +82,10 @@ struct kvm_s390_io_adapter_req {
>        mask or unmask the adapter, as specified in mask
> 
>      KVM_S390_IO_ADAPTER_MAP
> -      pin a userspace page for the address provided in addr and add it to the
> +      perform a gmap translation for the guest address provided in addr,
> +      pin a userspace page for the translated address and add it to the
>        list of mappings
> 
>      KVM_S390_IO_ADAPTER_UNMAP
> -      release a userspace page as specified in addr from the list of mappings
> +      release a userspace page for the translated address specified in addr
> +      from the list of mappings
> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
> index 356f595..82bf697 100644
> --- a/arch/s390/include/asm/kvm_host.h
> +++ b/arch/s390/include/asm/kvm_host.h
> @@ -24,6 +24,14 @@
>  #define KVM_MAX_VCPUS 64
>  #define KVM_USER_MEM_SLOTS 32
> 
> +/*
> + * These seem to be used for allocating ->chip in the routing table,
> + * which we don't use. 4096 is an out-of-thin-air value. If we need
> + * to look at ->chip later on, we'll need to revisit this.
> + */
> +#define KVM_NR_IRQCHIPS 1
> +#define KVM_IRQCHIP_NUM_PINS 4096
> +
>  struct sca_entry {
>  	atomic_t scn;
>  	__u32	reserved;
> @@ -248,6 +256,7 @@ struct kvm_arch_memory_slot {
> 
>  struct s390_map_info {
>  	struct list_head list;
> +	__u64 guest_addr;
>  	__u64 addr;
>  	struct page *page;
>  };
> @@ -271,6 +280,7 @@ struct kvm_arch{
>  	struct kvm_device *flic;
>  	struct gmap *gmap;
>  	int css_support;
> +	int use_irqchip;
>  	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
>  };
> 
> diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
> index c8bacbc..10d529a 100644
> --- a/arch/s390/kvm/Kconfig
> +++ b/arch/s390/kvm/Kconfig
> @@ -25,6 +25,8 @@ config KVM
>  	select HAVE_KVM_EVENTFD
>  	select KVM_ASYNC_PF
>  	select KVM_ASYNC_PF_SYNC
> +	select HAVE_KVM_IRQCHIP
> +	select HAVE_KVM_IRQ_ROUTING
>  	---help---
>  	  Support hosting paravirtualized guest machines using the SIE
>  	  virtualization capability on the mainframe. This should work
> diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
> index a47d2c3..d3adb37 100644
> --- a/arch/s390/kvm/Makefile
> +++ b/arch/s390/kvm/Makefile
> @@ -7,7 +7,7 @@
>  # as published by the Free Software Foundation.
> 
>  KVM := ../../../virt/kvm
> -common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  $(KVM)/async_pf.o
> +common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o  $(KVM)/async_pf.o $(KVM)/irqchip.o
> 
>  ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
> 
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 94b337e..8155bb4 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -13,6 +13,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/kvm_host.h>
>  #include <linux/hrtimer.h>
> +#include <linux/mmu_context.h>
>  #include <linux/signal.h>
>  #include <linux/slab.h>
>  #include <asm/asm-offsets.h>
> @@ -1118,8 +1119,13 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
>  		goto out;
>  	}
>  	INIT_LIST_HEAD(&map->list);
> -	map->addr = addr;
> -	ret = get_user_pages_fast(addr, 1, 1, &map->page);
> +	map->guest_addr = addr;
> +	map->addr = gmap_translate(addr, kvm->arch.gmap);
> +	if (map->addr == -EFAULT) {
> +		ret = -EFAULT;
> +		goto out;
> +	}
> +	ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
>  	if (ret < 0)
>  		goto out;
>  	BUG_ON(ret != 1);
> @@ -1144,7 +1150,7 @@ static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
> 
>  	down_write(&adapter->maps_lock);
>  	list_for_each_entry_safe(map, tmp, &adapter->maps, list) {
> -		if (map->addr == addr) {
> +		if (map->guest_addr == addr) {
>  			found = 1;
>  			list_del(&map->list);
>  			put_page(map->page);


Can't these two hunks be merged into the previous patch? 

Otherwise:
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>



> @@ -1272,3 +1278,123 @@ struct kvm_device_ops kvm_flic_ops = {
>  	.create = flic_create,
>  	.destroy = flic_destroy,
>  };
> +
> +static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
> +{
> +	unsigned long bit;
> +
> +	bit = bit_nr + (addr % PAGE_SIZE) * 8;
> +
> +	return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
> +}
> +
> +static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
> +					  u64 addr)
> +{
> +	struct s390_map_info *map;
> +
> +	if (!adapter)
> +		return NULL;
> +
> +	list_for_each_entry(map, &adapter->maps, list) {
> +		if (map->guest_addr == addr)
> +			return map;
> +	}
> +	return NULL;
> +}
> +
> +static int adapter_indicators_set(struct kvm *kvm,
> +				  struct s390_io_adapter *adapter,
> +				  struct kvm_s390_adapter_int *adapter_int)
> +{
> +	unsigned long bit;
> +	int summary_set, idx;
> +	struct s390_map_info *info;
> +	void *map;
> +
> +	info = get_map_info(adapter, adapter_int->ind_addr);
> +	if (!info)
> +		return -1;
> +	map = page_address(info->page);
> +	bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap);
> +	set_bit(bit, map);
> +	idx = srcu_read_lock(&kvm->srcu);
> +	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
> +	set_page_dirty_lock(info->page);
> +	info = get_map_info(adapter, adapter_int->summary_addr);
> +	if (!info) {
> +		srcu_read_unlock(&kvm->srcu, idx);
> +		return -1;
> +	}
> +	map = page_address(info->page);
> +	bit = get_ind_bit(info->addr, adapter_int->summary_offset,
> +			  adapter->swap);
> +	summary_set = test_and_set_bit(bit, map);
> +	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
> +	set_page_dirty_lock(info->page);
> +	srcu_read_unlock(&kvm->srcu, idx);
> +	return summary_set ? 0 : 1;
> +}
> +
> +/*
> + * < 0 - not injected due to error
> + * = 0 - coalesced, summary indicator already active
> + * > 0 - injected interrupt
> + */
> +static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
> +			   struct kvm *kvm, int irq_source_id, int level,
> +			   bool line_status)
> +{
> +	int ret;
> +	struct s390_io_adapter *adapter;
> +
> +	/* We're only interested in the 0->1 transition. */
> +	if (!level)
> +		return 0;
> +	adapter = get_io_adapter(kvm, e->adapter.adapter_id);
> +	if (!adapter)
> +		return -1;
> +	down_read(&adapter->maps_lock);
> +	ret = adapter_indicators_set(kvm, adapter, &e->adapter);
> +	up_read(&adapter->maps_lock);
> +	if ((ret > 0) && !adapter->masked) {
> +		struct kvm_s390_interrupt s390int = {
> +			.type = KVM_S390_INT_IO(1, 0, 0, 0),
> +			.parm = 0,
> +			.parm64 = (adapter->isc << 27) | 0x80000000,
> +		};
> +		ret = kvm_s390_inject_vm(kvm, &s390int);
> +		if (ret == 0)
> +			ret = 1;
> +	}
> +	return ret;
> +}
> +
> +int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
> +			  struct kvm_kernel_irq_routing_entry *e,
> +			  const struct kvm_irq_routing_entry *ue)
> +{
> +	int ret;
> +
> +	switch (ue->type) {
> +	case KVM_IRQ_ROUTING_S390_ADAPTER:
> +		e->set = set_adapter_int;
> +		e->adapter.summary_addr = ue->u.adapter.summary_addr;
> +		e->adapter.ind_addr = ue->u.adapter.ind_addr;
> +		e->adapter.summary_offset = ue->u.adapter.summary_offset;
> +		e->adapter.ind_offset = ue->u.adapter.ind_offset;
> +		e->adapter.adapter_id = ue->u.adapter.adapter_id;
> +		ret = 0;
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
> +		int irq_source_id, int level, bool line_status)
> +{
> +	return -EINVAL;
> +}
> diff --git a/arch/s390/kvm/irq.h b/arch/s390/kvm/irq.h
> new file mode 100644
> index 0000000..d98e415
> --- /dev/null
> +++ b/arch/s390/kvm/irq.h
> @@ -0,0 +1,22 @@
> +/*
> + * s390 irqchip routines
> + *
> + * Copyright IBM Corp. 2014
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License (version 2 only)
> + * as published by the Free Software Foundation.
> + *
> + *    Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
> + */
> +#ifndef __KVM_IRQ_H
> +#define __KVM_IRQ_H
> +
> +#include <linux/kvm_host.h>
> +
> +static inline int irqchip_in_kernel(struct kvm *kvm)
> +{
> +	return 1;
> +}
> +
> +#endif
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 2e6fbb0..ce5b659 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -196,6 +196,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
>  		return -EINVAL;
> 
>  	switch (cap->cap) {
> +	case KVM_CAP_S390_IRQCHIP:
> +		kvm->arch.use_irqchip = 1;
> +		r = 0;
> +		break;
>  	default:
>  		r = -EINVAL;
>  		break;
> @@ -228,6 +232,18 @@ long kvm_arch_vm_ioctl(struct file *filp,
>  		r = kvm_vm_ioctl_enable_cap(kvm, &cap);
>  		break;
>  	}
> +	case KVM_CREATE_IRQCHIP: {
> +		struct kvm_irq_routing_entry routing;
> +
> +		r = -EINVAL;
> +		if (kvm->arch.use_irqchip) {
> +			/* Set up dummy routing. */
> +			memset(&routing, 0, sizeof(routing));
> +			kvm_set_irq_routing(kvm, &routing, 0, 0);
> +			r = 0;
> +		}
> +		break;
> +	}
>  	default:
>  		r = -ENOTTY;
>  	}
> @@ -284,6 +300,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>  	}
> 
>  	kvm->arch.css_support = 0;
> +	kvm->arch.use_irqchip = 0;
> 
>  	return 0;
>  out_nogmap:
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 9816b68..da7510b 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -297,6 +297,14 @@ static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memsl
>  	return ALIGN(memslot->npages, BITS_PER_LONG) / 8;
>  }
> 
> +struct kvm_s390_adapter_int {
> +	u64 ind_addr;
> +	u64 summary_addr;
> +	u64 ind_offset;
> +	u32 summary_offset;
> +	u32 adapter_id;
> +};
> +
>  struct kvm_kernel_irq_routing_entry {
>  	u32 gsi;
>  	u32 type;
> @@ -309,6 +317,7 @@ struct kvm_kernel_irq_routing_entry {
>  			unsigned pin;
>  		} irqchip;
>  		struct msi_msg msi;
> +		struct kvm_s390_adapter_int adapter;
>  	};
>  	struct hlist_node link;
>  };
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 46ea1b4..a8f4ee5 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -742,6 +742,7 @@ struct kvm_ppc_smmu_info {
>  #define KVM_CAP_HYPERV_TIME 96
>  #define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
>  #define KVM_CAP_ENABLE_CAP_VM 98
> +#define KVM_CAP_S390_IRQCHIP 99
> 
>  #ifdef KVM_CAP_IRQ_ROUTING
> 
> @@ -757,9 +758,18 @@ struct kvm_irq_routing_msi {
>  	__u32 pad;
>  };
> 
> +struct kvm_irq_routing_s390_adapter {
> +	__u64 ind_addr;
> +	__u64 summary_addr;
> +	__u64 ind_offset;
> +	__u32 summary_offset;
> +	__u32 adapter_id;
> +};
> +
>  /* gsi routing entry types */
>  #define KVM_IRQ_ROUTING_IRQCHIP 1
>  #define KVM_IRQ_ROUTING_MSI 2
> +#define KVM_IRQ_ROUTING_S390_ADAPTER 3
> 
>  struct kvm_irq_routing_entry {
>  	__u32 gsi;
> @@ -769,6 +779,7 @@ struct kvm_irq_routing_entry {
>  	union {
>  		struct kvm_irq_routing_irqchip irqchip;
>  		struct kvm_irq_routing_msi msi;
> +		struct kvm_irq_routing_s390_adapter adapter;
>  		__u32 pad[8];
>  	} u;
>  };
> 

  reply	other threads:[~2014-03-21  9:32 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-17 18:11 [PATCH v2 0/5] KVM: irqfds for s390 Cornelia Huck
2014-03-17 18:11 ` [Qemu-devel] " Cornelia Huck
2014-03-17 18:11 ` [PATCH v2 1/5] KVM: eventfd: Fix lock order inversion Cornelia Huck
2014-03-17 18:11   ` [Qemu-devel] " Cornelia Huck
2014-03-17 21:55   ` Christian Borntraeger
2014-03-17 21:55     ` [Qemu-devel] " Christian Borntraeger
2014-03-18  9:18     ` Cornelia Huck
2014-03-18  9:18       ` [Qemu-devel] " Cornelia Huck
2014-03-18 16:05     ` Paolo Bonzini
2014-03-18 16:05       ` [Qemu-devel] " Paolo Bonzini
2014-03-17 18:11 ` [PATCH v2 2/5] KVM: Add per-vm capability enablement Cornelia Huck
2014-03-17 18:11   ` [Qemu-devel] " Cornelia Huck
2014-03-17 22:09   ` Christian Borntraeger
2014-03-17 22:09     ` [Qemu-devel] " Christian Borntraeger
2014-03-21  9:12   ` Christian Borntraeger
2014-03-21  9:12     ` [Qemu-devel] " Christian Borntraeger
2014-03-17 18:11 ` [PATCH v2 3/5] KVM: s390: adapter interrupt sources Cornelia Huck
2014-03-17 18:11   ` [Qemu-devel] " Cornelia Huck
2014-03-18  8:11   ` Heiko Carstens
2014-03-18  8:11     ` [Qemu-devel] " Heiko Carstens
2014-03-18  8:41     ` Cornelia Huck
2014-03-18  8:41       ` [Qemu-devel] " Cornelia Huck
2014-03-21  9:26   ` Christian Borntraeger
2014-03-21  9:26     ` [Qemu-devel] " Christian Borntraeger
2014-03-21 10:07     ` Cornelia Huck
2014-03-21 10:07       ` [Qemu-devel] " Cornelia Huck
2014-03-17 18:11 ` [PATCH v2 4/5] KVM: s390: irq routing for adapter interrupts Cornelia Huck
2014-03-17 18:11   ` [Qemu-devel] " Cornelia Huck
2014-03-21  9:32   ` Christian Borntraeger [this message]
2014-03-21  9:32     ` Christian Borntraeger
2014-03-21 10:08     ` Cornelia Huck
2014-03-21 10:08       ` [Qemu-devel] " Cornelia Huck
2014-03-17 18:11 ` [PATCH v2 5/5] KVM: Bump KVM_MAX_IRQ_ROUTES for s390 Cornelia Huck
2014-03-17 18:11   ` [Qemu-devel] " Cornelia Huck
2014-03-18 16:07   ` Paolo Bonzini
2014-03-18 16:07     ` [Qemu-devel] " Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=532C0713.7080208@de.ibm.com \
    --to=borntraeger@de.ibm.com \
    --cc=agraf@suse.de \
    --cc=cornelia.huck@de.ibm.com \
    --cc=gleb@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.