The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/vmm/amd/amdiommu.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2021 The FreeBSD Foundation
    5  *
    6  * Portions of this software were developed by Ka Ho Ng
    7  * under sponsorship from the FreeBSD Foundation.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice unmodified, this list of conditions, and the following
   14  *    disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/rman.h>
   39 
   40 #include <dev/pci/pcireg.h>
   41 #include <dev/pci/pcivar.h>
   42 
   43 #include "amdvi_priv.h"
   44 #include "ivhd_if.h"
   45 
   46 struct amdiommu_softc {
   47         struct resource *event_res;     /* Event interrupt resource. */
   48         void            *event_tag;     /* Event interrupt tag. */
   49         int             event_rid;
   50 };
   51 
   52 static int      amdiommu_probe(device_t);
   53 static int      amdiommu_attach(device_t);
   54 static int      amdiommu_detach(device_t);
   55 static int      ivhd_setup_intr(device_t, driver_intr_t, void *,
   56                     const char *);
   57 static int      ivhd_teardown_intr(device_t);
   58 
   59 static device_method_t amdiommu_methods[] = {
   60         /* device interface */
   61         DEVMETHOD(device_probe,                 amdiommu_probe),
   62         DEVMETHOD(device_attach,                amdiommu_attach),
   63         DEVMETHOD(device_detach,                amdiommu_detach),
   64         DEVMETHOD(ivhd_setup_intr,              ivhd_setup_intr),
   65         DEVMETHOD(ivhd_teardown_intr,           ivhd_teardown_intr),
   66         DEVMETHOD_END
   67 };
   68 static driver_t amdiommu_driver = {
   69         "amdiommu",
   70         amdiommu_methods,
   71         sizeof(struct amdiommu_softc),
   72 };
   73 
   74 static int
   75 amdiommu_probe(device_t dev)
   76 {
   77         int error;
   78         int capoff;
   79 
   80         /*
   81          * Check base class and sub-class
   82          */
   83         if (pci_get_class(dev) != PCIC_BASEPERIPH ||
   84             pci_get_subclass(dev) != PCIS_BASEPERIPH_IOMMU)
   85                 return (ENXIO);
   86 
   87         /*
   88          * A IOMMU capability block carries a 0Fh capid.
   89          */
   90         error = pci_find_cap(dev, PCIY_SECDEV, &capoff);
   91         if (error)
   92                 return (ENXIO);
   93 
   94         /*
   95          * bit [18:16] == 011b indicates the capability block is IOMMU
   96          * capability block. If the field is not set to 011b, bail out.
   97          */
   98         if ((pci_read_config(dev, capoff + 2, 2) & 0x7) != 0x3)
   99                 return (ENXIO);
  100 
  101         return (BUS_PROBE_SPECIFIC);
  102 }
  103 
  104 static int
  105 amdiommu_attach(device_t dev)
  106 {
  107 
  108         device_set_desc(dev, "AMD-Vi/IOMMU PCI function");
  109         return (0);
  110 }
  111 
  112 static int
  113 amdiommu_detach(device_t dev)
  114 {
  115 
  116         return (0);
  117 }
  118 
  119 static int
  120 ivhd_setup_intr(device_t dev, driver_intr_t handler, void *arg,
  121     const char *desc)
  122 {
  123         struct amdiommu_softc *sc;
  124         int error, msicnt;
  125 
  126         sc = device_get_softc(dev);
  127         msicnt = 1;
  128         if (sc->event_res != NULL)
  129                 panic("%s is called without intr teardown", __func__);
  130         sc->event_rid = 1;
  131 
  132         error = pci_alloc_msi(dev, &msicnt);
  133         if (error) {
  134                 device_printf(dev, "Couldn't find event MSI IRQ resource.\n");
  135                 return (ENOENT);
  136         }
  137 
  138         sc->event_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  139             &sc->event_rid, RF_ACTIVE);
  140         if (sc->event_res == NULL) {
  141                 device_printf(dev, "Unable to allocate event INTR resource.\n");
  142                 error = ENOMEM;
  143                 goto fail;
  144         }
  145 
  146         error = bus_setup_intr(dev, sc->event_res, INTR_TYPE_MISC | INTR_MPSAFE,
  147             NULL, handler, arg, &sc->event_tag);
  148         if (error) {
  149                 device_printf(dev, "Fail to setup event intr\n");
  150                 goto fail;
  151         }
  152 
  153         bus_describe_intr(dev, sc->event_res, sc->event_tag, "%s", desc);
  154         return (0);
  155 
  156 fail:
  157         ivhd_teardown_intr(dev);
  158         return (error);
  159 }
  160 
  161 static int
  162 ivhd_teardown_intr(device_t dev)
  163 {
  164         struct amdiommu_softc *sc;
  165 
  166         sc = device_get_softc(dev);
  167 
  168         if (sc->event_tag != NULL) {
  169                 bus_teardown_intr(dev, sc->event_res, sc->event_tag);
  170                 sc->event_tag = NULL;
  171         }
  172         if (sc->event_res != NULL) {
  173                 bus_release_resource(dev, SYS_RES_IRQ, sc->event_rid,
  174                     sc->event_res);
  175                 sc->event_res = NULL;
  176         }
  177         pci_release_msi(dev);
  178         return (0);
  179 }
  180 
  181 /* This driver has to be loaded before ivhd */
  182 DRIVER_MODULE(amdiommu, pci, amdiommu_driver, 0, 0);
  183 MODULE_DEPEND(amdiommu, pci, 1, 1, 1);

Cache object: b3536ea7ca7b0dc4e51810e11fd3877d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.