File Index
Files and directories
Sign in
FILE

vgic-irqfd.c

File preview with syntax highlighting.

linux-6.19.14/arch/arm64/kvm/vgic/vgic-irqfd.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2015, 2016 ARM Ltd.
  4 */
  5
  6#include <linux/kvm.h>
  7#include <linux/kvm_host.h>
  8#include <trace/events/kvm.h>
  9#include <kvm/arm_vgic.h>
 10#include "vgic.h"
 11
 12/*
 13 * vgic_irqfd_set_irq: inject the IRQ corresponding to the
 14 * irqchip routing entry
 15 *
 16 * This is the entry point for irqfd IRQ injection
 17 */
 18static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
 19			struct kvm *kvm, int irq_source_id,
 20			int level, bool line_status)
 21{
 22	unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
 23
 24	if (!vgic_valid_spi(kvm, spi_id))
 25		return -EINVAL;
 26	return kvm_vgic_inject_irq(kvm, NULL, spi_id, level, NULL);
 27}
 28
 29/**
 30 * kvm_set_routing_entry: populate a kvm routing entry
 31 * from a user routing entry
 32 *
 33 * @kvm: the VM this entry is applied to
 34 * @e: kvm kernel routing entry handle
 35 * @ue: user api routing entry handle
 36 * return 0 on success, -EINVAL on errors.
 37 */
 38int kvm_set_routing_entry(struct kvm *kvm,
 39			  struct kvm_kernel_irq_routing_entry *e,
 40			  const struct kvm_irq_routing_entry *ue)
 41{
 42	int r = -EINVAL;
 43
 44	switch (ue->type) {
 45	case KVM_IRQ_ROUTING_IRQCHIP:
 46		e->set = vgic_irqfd_set_irq;
 47		e->irqchip.irqchip = ue->u.irqchip.irqchip;
 48		e->irqchip.pin = ue->u.irqchip.pin;
 49		if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
 50		    (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
 51			goto out;
 52		break;
 53	case KVM_IRQ_ROUTING_MSI:
 54		e->set = kvm_set_msi;
 55		e->msi.address_lo = ue->u.msi.address_lo;
 56		e->msi.address_hi = ue->u.msi.address_hi;
 57		e->msi.data = ue->u.msi.data;
 58		e->msi.flags = ue->flags;
 59		e->msi.devid = ue->u.msi.devid;
 60		break;
 61	default:
 62		goto out;
 63	}
 64	r = 0;
 65out:
 66	return r;
 67}
 68
 69static void kvm_populate_msi(struct kvm_kernel_irq_routing_entry *e,
 70			     struct kvm_msi *msi)
 71{
 72	msi->address_lo = e->msi.address_lo;
 73	msi->address_hi = e->msi.address_hi;
 74	msi->data = e->msi.data;
 75	msi->flags = e->msi.flags;
 76	msi->devid = e->msi.devid;
 77}
 78
 79/*
 80 * kvm_set_msi: inject the MSI corresponding to the
 81 * MSI routing entry
 82 *
 83 * This is the entry point for irqfd MSI injection
 84 * and userspace MSI injection.
 85 */
 86int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 87		struct kvm *kvm, int irq_source_id,
 88		int level, bool line_status)
 89{
 90	struct kvm_msi msi;
 91
 92	if (!vgic_has_its(kvm))
 93		return -ENODEV;
 94
 95	if (!level)
 96		return -1;
 97
 98	kvm_populate_msi(e, &msi);
 99	return vgic_its_inject_msi(kvm, &msi);
100}
101
102/*
103 * kvm_arch_set_irq_inatomic: fast-path for irqfd injection
104 */
105int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
106			      struct kvm *kvm, int irq_source_id, int level,
107			      bool line_status)
108{
109	if (!level)
110		return -EWOULDBLOCK;
111
112	switch (e->type) {
113	case KVM_IRQ_ROUTING_MSI: {
114		struct kvm_msi msi;
115
116		if (!vgic_has_its(kvm))
117			break;
118
119		kvm_populate_msi(e, &msi);
120		return vgic_its_inject_cached_translation(kvm, &msi);
121	}
122
123	case KVM_IRQ_ROUTING_IRQCHIP:
124		/*
125		 * Injecting SPIs is always possible in atomic context
126		 * as long as the damn vgic is initialized.
127		 */
128		if (unlikely(!vgic_initialized(kvm)))
129			break;
130		return vgic_irqfd_set_irq(e, kvm, irq_source_id, 1, line_status);
131	}
132
133	return -EWOULDBLOCK;
134}
135
136int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
137{
138	struct kvm_irq_routing_entry *entries;
139	struct vgic_dist *dist = &kvm->arch.vgic;
140	u32 nr = dist->nr_spis;
141	int i, ret;
142
143	entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL_ACCOUNT);
144	if (!entries)
145		return -ENOMEM;
146
147	for (i = 0; i < nr; i++) {
148		entries[i].gsi = i;
149		entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
150		entries[i].u.irqchip.irqchip = 0;
151		entries[i].u.irqchip.pin = i;
152	}
153	ret = kvm_set_irq_routing(kvm, entries, nr, 0);
154	kfree(entries);
155	return ret;
156}
~/ Read-only file preview.