LCOV - code coverage report
Current view: top level - hdata - pcia.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 87 107 81.3 %
Date: 2024-09-10 18:37:41 Functions: 5 5 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /* Copyright 2013-2019 IBM Corp. */
       3                 :            : 
       4                 :            : #include <skiboot.h>
       5                 :            : #include "spira.h"
       6                 :            : #include <cpu.h>
       7                 :            : #include <fsp.h>
       8                 :            : #include <opal.h>
       9                 :            : #include <ccan/str/str.h>
      10                 :            : #include <device.h>
      11                 :            : 
      12                 :            : #include "hdata.h"
      13                 :            : 
      14                 :            : #define PCIA_MAX_THREADS        8
      15                 :            : 
      16                 :         12 : static unsigned int pcia_index(const void *pcia)
      17                 :            : {
      18                 :         12 :         return (pcia - (void *)get_hdif(&spiras->ntuples.pcia, "SPPCIA"))
      19                 :         12 :                 / be32_to_cpu(spiras->ntuples.pcia.alloc_len);
      20                 :            : }
      21                 :            : 
      22                 :        102 : static const struct sppcia_cpu_thread *find_tada(const void *pcia,
      23                 :            :                                                  unsigned int thread)
      24                 :            : {
      25                 :        102 :         int count = HDIF_get_iarray_size(pcia, SPPCIA_IDATA_THREAD_ARRAY);
      26                 :            :         int i;
      27                 :            : 
      28                 :        102 :         if (count < 0)
      29                 :          0 :                 return NULL;
      30                 :            : 
      31                 :        438 :         for (i = 0; i < count; i++) {
      32                 :            :                 const struct sppcia_cpu_thread *t;
      33                 :            :                 unsigned int size;
      34                 :            : 
      35                 :        438 :                 t = HDIF_get_iarray_item(pcia, SPPCIA_IDATA_THREAD_ARRAY,
      36                 :            :                                          i, &size);
      37                 :        438 :                 if (!t || size < sizeof(*t))
      38                 :          0 :                         continue;
      39                 :        438 :                 if (be32_to_cpu(t->phys_thread_id) == thread)
      40                 :        102 :                         return t;
      41                 :            :         }
      42                 :          0 :         return NULL;
      43                 :            : }
      44                 :            : 
      45                 :          6 : static void add_xics_icp(const void *pcia, u32 tcount, const char *compat)
      46                 :            : {
      47                 :            :         const struct sppcia_cpu_thread *t;
      48                 :            :         struct dt_node *icp;
      49                 :            :         __be64 *reg;
      50                 :            :         u32 i, irange[2], rsize;
      51                 :            : 
      52                 :          6 :         rsize = tcount * 2 * sizeof(__be64);
      53                 :          6 :         reg = malloc(rsize);
      54                 :          6 :         assert(reg);
      55                 :            : 
      56                 :            :         /* Suppresses uninitialized warning from gcc */
      57                 :          6 :         irange[0] = 0;
      58                 :         54 :         for (i = 0; i < tcount; i++) {
      59                 :         48 :                 t = find_tada(pcia, i);
      60                 :         48 :                 assert(t);
      61                 :         48 :                 if (i == 0)
      62                 :          6 :                         irange[0] = be32_to_cpu(t->pir);
      63                 :         48 :                 reg[i * 2] = cpu_to_be64(cleanup_addr(be64_to_cpu(t->ibase)));
      64                 :         48 :                 reg[i * 2 + 1] = cpu_to_be64(0x1000);
      65                 :            :         }
      66                 :          6 :         irange[1] = tcount;
      67                 :            : 
      68                 :          6 :         icp = dt_new_addr(dt_root, "interrupt-controller", be64_to_cpu(reg[0]));
      69                 :          6 :         if (!icp) {
      70                 :          0 :                 free(reg);
      71                 :          0 :                 return;
      72                 :            :         }
      73                 :            : 
      74                 :          6 :         if (compat)
      75                 :          6 :                 dt_add_property_strings(icp, "compatible", "ibm,ppc-xicp", compat);
      76                 :            :         else
      77                 :          0 :                 dt_add_property_strings(icp, "compatible", "ibm,ppc-xicp");
      78                 :          6 :         dt_add_property_cells(icp, "ibm,interrupt-server-ranges",
      79                 :            :                               irange[0], irange[1]);
      80                 :          6 :         dt_add_property(icp, "interrupt-controller", NULL, 0);
      81                 :          6 :         dt_add_property_cells(icp, "#interrupt-cells", 1);
      82                 :          6 :         dt_add_property(icp, "reg", reg, rsize);
      83                 :          6 :         dt_add_property_cells(icp, "#address-cells", 0);
      84                 :          6 :         dt_add_property_string(icp, "device_type",
      85                 :            :                                "PowerPC-External-Interrupt-Presentation");
      86                 :          6 :         free(reg);
      87                 :            : }
      88                 :            : 
      89                 :          6 : static struct dt_node *add_core_node(struct dt_node *cpus,
      90                 :            :                                      const void *pcia,
      91                 :            :                                      const struct sppcia_core_unique *id,
      92                 :            :                                      bool okay)
      93                 :            : {
      94                 :            :         const struct sppcia_cpu_thread *t;
      95                 :            :         const struct sppcia_cpu_timebase *timebase;
      96                 :            :         const struct sppcia_cpu_cache *cache;
      97                 :            :         const struct sppcia_cpu_attr *attr;
      98                 :            :         struct dt_node *cpu;
      99                 :            :         const char *icp_compat;
     100                 :            :         u32 i, size, threads, ve_flags, l2_phandle, chip_id;
     101                 :            :         __be32 iserv[PCIA_MAX_THREADS];
     102                 :            : 
     103                 :            :         /* Look for thread 0 */
     104                 :          6 :         t = find_tada(pcia, 0);
     105                 :          6 :         if (!t) {
     106                 :          0 :                 prerror("CORE[%i]: Failed to find thread 0 !\n",
     107                 :            :                         pcia_index(pcia));
     108                 :          0 :                 return NULL;
     109                 :            :         }
     110                 :            : 
     111                 :          6 :         ve_flags = be32_to_cpu(id->verif_exist_flags);
     112                 :          6 :         threads = ((ve_flags & CPU_ID_NUM_SECONDARY_THREAD_MASK)
     113                 :          6 :                    >> CPU_ID_NUM_SECONDARY_THREAD_SHIFT) + 1;
     114                 :          6 :         assert(threads <= PCIA_MAX_THREADS);
     115                 :            : 
     116                 :          6 :         prlog(PR_INFO, "CORE[%i]: PIR=%.8x %s %s(%u threads)\n",
     117                 :            :               pcia_index(pcia), be32_to_cpu(t->pir),
     118                 :            :               ve_flags & CPU_ID_PCIA_RESERVED
     119                 :            :               ? "**RESERVED**" : cpu_state(ve_flags),
     120                 :            :               be32_to_cpu(t->pir) == boot_cpu->pir ? "[boot] " : "", threads);
     121                 :            : 
     122                 :          6 :         timebase = HDIF_get_idata(pcia, SPPCIA_IDATA_TIMEBASE, &size);
     123                 :          6 :         if (!timebase || size < sizeof(*timebase)) {
     124                 :          0 :                 prerror("CORE[%i]: bad timebase size %u @ %p\n",
     125                 :            :                         pcia_index(pcia), size, timebase);
     126                 :          0 :                 return NULL;
     127                 :            :         }
     128                 :            : 
     129                 :          6 :         cache = HDIF_get_idata(pcia, SPPCIA_IDATA_CPU_CACHE, &size);
     130                 :          6 :         if (!cache || size < sizeof(*cache)) {
     131                 :          0 :                 prerror("CORE[%i]: bad cache size %u @ %p\n",
     132                 :            :                         pcia_index(pcia), size, cache);
     133                 :          0 :                 return NULL;
     134                 :            :         }
     135                 :            : 
     136                 :          6 :         cpu = add_core_common(cpus, cache, timebase,
     137                 :          6 :                               be32_to_cpu(t->pir), okay);
     138                 :            : 
     139                 :            :         /* Core attributes */
     140                 :          6 :         attr = HDIF_get_idata(pcia, SPPCIA_IDATA_CPU_ATTR, &size);
     141                 :          6 :         if (attr)
     142                 :          6 :                 add_core_attr(cpu, be32_to_cpu(attr->attr));
     143                 :            : 
     144                 :            :         /* Add cache info */
     145                 :          6 :         l2_phandle = add_core_cache_info(cpus, cache,
     146                 :          6 :                                          be32_to_cpu(t->pir), okay);
     147                 :          6 :         dt_add_property_cells(cpu, "l2-cache", l2_phandle);
     148                 :            : 
     149                 :          6 :         if (proc_gen == proc_gen_p8)
     150                 :          6 :                 icp_compat = "IBM,power8-icp";
     151                 :            : 
     152                 :            :         /* Get HW Chip ID */
     153                 :          6 :         chip_id = pcid_to_chip_id(be32_to_cpu(id->proc_chip_id));
     154                 :            : 
     155                 :          6 :         dt_add_property_cells(cpu, "ibm,pir", be32_to_cpu(t->pir));
     156                 :          6 :         dt_add_property_cells(cpu, "ibm,chip-id", chip_id);
     157                 :            : 
     158                 :            :         /* Build ibm,ppc-interrupt-server#s with all threads */
     159                 :         54 :         for (i = 0; i < threads; i++) {
     160                 :         48 :                 t = find_tada(pcia, i);
     161                 :         48 :                 if (!t) {
     162                 :          0 :                         threads = i;
     163                 :          0 :                         break;
     164                 :            :                 }
     165                 :            : 
     166                 :         48 :                 iserv[i] = t->pir;
     167                 :            :         }
     168                 :            : 
     169                 :          6 :         dt_add_property(cpu, "ibm,ppc-interrupt-server#s", iserv, 4 * threads);
     170                 :            : 
     171                 :            :         /* Add the ICP node for this CPU for P8 */
     172                 :          6 :         if (proc_gen == proc_gen_p8)
     173                 :          6 :                 add_xics_icp(pcia, threads, icp_compat);
     174                 :            : 
     175                 :          6 :         return cpu;
     176                 :            : }
     177                 :            : 
     178                 :          1 : bool pcia_parse(void)
     179                 :            : {
     180                 :            :         const void *pcia;
     181                 :            :         struct dt_node *cpus;
     182                 :            : 
     183                 :          1 :         pcia = get_hdif(&spiras->ntuples.pcia, SPPCIA_HDIF_SIG);
     184                 :          1 :         if (!pcia)
     185                 :          0 :                 return false;
     186                 :            : 
     187                 :          1 :         prlog(PR_INFO, "Got PCIA !\n");
     188                 :            : 
     189                 :          1 :         cpus = dt_new(dt_root, "cpus");
     190                 :          1 :         dt_add_property_cells(cpus, "#address-cells", 1);
     191                 :          1 :         dt_add_property_cells(cpus, "#size-cells", 0);
     192                 :            : 
     193                 :          7 :         for_each_pcia(spiras, pcia) {
     194                 :            :                 const struct sppcia_core_unique *id;
     195                 :            :                 u32 size, ve_flags;
     196                 :            :                 bool okay;
     197                 :            : 
     198                 :          6 :                 id = HDIF_get_idata(pcia, SPPCIA_IDATA_CORE_UNIQUE, &size);
     199                 :          6 :                 if (!id || size < sizeof(*id)) {
     200                 :          0 :                         prerror("CORE[%i]: bad id size %u @ %p\n",
     201                 :            :                                 pcia_index(pcia), size, id);
     202                 :          0 :                         return false;
     203                 :            :                 }
     204                 :          6 :                 ve_flags = be32_to_cpu(id->verif_exist_flags);
     205                 :            : 
     206                 :          6 :                 switch ((ve_flags & CPU_ID_VERIFY_MASK)
     207                 :          6 :                         >> CPU_ID_VERIFY_SHIFT) {
     208                 :          6 :                 case CPU_ID_VERIFY_USABLE_NO_FAILURES:
     209                 :            :                 case CPU_ID_VERIFY_USABLE_FAILURES:
     210                 :          6 :                         okay = true;
     211                 :          6 :                         break;
     212                 :          0 :                 default:
     213                 :          0 :                         okay = false;
     214                 :            :                 }
     215                 :            : 
     216                 :          6 :                 prlog(okay ? PR_INFO : PR_WARNING,
     217                 :            :                       "CORE[%i]: HW_PROC_ID=%i PROC_CHIP_ID=%i EC=0x%x %s\n",
     218                 :            :                       pcia_index(pcia), be32_to_cpu(id->hw_proc_id),
     219                 :            :                       be32_to_cpu(id->proc_chip_id),
     220                 :            :                       be32_to_cpu(id->chip_ec_level),
     221                 :            :                       okay ? "OK" : "UNAVAILABLE");
     222                 :            : 
     223                 :          6 :                 if (!add_core_node(cpus, pcia, id, okay))
     224                 :          0 :                         break;
     225                 :            :         }
     226                 :          1 :         return true;
     227                 :            : }

Generated by: LCOV version 1.14