~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm64/kvm/vgic/vgic-irqfd.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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  */
 18 static 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  */
 38 int 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;
 65 out:
 66         return r;
 67 }
 68 
 69 static 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  */
 86 int 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  */
105 int 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 
136 int 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 }
157 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php