LCOV - code coverage report
Current view: top level - hdata - pcia.c (source / functions) Coverage Total Hit
Test: skiboot.info Lines: 81.3 % 107 87
Test Date: 2025-01-24 18:40:10 Functions: 100.0 % 5 5
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 2.0-1