brintos

brintos / linux-shallow public Read only

0
0
Text · 20.2 KiB · 8382c58 Raw
864 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * VFIO PCI interrupt handling4 *5 * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.6 *     Author: Alex Williamson <alex.williamson@redhat.com>7 *8 * Derived from original vfio:9 * Copyright 2010 Cisco Systems, Inc.  All rights reserved.10 * Author: Tom Lyon, pugs@cisco.com11 */12 13#include <linux/device.h>14#include <linux/interrupt.h>15#include <linux/eventfd.h>16#include <linux/msi.h>17#include <linux/pci.h>18#include <linux/file.h>19#include <linux/vfio.h>20#include <linux/wait.h>21#include <linux/slab.h>22 23#include "vfio_pci_priv.h"24 25struct vfio_pci_irq_ctx {26	struct vfio_pci_core_device	*vdev;27	struct eventfd_ctx		*trigger;28	struct virqfd			*unmask;29	struct virqfd			*mask;30	char				*name;31	bool				masked;32	struct irq_bypass_producer	producer;33};34 35static bool irq_is(struct vfio_pci_core_device *vdev, int type)36{37	return vdev->irq_type == type;38}39 40static bool is_intx(struct vfio_pci_core_device *vdev)41{42	return vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX;43}44 45static bool is_irq_none(struct vfio_pci_core_device *vdev)46{47	return !(vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX ||48		 vdev->irq_type == VFIO_PCI_MSI_IRQ_INDEX ||49		 vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX);50}51 52static53struct vfio_pci_irq_ctx *vfio_irq_ctx_get(struct vfio_pci_core_device *vdev,54					  unsigned long index)55{56	return xa_load(&vdev->ctx, index);57}58 59static void vfio_irq_ctx_free(struct vfio_pci_core_device *vdev,60			      struct vfio_pci_irq_ctx *ctx, unsigned long index)61{62	xa_erase(&vdev->ctx, index);63	kfree(ctx);64}65 66static struct vfio_pci_irq_ctx *67vfio_irq_ctx_alloc(struct vfio_pci_core_device *vdev, unsigned long index)68{69	struct vfio_pci_irq_ctx *ctx;70	int ret;71 72	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);73	if (!ctx)74		return NULL;75 76	ret = xa_insert(&vdev->ctx, index, ctx, GFP_KERNEL_ACCOUNT);77	if (ret) {78		kfree(ctx);79		return NULL;80	}81 82	return ctx;83}84 85/*86 * INTx87 */88static void vfio_send_intx_eventfd(void *opaque, void *data)89{90	struct vfio_pci_core_device *vdev = opaque;91 92	if (likely(is_intx(vdev) && !vdev->virq_disabled)) {93		struct vfio_pci_irq_ctx *ctx = data;94		struct eventfd_ctx *trigger = READ_ONCE(ctx->trigger);95 96		if (likely(trigger))97			eventfd_signal(trigger);98	}99}100 101/* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */102static bool __vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)103{104	struct pci_dev *pdev = vdev->pdev;105	struct vfio_pci_irq_ctx *ctx;106	unsigned long flags;107	bool masked_changed = false;108 109	lockdep_assert_held(&vdev->igate);110 111	spin_lock_irqsave(&vdev->irqlock, flags);112 113	/*114	 * Masking can come from interrupt, ioctl, or config space115	 * via INTx disable.  The latter means this can get called116	 * even when not using intx delivery.  In this case, just117	 * try to have the physical bit follow the virtual bit.118	 */119	if (unlikely(!is_intx(vdev))) {120		if (vdev->pci_2_3)121			pci_intx(pdev, 0);122		goto out_unlock;123	}124 125	ctx = vfio_irq_ctx_get(vdev, 0);126	if (WARN_ON_ONCE(!ctx))127		goto out_unlock;128 129	if (!ctx->masked) {130		/*131		 * Can't use check_and_mask here because we always want to132		 * mask, not just when something is pending.133		 */134		if (vdev->pci_2_3)135			pci_intx(pdev, 0);136		else137			disable_irq_nosync(pdev->irq);138 139		ctx->masked = true;140		masked_changed = true;141	}142 143out_unlock:144	spin_unlock_irqrestore(&vdev->irqlock, flags);145	return masked_changed;146}147 148bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)149{150	bool mask_changed;151 152	mutex_lock(&vdev->igate);153	mask_changed = __vfio_pci_intx_mask(vdev);154	mutex_unlock(&vdev->igate);155 156	return mask_changed;157}158 159/*160 * If this is triggered by an eventfd, we can't call eventfd_signal161 * or else we'll deadlock on the eventfd wait queue.  Return >0 when162 * a signal is necessary, which can then be handled via a work queue163 * or directly depending on the caller.164 */165static int vfio_pci_intx_unmask_handler(void *opaque, void *data)166{167	struct vfio_pci_core_device *vdev = opaque;168	struct pci_dev *pdev = vdev->pdev;169	struct vfio_pci_irq_ctx *ctx = data;170	unsigned long flags;171	int ret = 0;172 173	spin_lock_irqsave(&vdev->irqlock, flags);174 175	/*176	 * Unmasking comes from ioctl or config, so again, have the177	 * physical bit follow the virtual even when not using INTx.178	 */179	if (unlikely(!is_intx(vdev))) {180		if (vdev->pci_2_3)181			pci_intx(pdev, 1);182		goto out_unlock;183	}184 185	if (ctx->masked && !vdev->virq_disabled) {186		/*187		 * A pending interrupt here would immediately trigger,188		 * but we can avoid that overhead by just re-sending189		 * the interrupt to the user.190		 */191		if (vdev->pci_2_3) {192			if (!pci_check_and_unmask_intx(pdev))193				ret = 1;194		} else195			enable_irq(pdev->irq);196 197		ctx->masked = (ret > 0);198	}199 200out_unlock:201	spin_unlock_irqrestore(&vdev->irqlock, flags);202 203	return ret;204}205 206static void __vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)207{208	struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0);209 210	lockdep_assert_held(&vdev->igate);211 212	if (vfio_pci_intx_unmask_handler(vdev, ctx) > 0)213		vfio_send_intx_eventfd(vdev, ctx);214}215 216void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)217{218	mutex_lock(&vdev->igate);219	__vfio_pci_intx_unmask(vdev);220	mutex_unlock(&vdev->igate);221}222 223static irqreturn_t vfio_intx_handler(int irq, void *dev_id)224{225	struct vfio_pci_irq_ctx *ctx = dev_id;226	struct vfio_pci_core_device *vdev = ctx->vdev;227	unsigned long flags;228	int ret = IRQ_NONE;229 230	spin_lock_irqsave(&vdev->irqlock, flags);231 232	if (!vdev->pci_2_3) {233		disable_irq_nosync(vdev->pdev->irq);234		ctx->masked = true;235		ret = IRQ_HANDLED;236	} else if (!ctx->masked &&  /* may be shared */237		   pci_check_and_mask_intx(vdev->pdev)) {238		ctx->masked = true;239		ret = IRQ_HANDLED;240	}241 242	spin_unlock_irqrestore(&vdev->irqlock, flags);243 244	if (ret == IRQ_HANDLED)245		vfio_send_intx_eventfd(vdev, ctx);246 247	return ret;248}249 250static int vfio_intx_enable(struct vfio_pci_core_device *vdev,251			    struct eventfd_ctx *trigger)252{253	struct pci_dev *pdev = vdev->pdev;254	struct vfio_pci_irq_ctx *ctx;255	unsigned long irqflags;256	char *name;257	int ret;258 259	if (!is_irq_none(vdev))260		return -EINVAL;261 262	if (!pdev->irq)263		return -ENODEV;264 265	name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev));266	if (!name)267		return -ENOMEM;268 269	ctx = vfio_irq_ctx_alloc(vdev, 0);270	if (!ctx) {271		kfree(name);272		return -ENOMEM;273	}274 275	ctx->name = name;276	ctx->trigger = trigger;277	ctx->vdev = vdev;278 279	/*280	 * Fill the initial masked state based on virq_disabled.  After281	 * enable, changing the DisINTx bit in vconfig directly changes INTx282	 * masking.  igate prevents races during setup, once running masked283	 * is protected via irqlock.284	 *285	 * Devices supporting DisINTx also reflect the current mask state in286	 * the physical DisINTx bit, which is not affected during IRQ setup.287	 *288	 * Devices without DisINTx support require an exclusive interrupt.289	 * IRQ masking is performed at the IRQ chip.  Again, igate protects290	 * against races during setup and IRQ handlers and irqfds are not291	 * yet active, therefore masked is stable and can be used to292	 * conditionally auto-enable the IRQ.293	 *294	 * irq_type must be stable while the IRQ handler is registered,295	 * therefore it must be set before request_irq().296	 */297	ctx->masked = vdev->virq_disabled;298	if (vdev->pci_2_3) {299		pci_intx(pdev, !ctx->masked);300		irqflags = IRQF_SHARED;301	} else {302		irqflags = ctx->masked ? IRQF_NO_AUTOEN : 0;303	}304 305	vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX;306 307	ret = request_irq(pdev->irq, vfio_intx_handler,308			  irqflags, ctx->name, ctx);309	if (ret) {310		vdev->irq_type = VFIO_PCI_NUM_IRQS;311		kfree(name);312		vfio_irq_ctx_free(vdev, ctx, 0);313		return ret;314	}315 316	return 0;317}318 319static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,320				struct eventfd_ctx *trigger)321{322	struct pci_dev *pdev = vdev->pdev;323	struct vfio_pci_irq_ctx *ctx;324	struct eventfd_ctx *old;325 326	ctx = vfio_irq_ctx_get(vdev, 0);327	if (WARN_ON_ONCE(!ctx))328		return -EINVAL;329 330	old = ctx->trigger;331 332	WRITE_ONCE(ctx->trigger, trigger);333 334	/* Releasing an old ctx requires synchronizing in-flight users */335	if (old) {336		synchronize_irq(pdev->irq);337		vfio_virqfd_flush_thread(&ctx->unmask);338		eventfd_ctx_put(old);339	}340 341	return 0;342}343 344static void vfio_intx_disable(struct vfio_pci_core_device *vdev)345{346	struct pci_dev *pdev = vdev->pdev;347	struct vfio_pci_irq_ctx *ctx;348 349	ctx = vfio_irq_ctx_get(vdev, 0);350	WARN_ON_ONCE(!ctx);351	if (ctx) {352		vfio_virqfd_disable(&ctx->unmask);353		vfio_virqfd_disable(&ctx->mask);354		free_irq(pdev->irq, ctx);355		if (ctx->trigger)356			eventfd_ctx_put(ctx->trigger);357		kfree(ctx->name);358		vfio_irq_ctx_free(vdev, ctx, 0);359	}360	vdev->irq_type = VFIO_PCI_NUM_IRQS;361}362 363/*364 * MSI/MSI-X365 */366static irqreturn_t vfio_msihandler(int irq, void *arg)367{368	struct eventfd_ctx *trigger = arg;369 370	eventfd_signal(trigger);371	return IRQ_HANDLED;372}373 374static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msix)375{376	struct pci_dev *pdev = vdev->pdev;377	unsigned int flag = msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;378	int ret;379	u16 cmd;380 381	if (!is_irq_none(vdev))382		return -EINVAL;383 384	/* return the number of supported vectors if we can't get all: */385	cmd = vfio_pci_memory_lock_and_enable(vdev);386	ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag);387	if (ret < nvec) {388		if (ret > 0)389			pci_free_irq_vectors(pdev);390		vfio_pci_memory_unlock_and_restore(vdev, cmd);391		return ret;392	}393	vfio_pci_memory_unlock_and_restore(vdev, cmd);394 395	vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX :396				VFIO_PCI_MSI_IRQ_INDEX;397 398	if (!msix) {399		/*400		 * Compute the virtual hardware field for max msi vectors -401		 * it is the log base 2 of the number of vectors.402		 */403		vdev->msi_qmax = fls(nvec * 2 - 1) - 1;404	}405 406	return 0;407}408 409/*410 * vfio_msi_alloc_irq() returns the Linux IRQ number of an MSI or MSI-X device411 * interrupt vector. If a Linux IRQ number is not available then a new412 * interrupt is allocated if dynamic MSI-X is supported.413 *414 * Where is vfio_msi_free_irq()? Allocated interrupts are maintained,415 * essentially forming a cache that subsequent allocations can draw from.416 * Interrupts are freed using pci_free_irq_vectors() when MSI/MSI-X is417 * disabled.418 */419static int vfio_msi_alloc_irq(struct vfio_pci_core_device *vdev,420			      unsigned int vector, bool msix)421{422	struct pci_dev *pdev = vdev->pdev;423	struct msi_map map;424	int irq;425	u16 cmd;426 427	irq = pci_irq_vector(pdev, vector);428	if (WARN_ON_ONCE(irq == 0))429		return -EINVAL;430	if (irq > 0 || !msix || !vdev->has_dyn_msix)431		return irq;432 433	cmd = vfio_pci_memory_lock_and_enable(vdev);434	map = pci_msix_alloc_irq_at(pdev, vector, NULL);435	vfio_pci_memory_unlock_and_restore(vdev, cmd);436 437	return map.index < 0 ? map.index : map.virq;438}439 440static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,441				      unsigned int vector, int fd, bool msix)442{443	struct pci_dev *pdev = vdev->pdev;444	struct vfio_pci_irq_ctx *ctx;445	struct eventfd_ctx *trigger;446	int irq = -EINVAL, ret;447	u16 cmd;448 449	ctx = vfio_irq_ctx_get(vdev, vector);450 451	if (ctx) {452		irq_bypass_unregister_producer(&ctx->producer);453		irq = pci_irq_vector(pdev, vector);454		cmd = vfio_pci_memory_lock_and_enable(vdev);455		free_irq(irq, ctx->trigger);456		vfio_pci_memory_unlock_and_restore(vdev, cmd);457		/* Interrupt stays allocated, will be freed at MSI-X disable. */458		kfree(ctx->name);459		eventfd_ctx_put(ctx->trigger);460		vfio_irq_ctx_free(vdev, ctx, vector);461	}462 463	if (fd < 0)464		return 0;465 466	if (irq == -EINVAL) {467		/* Interrupt stays allocated, will be freed at MSI-X disable. */468		irq = vfio_msi_alloc_irq(vdev, vector, msix);469		if (irq < 0)470			return irq;471	}472 473	ctx = vfio_irq_ctx_alloc(vdev, vector);474	if (!ctx)475		return -ENOMEM;476 477	ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-msi%s[%d](%s)",478			      msix ? "x" : "", vector, pci_name(pdev));479	if (!ctx->name) {480		ret = -ENOMEM;481		goto out_free_ctx;482	}483 484	trigger = eventfd_ctx_fdget(fd);485	if (IS_ERR(trigger)) {486		ret = PTR_ERR(trigger);487		goto out_free_name;488	}489 490	/*491	 * If the vector was previously allocated, refresh the on-device492	 * message data before enabling in case it had been cleared or493	 * corrupted (e.g. due to backdoor resets) since writing.494	 */495	cmd = vfio_pci_memory_lock_and_enable(vdev);496	if (msix) {497		struct msi_msg msg;498 499		get_cached_msi_msg(irq, &msg);500		pci_write_msi_msg(irq, &msg);501	}502 503	ret = request_irq(irq, vfio_msihandler, 0, ctx->name, trigger);504	vfio_pci_memory_unlock_and_restore(vdev, cmd);505	if (ret)506		goto out_put_eventfd_ctx;507 508	ctx->producer.token = trigger;509	ctx->producer.irq = irq;510	ret = irq_bypass_register_producer(&ctx->producer);511	if (unlikely(ret)) {512		dev_info(&pdev->dev,513		"irq bypass producer (token %p) registration fails: %d\n",514		ctx->producer.token, ret);515 516		ctx->producer.token = NULL;517	}518	ctx->trigger = trigger;519 520	return 0;521 522out_put_eventfd_ctx:523	eventfd_ctx_put(trigger);524out_free_name:525	kfree(ctx->name);526out_free_ctx:527	vfio_irq_ctx_free(vdev, ctx, vector);528	return ret;529}530 531static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start,532			      unsigned count, int32_t *fds, bool msix)533{534	unsigned int i, j;535	int ret = 0;536 537	for (i = 0, j = start; i < count && !ret; i++, j++) {538		int fd = fds ? fds[i] : -1;539		ret = vfio_msi_set_vector_signal(vdev, j, fd, msix);540	}541 542	if (ret) {543		for (i = start; i < j; i++)544			vfio_msi_set_vector_signal(vdev, i, -1, msix);545	}546 547	return ret;548}549 550static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix)551{552	struct pci_dev *pdev = vdev->pdev;553	struct vfio_pci_irq_ctx *ctx;554	unsigned long i;555	u16 cmd;556 557	xa_for_each(&vdev->ctx, i, ctx) {558		vfio_virqfd_disable(&ctx->unmask);559		vfio_virqfd_disable(&ctx->mask);560		vfio_msi_set_vector_signal(vdev, i, -1, msix);561	}562 563	cmd = vfio_pci_memory_lock_and_enable(vdev);564	pci_free_irq_vectors(pdev);565	vfio_pci_memory_unlock_and_restore(vdev, cmd);566 567	/*568	 * Both disable paths above use pci_intx_for_msi() to clear DisINTx569	 * via their shutdown paths.  Restore for NoINTx devices.570	 */571	if (vdev->nointx)572		pci_intx(pdev, 0);573 574	vdev->irq_type = VFIO_PCI_NUM_IRQS;575}576 577/*578 * IOCTL support579 */580static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev,581				    unsigned index, unsigned start,582				    unsigned count, uint32_t flags, void *data)583{584	if (!is_intx(vdev) || start != 0 || count != 1)585		return -EINVAL;586 587	if (flags & VFIO_IRQ_SET_DATA_NONE) {588		__vfio_pci_intx_unmask(vdev);589	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {590		uint8_t unmask = *(uint8_t *)data;591		if (unmask)592			__vfio_pci_intx_unmask(vdev);593	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {594		struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0);595		int32_t fd = *(int32_t *)data;596 597		if (WARN_ON_ONCE(!ctx))598			return -EINVAL;599		if (fd >= 0)600			return vfio_virqfd_enable((void *) vdev,601						  vfio_pci_intx_unmask_handler,602						  vfio_send_intx_eventfd, ctx,603						  &ctx->unmask, fd);604 605		vfio_virqfd_disable(&ctx->unmask);606	}607 608	return 0;609}610 611static int vfio_pci_set_intx_mask(struct vfio_pci_core_device *vdev,612				  unsigned index, unsigned start,613				  unsigned count, uint32_t flags, void *data)614{615	if (!is_intx(vdev) || start != 0 || count != 1)616		return -EINVAL;617 618	if (flags & VFIO_IRQ_SET_DATA_NONE) {619		__vfio_pci_intx_mask(vdev);620	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {621		uint8_t mask = *(uint8_t *)data;622		if (mask)623			__vfio_pci_intx_mask(vdev);624	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {625		return -ENOTTY; /* XXX implement me */626	}627 628	return 0;629}630 631static int vfio_pci_set_intx_trigger(struct vfio_pci_core_device *vdev,632				     unsigned index, unsigned start,633				     unsigned count, uint32_t flags, void *data)634{635	if (is_intx(vdev) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) {636		vfio_intx_disable(vdev);637		return 0;638	}639 640	if (!(is_intx(vdev) || is_irq_none(vdev)) || start != 0 || count != 1)641		return -EINVAL;642 643	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {644		struct eventfd_ctx *trigger = NULL;645		int32_t fd = *(int32_t *)data;646		int ret;647 648		if (fd >= 0) {649			trigger = eventfd_ctx_fdget(fd);650			if (IS_ERR(trigger))651				return PTR_ERR(trigger);652		}653 654		if (is_intx(vdev))655			ret = vfio_intx_set_signal(vdev, trigger);656		else657			ret = vfio_intx_enable(vdev, trigger);658 659		if (ret && trigger)660			eventfd_ctx_put(trigger);661 662		return ret;663	}664 665	if (!is_intx(vdev))666		return -EINVAL;667 668	if (flags & VFIO_IRQ_SET_DATA_NONE) {669		vfio_send_intx_eventfd(vdev, vfio_irq_ctx_get(vdev, 0));670	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {671		uint8_t trigger = *(uint8_t *)data;672		if (trigger)673			vfio_send_intx_eventfd(vdev, vfio_irq_ctx_get(vdev, 0));674	}675	return 0;676}677 678static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,679				    unsigned index, unsigned start,680				    unsigned count, uint32_t flags, void *data)681{682	struct vfio_pci_irq_ctx *ctx;683	unsigned int i;684	bool msix = (index == VFIO_PCI_MSIX_IRQ_INDEX) ? true : false;685 686	if (irq_is(vdev, index) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) {687		vfio_msi_disable(vdev, msix);688		return 0;689	}690 691	if (!(irq_is(vdev, index) || is_irq_none(vdev)))692		return -EINVAL;693 694	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {695		int32_t *fds = data;696		int ret;697 698		if (vdev->irq_type == index)699			return vfio_msi_set_block(vdev, start, count,700						  fds, msix);701 702		ret = vfio_msi_enable(vdev, start + count, msix);703		if (ret)704			return ret;705 706		ret = vfio_msi_set_block(vdev, start, count, fds, msix);707		if (ret)708			vfio_msi_disable(vdev, msix);709 710		return ret;711	}712 713	if (!irq_is(vdev, index))714		return -EINVAL;715 716	for (i = start; i < start + count; i++) {717		ctx = vfio_irq_ctx_get(vdev, i);718		if (!ctx)719			continue;720		if (flags & VFIO_IRQ_SET_DATA_NONE) {721			eventfd_signal(ctx->trigger);722		} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {723			uint8_t *bools = data;724			if (bools[i - start])725				eventfd_signal(ctx->trigger);726		}727	}728	return 0;729}730 731static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,732					   unsigned int count, uint32_t flags,733					   void *data)734{735	/* DATA_NONE/DATA_BOOL enables loopback testing */736	if (flags & VFIO_IRQ_SET_DATA_NONE) {737		if (*ctx) {738			if (count) {739				eventfd_signal(*ctx);740			} else {741				eventfd_ctx_put(*ctx);742				*ctx = NULL;743			}744			return 0;745		}746	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {747		uint8_t trigger;748 749		if (!count)750			return -EINVAL;751 752		trigger = *(uint8_t *)data;753		if (trigger && *ctx)754			eventfd_signal(*ctx);755 756		return 0;757	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {758		int32_t fd;759 760		if (!count)761			return -EINVAL;762 763		fd = *(int32_t *)data;764		if (fd == -1) {765			if (*ctx)766				eventfd_ctx_put(*ctx);767			*ctx = NULL;768		} else if (fd >= 0) {769			struct eventfd_ctx *efdctx;770 771			efdctx = eventfd_ctx_fdget(fd);772			if (IS_ERR(efdctx))773				return PTR_ERR(efdctx);774 775			if (*ctx)776				eventfd_ctx_put(*ctx);777 778			*ctx = efdctx;779		}780		return 0;781	}782 783	return -EINVAL;784}785 786static int vfio_pci_set_err_trigger(struct vfio_pci_core_device *vdev,787				    unsigned index, unsigned start,788				    unsigned count, uint32_t flags, void *data)789{790	if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)791		return -EINVAL;792 793	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,794					       count, flags, data);795}796 797static int vfio_pci_set_req_trigger(struct vfio_pci_core_device *vdev,798				    unsigned index, unsigned start,799				    unsigned count, uint32_t flags, void *data)800{801	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)802		return -EINVAL;803 804	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,805					       count, flags, data);806}807 808int vfio_pci_set_irqs_ioctl(struct vfio_pci_core_device *vdev, uint32_t flags,809			    unsigned index, unsigned start, unsigned count,810			    void *data)811{812	int (*func)(struct vfio_pci_core_device *vdev, unsigned index,813		    unsigned start, unsigned count, uint32_t flags,814		    void *data) = NULL;815 816	switch (index) {817	case VFIO_PCI_INTX_IRQ_INDEX:818		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {819		case VFIO_IRQ_SET_ACTION_MASK:820			func = vfio_pci_set_intx_mask;821			break;822		case VFIO_IRQ_SET_ACTION_UNMASK:823			func = vfio_pci_set_intx_unmask;824			break;825		case VFIO_IRQ_SET_ACTION_TRIGGER:826			func = vfio_pci_set_intx_trigger;827			break;828		}829		break;830	case VFIO_PCI_MSI_IRQ_INDEX:831	case VFIO_PCI_MSIX_IRQ_INDEX:832		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {833		case VFIO_IRQ_SET_ACTION_MASK:834		case VFIO_IRQ_SET_ACTION_UNMASK:835			/* XXX Need masking support exported */836			break;837		case VFIO_IRQ_SET_ACTION_TRIGGER:838			func = vfio_pci_set_msi_trigger;839			break;840		}841		break;842	case VFIO_PCI_ERR_IRQ_INDEX:843		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {844		case VFIO_IRQ_SET_ACTION_TRIGGER:845			if (pci_is_pcie(vdev->pdev))846				func = vfio_pci_set_err_trigger;847			break;848		}849		break;850	case VFIO_PCI_REQ_IRQ_INDEX:851		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {852		case VFIO_IRQ_SET_ACTION_TRIGGER:853			func = vfio_pci_set_req_trigger;854			break;855		}856		break;857	}858 859	if (!func)860		return -ENOTTY;861 862	return func(vdev, index, start, count, flags, data);863}864