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/arm64/coresight/coresight_acpi.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
    3  *
    4  * Copyright (c) 2020 Ruslan Bukin <br@bsdpad.com>
    5  *
    6  * This software was developed by SRI International and the University of
    7  * Cambridge Computer Laboratory (Department of Computer Science and
    8  * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
    9  * DARPA SSITH research programme.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 #include <sys/rman.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 #include <sys/uuid.h>
   45 #include <machine/bus.h>
   46 
   47 #include <contrib/dev/acpica/include/acpi.h>
   48 #include <dev/acpica/acpivar.h>
   49 
   50 #include <arm64/coresight/coresight.h>
   51 
   52 #define ACPI_CORESIGHT_LINK_OUTPUT      1
   53 #define ACPI_CORESIGHT_LINK_INPUT       0
   54 
   55 static const struct uuid acpi_graph_uuid = {
   56         0xab02a46b, 0x74c7, 0x45a2, 0xbd, 0x68,
   57         { 0xf7, 0xd3, 0x44, 0xef, 0x21, 0x53 },
   58 };
   59 
   60 static const struct uuid coresight_graph_uuid = {
   61         0x3ecbc8b6, 0x1d0e, 0x4fb3, 0x81, 0x07,
   62         { 0xe6, 0x27, 0xf8, 0x05, 0xc6, 0xcd },
   63 };
   64 
   65 static inline bool
   66 cs_acpi_validate_dsd_graph(const union acpi_object *graph)
   67 {
   68         const union acpi_object *rev, *nr_graphs;
   69         const union acpi_object *obj;
   70         int i, n;
   71 
   72         if (graph->Package.Count < 2)
   73                 return (false);
   74 
   75         rev = &graph->Package.Elements[0];
   76         nr_graphs = &graph->Package.Elements[1];
   77 
   78         if (rev->Type != ACPI_TYPE_INTEGER ||
   79             nr_graphs->Type != ACPI_TYPE_INTEGER)
   80                 return (false);
   81 
   82         /* Revision 0 supported only. */
   83         if (rev->Integer.Value != 0)
   84                 return (false);
   85 
   86         /* We are looking for a single graph. */
   87         n = nr_graphs->Integer.Value;
   88         if (n != 1)
   89                 return (false);
   90 
   91         /* Check the number of elements. */
   92         if (graph->Package.Count != (n + 2))
   93                 return (false);
   94 
   95         for (i = 2; i < n + 2; i++) {
   96                 obj = &graph->Package.Elements[i];
   97                 if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count < 3)
   98                         return (false);
   99         }
  100 
  101         return (true);
  102 }
  103 
  104 static inline bool
  105 cs_is_acpi_guid(const union acpi_object *obj)
  106 {
  107 
  108         return (obj->Type == ACPI_TYPE_BUFFER) && (obj->Buffer.Length == 16);
  109 }
  110 
  111 static inline bool
  112 cs_guid_equal(const struct uuid *u1, const struct uuid *u2)
  113 {
  114 
  115         if (memcmp(u1, u2, 16) == 0)
  116                 return (true);
  117 
  118         return (false);
  119 }
  120 
  121 static inline bool
  122 cs_acpi_guid_matches(const union acpi_object *obj, const struct uuid *guid)
  123 {
  124 
  125         if (cs_is_acpi_guid(obj) &&
  126             cs_guid_equal((struct uuid *)obj->Buffer.Pointer, guid))
  127                 return (true);
  128 
  129         return (false);
  130 }
  131 
  132 static inline bool
  133 is_acpi_dsd_graph_guid(const union acpi_object *obj)
  134 {
  135 
  136         return (cs_acpi_guid_matches(obj, &acpi_graph_uuid));
  137 }
  138 
  139 static inline bool
  140 cs_is_acpi_coresight_graph_guid(const union acpi_object *obj)
  141 {
  142 
  143         return (cs_acpi_guid_matches(obj, &coresight_graph_uuid));
  144 }
  145 
  146 static inline bool
  147 cs_is_acpi_coresight_graph(const union acpi_object *obj)
  148 {
  149         const union acpi_object *graphid, *guid, *links;
  150 
  151         if (obj->Type != ACPI_TYPE_PACKAGE ||
  152             obj->Package.Count < 3)
  153                 return (false);
  154 
  155         graphid = &obj->Package.Elements[0];
  156         guid = &obj->Package.Elements[1];
  157         links = &obj->Package.Elements[2];
  158 
  159         if (graphid->Type != ACPI_TYPE_INTEGER ||
  160             links->Type != ACPI_TYPE_INTEGER)
  161                 return (false);
  162 
  163         if (cs_is_acpi_coresight_graph_guid(guid))
  164                 return (true);
  165 
  166         return (false);
  167 }
  168 
  169 static const union acpi_object *
  170 cs_get_dsd_graph(device_t dev)
  171 {
  172         const union acpi_object *guid, *package;
  173         union acpi_object *dsd;
  174         ACPI_STATUS status;
  175         ACPI_BUFFER buf;
  176         device_t bus;
  177         int i;
  178 
  179         buf.Length = PAGE_SIZE;
  180         buf.Pointer = malloc(buf.Length, M_TEMP, M_NOWAIT | M_ZERO);
  181         if (buf.Pointer == NULL) {
  182                 printf("Failed to allocate memory.\n");
  183                 return (NULL);
  184         }
  185 
  186         bus = device_get_parent(dev);
  187         status = ACPI_EVALUATE_OBJECT(bus, dev, "_DSD", NULL, &buf);
  188         if (ACPI_FAILURE(status)) {
  189                 printf("Failed to evaluate object.\n");
  190                 return (NULL);
  191         }
  192 
  193         dsd = buf.Pointer;
  194 
  195         for (i = 0; i + 1 < dsd->Package.Count; i += 2) {
  196                 guid = &dsd->Package.Elements[i];
  197                 package = &dsd->Package.Elements[i + 1];
  198 
  199                 if (!cs_is_acpi_guid(guid) ||
  200                     package->Type != ACPI_TYPE_PACKAGE)
  201                         break;
  202 
  203                 if (!is_acpi_dsd_graph_guid(guid))
  204                         continue;
  205 
  206                 if (cs_acpi_validate_dsd_graph(package))
  207                         return (package);
  208         }
  209 
  210         return (NULL);
  211 }
  212 
  213 static inline bool
  214 cs_acpi_validate_coresight_graph(const union acpi_object *cs_graph)
  215 {
  216         int nlinks;
  217 
  218         nlinks = cs_graph->Package.Elements[2].Integer.Value;
  219         if (cs_graph->Package.Count != (nlinks + 3))
  220                 return (false);
  221 
  222         return (true);
  223 }
  224 
  225 static const union acpi_object *
  226 cs_get_coresight_graph(device_t dev)
  227 {
  228         const union acpi_object *graph_list, *graph;
  229         int i, nr_graphs;
  230 
  231         graph_list = cs_get_dsd_graph(dev);
  232         if (!graph_list) {
  233                 printf("failed to get graph list\n");
  234                 return (NULL);
  235         }
  236 
  237         nr_graphs = graph_list->Package.Elements[1].Integer.Value;
  238         for (i = 2; i < nr_graphs + 2; i++) {
  239                 graph = &graph_list->Package.Elements[i];
  240                 if (!cs_is_acpi_coresight_graph(graph))
  241                         continue;
  242                 if (cs_acpi_validate_coresight_graph(graph))
  243                         return (graph);
  244                 break;
  245         }
  246 
  247         return (NULL);
  248 }
  249 
  250 static int
  251 cs_acpi_record_endpoint(device_t dev,
  252     struct coresight_platform_data *pdata,
  253     const union acpi_object *link)
  254 {
  255         const union acpi_object *fields;
  256         struct endpoint *endp;
  257         ACPI_HANDLE handle;
  258         int dir;
  259 
  260         if (link->Type != ACPI_TYPE_PACKAGE ||
  261             link->Package.Count != 4)
  262                 return (ENXIO);
  263 
  264         fields = link->Package.Elements;
  265         if (fields[0].Type != ACPI_TYPE_INTEGER ||
  266             fields[1].Type != ACPI_TYPE_INTEGER ||
  267             fields[2].Type != ACPI_TYPE_LOCAL_REFERENCE ||
  268             fields[3].Type != ACPI_TYPE_INTEGER)
  269                 return (ENXIO);
  270 
  271         handle = fields[2].Reference.Handle;
  272         dir = fields[3].Integer.Value;
  273 
  274         endp = malloc(sizeof(struct endpoint),
  275             M_CORESIGHT, M_WAITOK | M_ZERO);
  276         if (endp == NULL) {
  277                 device_printf(dev, "Failed to allocate memory.\n");
  278                 return (ENXIO);
  279         }
  280 
  281         endp->their_handle = handle;
  282         endp->my_handle = acpi_get_handle(dev);
  283 
  284         mtx_lock(&pdata->mtx_lock);
  285         TAILQ_INSERT_TAIL(&pdata->endpoints, endp, link);
  286         mtx_unlock(&pdata->mtx_lock);
  287 
  288         if (dir == ACPI_CORESIGHT_LINK_OUTPUT) {
  289                 pdata->out_ports++;
  290         } else {
  291                 endp->input = true;
  292                 pdata->in_ports++;
  293         }
  294 
  295         return (0);
  296 }
  297 
  298 static int
  299 coresight_acpi_get_ports(device_t dev,
  300     struct coresight_platform_data *pdata)
  301 {
  302         const union acpi_object *graph;
  303         const union acpi_object *link;
  304         int nlinks;
  305         int error;
  306         int i;
  307 
  308         graph = cs_get_coresight_graph(dev);
  309         if (graph == NULL) {
  310                 device_printf(dev, "Coresight graph not found.\n");
  311                 return (ENXIO);
  312         }
  313 
  314         nlinks = graph->Package.Elements[2].Integer.Value;
  315         if (!nlinks)
  316                 return (0);
  317 
  318         for (i = 0; i < nlinks; i++) {
  319                 link = &graph->Package.Elements[3 + i];
  320                 error = cs_acpi_record_endpoint(dev, pdata, link);
  321                 if (error < 0)
  322                         return (error);
  323         }
  324 
  325         return (0);
  326 }
  327 
  328 static int
  329 coresight_acpi_get_cpu(device_t dev, struct coresight_platform_data *pdata)
  330 {
  331         ACPI_HANDLE handle, parent;
  332         ACPI_STATUS status;
  333         int cpuid;
  334 
  335         handle = acpi_get_handle(dev);
  336 
  337         status = AcpiGetParent(handle, &parent);
  338         if (!ACPI_SUCCESS(status))
  339                 return (ENXIO);
  340 
  341         if (!acpi_MatchHid(parent, "ACPI0007"))
  342                 return (ENXIO);
  343 
  344         status = acpi_GetInteger(parent, "_UID", &cpuid);
  345         if (ACPI_SUCCESS(status)) {
  346                 pdata->cpu = cpuid;
  347                 return (0);
  348         }
  349 
  350         return (ENXIO);
  351 }
  352 
  353 struct coresight_platform_data *
  354 coresight_acpi_get_platform_data(device_t dev)
  355 {
  356         struct coresight_platform_data *pdata;
  357 
  358         pdata = malloc(sizeof(struct coresight_platform_data),
  359             M_CORESIGHT, M_WAITOK | M_ZERO);
  360         pdata->bus_type = CORESIGHT_BUS_ACPI;
  361 
  362         mtx_init(&pdata->mtx_lock, "Coresight Platform Data", NULL, MTX_DEF);
  363         TAILQ_INIT(&pdata->endpoints);
  364 
  365         coresight_acpi_get_cpu(dev, pdata);
  366         coresight_acpi_get_ports(dev, pdata);
  367 
  368         if (bootverbose)
  369                 printf("Total ports: in %d out %d\n",
  370                     pdata->in_ports, pdata->out_ports);
  371 
  372         return (pdata);
  373 }

Cache object: 2481b15565f10303efb0dff3b862f233


[ 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.