LCOV - code coverage report
Current view: top level - hdata - memory.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 153 421 36.3 %
Date: 2024-01-02 21:04:04 Functions: 13 19 68.4 %
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 <cpu.h>
       5                 :            : #include <device.h>
       6                 :            : #include <vpd.h>
       7                 :            : #include <ccan/str/str.h>
       8                 :            : #include <libfdt/libfdt.h>
       9                 :            : #include <mem_region.h>
      10                 :            : #include <types.h>
      11                 :            : #include <inttypes.h>
      12                 :            : #include <processor.h>
      13                 :            : 
      14                 :            : #include "spira.h"
      15                 :            : #include "hdata.h"
      16                 :            : 
      17                 :            : struct HDIF_ram_area_id {
      18                 :            :         __be16 id;
      19                 :            : #define RAM_AREA_INSTALLED      0x8000
      20                 :            : #define RAM_AREA_FUNCTIONAL     0x4000
      21                 :            :         __be16 flags;
      22                 :            :         __be32 dimm_id;
      23                 :            :         __be32 speed;
      24                 :            : } __packed;
      25                 :            : 
      26                 :            : struct HDIF_ram_area_size {
      27                 :            :         __be32 reserved1;
      28                 :            :         __be32 mb;
      29                 :            : } __packed;
      30                 :            : 
      31                 :            : struct HDIF_ms_area_address_range {
      32                 :            :         __be64 start;
      33                 :            :         __be64 end;
      34                 :            :         __be32 chip;
      35                 :            :         __be32 mirror_attr;
      36                 :            :         __be64 mirror_start;
      37                 :            :         __be32 controller_id;
      38                 :            :         __be32 phys_attr;
      39                 :            : } __packed;
      40                 :            : #define PHYS_ATTR_TYPE_MASK     0xff000000
      41                 :            : #define   PHYS_ATTR_TYPE_STD            0
      42                 :            : #define   PHYS_ATTR_TYPE_NVDIMM         1
      43                 :            : #define   PHYS_ATTR_TYPE_MRAM           2
      44                 :            : #define   PHYS_ATTR_TYPE_PCM            3
      45                 :            : 
      46                 :            : #define PHYS_ATTR_STATUS_MASK   0x00ff0000
      47                 :            : /*
      48                 :            :  * The values here are mutually exclusive. I have no idea why anyone
      49                 :            :  * decided encoding these are flags rather than sequential numbers was
      50                 :            :  * a good idea, but here we are.
      51                 :            :  */
      52                 :            : #define   PHYS_ATTR_STATUS_CANT_SAVE    0x01
      53                 :            : #define   PHYS_ATTR_STATUS_SAVE_FAILED  0x02
      54                 :            : #define   PHYS_ATTR_STATUS_SAVED        0x04
      55                 :            : #define   PHYS_ATTR_STATUS_NOT_SAVED    0x08
      56                 :            : #define   PHYS_ATTR_STATUS_ENCRYPTED    0x10
      57                 :            : #define   PHYS_ATTR_STATUS_ERR_DETECTED 0x40
      58                 :            : #define   PHYS_ATTR_STATUS_MEM_INVALID  0xff
      59                 :            : 
      60                 :            : /* Memory Controller ID for Nimbus P9 systems */
      61                 :            : #define MS_CONTROLLER_MCBIST_ID(id)     GETFIELD(PPC_BITMASK32(0, 1), id)
      62                 :            : #define MS_CONTROLLER_MCS_ID(id)        GETFIELD(PPC_BITMASK32(4, 7), id)
      63                 :            : #define MS_CONTROLLER_MCA_ID(id)        GETFIELD(PPC_BITMASK32(8, 15), id)
      64                 :            : 
      65                 :            : /* Memory Controller ID for P9 AXONE systems */
      66                 :            : #define MS_CONTROLLER_MC_ID(id)         GETFIELD(PPC_BITMASK32(0, 1), id)
      67                 :            : #define MS_CONTROLLER_MI_ID(id)         GETFIELD(PPC_BITMASK32(4, 7), id)
      68                 :            : #define MS_CONTROLLER_MCC_ID(id)        GETFIELD(PPC_BITMASK32(8, 15), id)
      69                 :            : #define MS_CONTROLLER_OMI_ID(id)        GETFIELD(PPC_BITMASK32(16, 31), id)
      70                 :            : 
      71                 :            : struct HDIF_ms_area_id {
      72                 :            :         __be16 id;
      73                 :            : #define MS_PTYPE_RISER_CARD     0x8000
      74                 :            : #define MS_PTYPE_MEM_CARD       0x4000
      75                 :            : #define MS_PTYPE_CEC_FRU        0x2000
      76                 :            : #define MS_PTYPE_HYBRID_CARD    0x1000
      77                 :            :         __be16 parent_type;
      78                 :            : #define MS_AREA_INSTALLED       0x8000
      79                 :            : #define MS_AREA_FUNCTIONAL      0x4000
      80                 :            : #define MS_AREA_SHARED          0x2000
      81                 :            :         __be16 flags;
      82                 :            :         __be16 share_id;
      83                 :            : } __packed;
      84                 :            : 
      85                 :            : 
      86                 :            : // FIXME: it should be 9, current HDATs are broken
      87                 :            : #define MSAREA_IDATA_MMIO_IDX 8
      88                 :            : struct HDIF_ms_area_ocmb_mmio {
      89                 :            :         __be64 range_start;
      90                 :            :         __be64 range_end;
      91                 :            :         __be32 controller_id;
      92                 :            :         __be32 proc_chip_id;
      93                 :            :         __be64 hbrt_id;
      94                 :            : #define OCMB_SCOM_8BYTE_ACCESS  PPC_BIT(0)
      95                 :            : #define OCMB_SCOM_4BYTE_ACCESS  PPC_BIT(1)
      96                 :            :         __be64 flags;
      97                 :            : } __packed;
      98                 :            : 
      99                 :          1 : static void append_chip_id(struct dt_node *mem, u32 id)
     100                 :            : {
     101                 :            :         struct dt_property *prop;
     102                 :            :         size_t len, i;
     103                 :            : 
     104                 :          1 :         prop = __dt_find_property(mem, "ibm,chip-id");
     105                 :          1 :         if (!prop)
     106                 :          1 :                 return;
     107                 :          1 :         len = prop->len >> 2;
     108                 :            : 
     109                 :            :         /* Check if it exists already */
     110                 :          1 :         for (i = 0; i < len; i++) {
     111                 :          1 :                 if (dt_property_get_cell(prop, i) == id)
     112                 :          1 :                         return;
     113                 :            :         }
     114                 :            : 
     115                 :            :         /* Add it to the list */
     116                 :          0 :         dt_resize_property(&prop, (len + 1) << 2);
     117                 :          0 :         dt_property_set_cell(prop, len, id);
     118                 :            : }
     119                 :            : 
     120                 :          0 : static void update_status(struct dt_node *mem, uint32_t status)
     121                 :            : {
     122                 :          0 :         switch (status) {
     123                 :          0 :         case PHYS_ATTR_STATUS_CANT_SAVE:
     124                 :          0 :                 if (!dt_find_property(mem, "save-trigged-unarmed"))
     125                 :          0 :                         dt_add_property(mem, "save-trigger-unarmed", NULL, 0);
     126                 :          0 :                 break;
     127                 :            : 
     128                 :          0 :         case PHYS_ATTR_STATUS_SAVE_FAILED:
     129                 :          0 :                 if (!dt_find_property(mem, "save-failed"))
     130                 :          0 :                         dt_add_property(mem, "save-failed", NULL, 0);
     131                 :            : 
     132                 :          0 :                 break;
     133                 :            : 
     134                 :          0 :         case PHYS_ATTR_STATUS_MEM_INVALID:
     135                 :          0 :                 if (dt_find_property(mem, "save-trigged-unarmed"))
     136                 :          0 :                         dt_add_property_string(mem, "status",
     137                 :            :                                 "disabled-memory-invalid");
     138                 :          0 :                 break;
     139                 :            :         }
     140                 :          0 : }
     141                 :            : 
     142                 :          2 : static bool add_address_range(struct dt_node *root,
     143                 :            :                               const struct HDIF_ms_area_id *id,
     144                 :            :                               const struct HDIF_ms_area_address_range *arange,
     145                 :            :                               uint32_t mem_type, uint32_t mem_status)
     146                 :            : {
     147                 :          2 :         const char *compat = NULL, *dev_type = NULL, *name = NULL;
     148                 :            :         struct dt_node *mem;
     149                 :            :         u32 chip_id;
     150                 :            :         u64 reg[2];
     151                 :            : 
     152                 :          2 :         chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip));
     153                 :            : 
     154                 :          2 :         prlog(PR_DEBUG, "  Range: 0x%016llx..0x%016llx "
     155                 :            :               "on Chip 0x%x mattr: 0x%x pattr: 0x%x status:0x%x\n",
     156                 :            :               (long long)be64_to_cpu(arange->start),
     157                 :            :               (long long)be64_to_cpu(arange->end),
     158                 :            :               chip_id, be32_to_cpu(arange->mirror_attr),
     159                 :            :               mem_type, mem_status);
     160                 :            : 
     161                 :            :         /* reg contains start and length */
     162                 :          2 :         reg[0] = cleanup_addr(be64_to_cpu(arange->start));
     163                 :          2 :         reg[1] = cleanup_addr(be64_to_cpu(arange->end)) - reg[0];
     164                 :            : 
     165                 :          2 :         switch (mem_type) {
     166                 :          2 :         case PHYS_ATTR_TYPE_STD:
     167                 :          2 :                 name = "memory";
     168                 :          2 :                 dev_type = "memory";
     169                 :          2 :                 break;
     170                 :            : 
     171                 :          0 :         case PHYS_ATTR_TYPE_NVDIMM:
     172                 :            :         case PHYS_ATTR_TYPE_MRAM:
     173                 :            :         case PHYS_ATTR_TYPE_PCM:
     174                 :            :                 /* fall through */
     175                 :          0 :                 name = "nvdimm";
     176                 :          0 :                 compat = "pmem-region";
     177                 :          0 :                 break;
     178                 :            : 
     179                 :            :         /*
     180                 :            :          * Future memory types could be volatile or non-volatile. Bail if don't
     181                 :            :          * recognise the type so we don't end up trashing data accidently.
     182                 :            :          */
     183                 :          0 :         default:
     184                 :          0 :                 return false;
     185                 :            :         }
     186                 :            : 
     187                 :          2 :         if (be16_to_cpu(id->flags) & MS_AREA_SHARED) {
     188                 :          2 :                 mem = dt_find_by_name_addr(dt_root, name, reg[0]);
     189                 :          2 :                 if (mem) {
     190                 :          1 :                         append_chip_id(mem, chip_id);
     191                 :          1 :                         if (mem_type == PHYS_ATTR_TYPE_NVDIMM)
     192                 :          0 :                                 update_status(mem, mem_status);
     193                 :          1 :                         return true;
     194                 :            :                 }
     195                 :            :         }
     196                 :            : 
     197                 :          1 :         mem = dt_new_addr(root, name, reg[0]);
     198                 :          1 :         if (compat)
     199                 :          0 :                 dt_add_property_string(mem, "compatible", compat);
     200                 :          1 :         if (dev_type)
     201                 :          1 :                 dt_add_property_string(mem, "device_type", dev_type);
     202                 :            : 
     203                 :            :         /* add in the nvdimm backup status flags */
     204                 :          1 :         if (mem_type == PHYS_ATTR_TYPE_NVDIMM)
     205                 :          0 :                 update_status(mem, mem_status);
     206                 :            : 
     207                 :            :         /* common properties */
     208                 :            : 
     209                 :          1 :         dt_add_property_u64s(mem, "reg", reg[0], reg[1]);
     210                 :          1 :         dt_add_property_cells(mem, "ibm,chip-id", chip_id);
     211                 :          1 :         return true;
     212                 :            : }
     213                 :            : 
     214                 :          2 : static u32 add_chip_id_to_ram_area(const struct HDIF_common_hdr *msarea,
     215                 :            :                                     struct dt_node *ram_area)
     216                 :            : {
     217                 :            :         const struct HDIF_array_hdr *arr;
     218                 :            :         const struct HDIF_ms_area_address_range *arange;
     219                 :            :         unsigned int size;
     220                 :            :         u32 chip_id;
     221                 :            : 
     222                 :            :         /* Safe to assume pointers are valid here. */
     223                 :          2 :         arr = HDIF_get_idata(msarea, 4, &size);
     224                 :          2 :         arange = (void *)arr + be32_to_cpu(arr->offset);
     225                 :          2 :         chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip));
     226                 :          2 :         dt_add_property_cells(ram_area, "ibm,chip-id", chip_id);
     227                 :            : 
     228                 :          2 :         return chip_id;
     229                 :            : }
     230                 :            : 
     231                 :          2 : static void add_bus_freq_to_ram_area(struct dt_node *ram_node, u32 chip_id)
     232                 :            : {
     233                 :            :         const struct sppcia_cpu_timebase *timebase;
     234                 :          2 :         bool got_pcia = false;
     235                 :            :         const void *pcia;
     236                 :            :         u64 freq;
     237                 :            :         u32 size;
     238                 :            : 
     239                 :          2 :         pcia = get_hdif(&spiras->ntuples.pcia, SPPCIA_HDIF_SIG);
     240                 :          2 :         if (!pcia) {
     241                 :          0 :                 prlog(PR_WARNING, "HDAT: Failed to add memory bus frequency "
     242                 :            :                       "as PCIA does not exist\n");
     243                 :          0 :                 return;
     244                 :            :         }
     245                 :            : 
     246                 :          2 :         for_each_pcia(spiras, pcia) {
     247                 :            :                 const struct sppcia_core_unique *id;
     248                 :            : 
     249                 :          2 :                 id = HDIF_get_idata(pcia, SPPCIA_IDATA_CORE_UNIQUE, &size);
     250                 :          2 :                 if (!id || size < sizeof(*id)) {
     251                 :          0 :                         prlog(PR_WARNING, "HDAT: Bad id size %u @ %p\n", size, id);
     252                 :          0 :                         return;
     253                 :            :                 }
     254                 :            : 
     255                 :          2 :                 if (chip_id == pcid_to_chip_id(be32_to_cpu(id->proc_chip_id))) {
     256                 :          2 :                         got_pcia = true;
     257                 :          2 :                         break;
     258                 :            :                 }
     259                 :            :         }
     260                 :            : 
     261                 :          2 :         if (got_pcia == false)
     262                 :          0 :                 return;
     263                 :            : 
     264                 :          2 :         timebase = HDIF_get_idata(pcia, SPPCIA_IDATA_TIMEBASE, &size);
     265                 :          2 :         if (!timebase || size < sizeof(*timebase)) {
     266                 :            :                 /**
     267                 :            :                  * @fwts-label HDATBadTimebaseSize
     268                 :            :                  * @fwts-advice HDAT described an invalid size for timebase,
     269                 :            :                  * which means there's a disagreement between HDAT and OPAL.
     270                 :            :                  * This is most certainly a firmware bug.
     271                 :            :                  */
     272                 :          0 :                 prlog(PR_ERR, "HDAT: Bad timebase size %u @ %p\n", size,
     273                 :            :                       timebase);
     274                 :          0 :                 return;
     275                 :            :         }
     276                 :            : 
     277                 :          2 :         freq = ((u64)be32_to_cpu(timebase->memory_bus_frequency)) * 1000000ul;
     278                 :          2 :         dt_add_property_u64(ram_node, "ibm,memory-bus-frequency", freq);
     279                 :            : }
     280                 :            : 
     281                 :          2 : static void add_size_to_ram_area(struct dt_node *ram_node,
     282                 :            :                                  const struct HDIF_common_hdr *ramarea)
     283                 :            : {
     284                 :            :         char    str[16];
     285                 :            :         const struct HDIF_ram_area_size *ram_area_sz;
     286                 :            : 
     287                 :            :         /* DIMM size */
     288                 :          2 :         ram_area_sz = HDIF_get_idata(ramarea, 3, NULL);
     289                 :          2 :         if (!CHECK_SPPTR(ram_area_sz))
     290                 :          0 :                 return;
     291                 :            : 
     292                 :          2 :         memset(str, 0, 16);
     293                 :          2 :         snprintf(str, 16, "%d", be32_to_cpu(ram_area_sz->mb));
     294                 :          2 :         dt_add_property_string(ram_node, "size", str);
     295                 :            : }
     296                 :            : 
     297                 :          2 : static void vpd_add_ram_area(const struct HDIF_common_hdr *msarea)
     298                 :            : {
     299                 :            :         unsigned int i;
     300                 :            :         unsigned int ram_sz;
     301                 :            :         const struct HDIF_common_hdr *ramarea;
     302                 :            :         const struct HDIF_child_ptr *ramptr;
     303                 :            :         const struct HDIF_ram_area_id *ram_id;
     304                 :            :         struct dt_node *ram_node;
     305                 :            :         u32 chip_id;
     306                 :            :         const void *vpd_blob;
     307                 :            : 
     308                 :          2 :         ramptr = HDIF_child_arr(msarea, 0);
     309                 :          2 :         if (!CHECK_SPPTR(ramptr)) {
     310                 :          0 :                 prerror("MS AREA: No RAM area at %p\n", msarea);
     311                 :          0 :                 return;
     312                 :            :         }
     313                 :            : 
     314                 :          4 :         for (i = 0; i < be32_to_cpu(ramptr->count); i++) {
     315                 :          2 :                 ramarea = HDIF_child(msarea, ramptr, i, "RAM   ");
     316                 :          2 :                 if (!CHECK_SPPTR(ramarea))
     317                 :          0 :                         continue;
     318                 :            : 
     319                 :          2 :                 ram_id = HDIF_get_idata(ramarea, 2, &ram_sz);
     320                 :          2 :                 if (!CHECK_SPPTR(ram_id))
     321                 :          0 :                         continue;
     322                 :            : 
     323                 :            :                 /* Don't add VPD for non-existent RAM */
     324                 :          2 :                 if (!(be16_to_cpu(ram_id->flags) & RAM_AREA_INSTALLED))
     325                 :          0 :                         continue;
     326                 :            : 
     327                 :          2 :                 ram_node = dt_add_vpd_node(ramarea, 0, 1);
     328                 :          2 :                 if (!ram_node)
     329                 :          0 :                         continue;
     330                 :            : 
     331                 :          2 :                 chip_id = add_chip_id_to_ram_area(msarea, ram_node);
     332                 :          2 :                 add_bus_freq_to_ram_area(ram_node, chip_id);
     333                 :            : 
     334                 :          2 :                 if (ram_sz >= offsetof(struct HDIF_ram_area_id, speed)) {
     335                 :          0 :                         dt_add_property_cells(ram_node, "frequency",
     336                 :            :                                               be32_to_cpu(ram_id->speed)*1000000);
     337                 :            :                 }
     338                 :            : 
     339                 :          2 :                 vpd_blob = HDIF_get_idata(ramarea, 1, &ram_sz);
     340                 :            : 
     341                 :            :                 /* DIMM size */
     342                 :          2 :                 add_size_to_ram_area(ram_node, ramarea);
     343                 :            :                 /*
     344                 :            :                  * For direct-attached memory we have a DDR "Serial
     345                 :            :                  * Presence Detection" blob rather than an IBM keyword
     346                 :            :                  * blob.
     347                 :            :                  */
     348                 :          2 :                 if (!vpd_valid(vpd_blob, ram_sz))
     349                 :          0 :                         dt_add_property(ram_node, "spd", vpd_blob, ram_sz);
     350                 :            :         }
     351                 :            : }
     352                 :            : 
     353                 :          0 : static void vpd_parse_spd(struct dt_node *dimm, const char *spd, u32 size)
     354                 :            : {
     355                 :            :         __be16 *vendor;
     356                 :            :         __be32 *sn;
     357                 :            : 
     358                 :            :         /* SPD is too small */
     359                 :          0 :         if (size < 512) {
     360                 :          0 :                 prlog(PR_WARNING, "MSVPD: Invalid SPD size. "
     361                 :            :                       "Expected 512 bytes, got %d\n", size);
     362                 :          0 :                 return;
     363                 :            :         }
     364                 :            : 
     365                 :            :         /* Supports DDR4 format pasing only */
     366                 :          0 :         if (spd[0x2] < 0xc) {
     367                 :          0 :                 prlog(PR_WARNING,
     368                 :            :                       "MSVPD: SPD format (%x) not supported\n", spd[0x2]);
     369                 :          0 :                 return;
     370                 :            :         }
     371                 :            : 
     372                 :          0 :         dt_add_property_string(dimm, "device_type", "memory-dimm-ddr4");
     373                 :            : 
     374                 :            :         /* DRAM device type */
     375                 :          0 :         dt_add_property_cells(dimm, "memory-id", spd[0x2]);
     376                 :            : 
     377                 :            :         /* Module revision code */
     378                 :          0 :         dt_add_property_cells(dimm, "product-version", spd[0x15d]);
     379                 :            : 
     380                 :            :         /* Serial number */
     381                 :          0 :         sn = (__be32 *)&spd[0x145];
     382                 :          0 :         dt_add_property_cells(dimm, "serial-number", be32_to_cpu(*sn));
     383                 :            : 
     384                 :            :         /* Part number */
     385                 :          0 :         dt_add_property_nstr(dimm, "part-number", &spd[0x149], 20);
     386                 :            : 
     387                 :            :         /* Module manufacturer ID */
     388                 :          0 :         vendor = (__be16 *)&spd[0x140];
     389                 :          0 :         dt_add_property_cells(dimm, "manufacturer-id", be16_to_cpu(*vendor));
     390                 :            : }
     391                 :            : 
     392                 :          0 : static void add_dimm_info(struct dt_node *parent,
     393                 :            :                               const struct HDIF_common_hdr *msarea)
     394                 :            : {
     395                 :            :         unsigned int i, size;
     396                 :            :         const struct HDIF_child_ptr *ramptr;
     397                 :            :         const struct HDIF_common_hdr *ramarea;
     398                 :            :         const struct spira_fru_id *fru_id;
     399                 :            :         const struct HDIF_ram_area_id *ram_id;
     400                 :            :         const struct HDIF_ram_area_size *ram_area_sz;
     401                 :            :         struct dt_node *dimm;
     402                 :            :         const void *vpd_blob;
     403                 :            : 
     404                 :          0 :         ramptr = HDIF_child_arr(msarea, 0);
     405                 :          0 :         if (!CHECK_SPPTR(ramptr)) {
     406                 :          0 :                 prerror("MS AREA: No RAM area at %p\n", msarea);
     407                 :          0 :                 return;
     408                 :            :         }
     409                 :            : 
     410                 :          0 :         for (i = 0; i < be32_to_cpu(ramptr->count); i++) {
     411                 :          0 :                 ramarea = HDIF_child(msarea, ramptr, i, "RAM   ");
     412                 :          0 :                 if (!CHECK_SPPTR(ramarea))
     413                 :          0 :                         continue;
     414                 :            : 
     415                 :          0 :                 fru_id = HDIF_get_idata(ramarea, 0, NULL);
     416                 :          0 :                 if (!fru_id)
     417                 :          0 :                         continue;
     418                 :            : 
     419                 :            :                 /* Use Resource ID to add dimm node */
     420                 :          0 :                 dimm = dt_find_by_name_addr(parent, "dimm",
     421                 :          0 :                                             be16_to_cpu(fru_id->rsrc_id));
     422                 :          0 :                 if (dimm)
     423                 :          0 :                         continue;
     424                 :          0 :                 dimm= dt_new_addr(parent, "dimm", be16_to_cpu(fru_id->rsrc_id));
     425                 :          0 :                 assert(dimm);
     426                 :          0 :                 dt_add_property_cells(dimm, "reg", be16_to_cpu(fru_id->rsrc_id));
     427                 :            : 
     428                 :            :                 /* Add location code */
     429                 :          0 :                 slca_vpd_add_loc_code(dimm, be16_to_cpu(fru_id->slca_index));
     430                 :            : 
     431                 :            :                 /* DIMM size */
     432                 :          0 :                 ram_area_sz = HDIF_get_idata(ramarea, 3, NULL);
     433                 :          0 :                 if (!CHECK_SPPTR(ram_area_sz))
     434                 :          0 :                         continue;
     435                 :          0 :                 dt_add_property_cells(dimm, "size", be32_to_cpu(ram_area_sz->mb));
     436                 :            : 
     437                 :            :                 /* DIMM state */
     438                 :          0 :                 ram_id = HDIF_get_idata(ramarea, 2, NULL);
     439                 :          0 :                 if (!CHECK_SPPTR(ram_id))
     440                 :          0 :                         continue;
     441                 :            : 
     442                 :          0 :                 if ((be16_to_cpu(ram_id->flags) & RAM_AREA_INSTALLED) &&
     443                 :          0 :                     (be16_to_cpu(ram_id->flags) & RAM_AREA_FUNCTIONAL))
     444                 :          0 :                         dt_add_property_string(dimm, "status", "okay");
     445                 :            :                 else
     446                 :          0 :                         dt_add_property_string(dimm, "status", "disabled");
     447                 :            : 
     448                 :          0 :                 vpd_blob = HDIF_get_idata(ramarea, 1, &size);
     449                 :          0 :                 if (!CHECK_SPPTR(vpd_blob))
     450                 :          0 :                         continue;
     451                 :          0 :                 if (vpd_valid(vpd_blob, size))
     452                 :          0 :                         vpd_data_parse(dimm, vpd_blob, size);
     453                 :            :                 else
     454                 :          0 :                         vpd_parse_spd(dimm, vpd_blob, size);
     455                 :            :         }
     456                 :            : }
     457                 :            : 
     458                 :          0 : static inline void dt_add_mem_reg_property(struct dt_node *node, u64 addr)
     459                 :            : {
     460                 :          0 :         dt_add_property_cells(node, "#address-cells", 1);
     461                 :          0 :         dt_add_property_cells(node, "#size-cells", 0);
     462                 :          0 :         dt_add_property_cells(node, "reg", addr);
     463                 :          0 : }
     464                 :            : 
     465                 :          0 : static void add_memory_controller_p9n(const struct HDIF_common_hdr *msarea,
     466                 :            :                                   const struct HDIF_ms_area_address_range *arange)
     467                 :            : {
     468                 :            :         uint32_t chip_id;
     469                 :            :         uint32_t controller_id, mcbist_id, mcs_id, mca_id;
     470                 :            :         struct dt_node *xscom, *mcbist, *mcs, *mca;
     471                 :            : 
     472                 :          0 :         chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip));
     473                 :          0 :         controller_id = be32_to_cpu(arange->controller_id);
     474                 :          0 :         xscom = find_xscom_for_chip(chip_id);
     475                 :          0 :         if (!xscom) {
     476                 :          0 :                 prlog(PR_WARNING,
     477                 :            :                       "MS AREA: Can't find XSCOM for chip %d\n", chip_id);
     478                 :          0 :                 return;
     479                 :            :         }
     480                 :            : 
     481                 :          0 :         mcbist_id = MS_CONTROLLER_MCBIST_ID(controller_id);
     482                 :          0 :         mcbist = dt_find_by_name_addr(xscom, "mcbist", mcbist_id);
     483                 :          0 :         if (!mcbist) {
     484                 :          0 :                 mcbist = dt_new_addr(xscom, "mcbist", mcbist_id);
     485                 :          0 :                 assert(mcbist);
     486                 :          0 :                 dt_add_property_cells(mcbist, "#address-cells", 1);
     487                 :          0 :                 dt_add_property_cells(mcbist, "#size-cells", 0);
     488                 :          0 :                 dt_add_property_cells(mcbist, "reg", mcbist_id, 0);
     489                 :            :         }
     490                 :            : 
     491                 :          0 :         mcs_id = MS_CONTROLLER_MCS_ID(controller_id);
     492                 :          0 :         mcs = dt_find_by_name_addr(mcbist, "mcs", mcs_id);
     493                 :          0 :         if (!mcs) {
     494                 :          0 :                 mcs = dt_new_addr(mcbist, "mcs", mcs_id);
     495                 :          0 :                 assert(mcs);
     496                 :          0 :                 dt_add_mem_reg_property(mcs, mcs_id);
     497                 :            :         }
     498                 :            : 
     499                 :          0 :         mca_id = MS_CONTROLLER_MCA_ID(controller_id);
     500                 :          0 :         mca = dt_find_by_name_addr(mcs, "mca", mca_id);
     501                 :          0 :         if (!mca) {
     502                 :          0 :                 mca = dt_new_addr(mcs, "mca", mca_id);
     503                 :          0 :                 assert(mca);
     504                 :          0 :                 dt_add_mem_reg_property(mca, mca_id);
     505                 :            :         }
     506                 :            : 
     507                 :          0 :         add_dimm_info(mca, msarea);
     508                 :            : }
     509                 :            : 
     510                 :          2 : static void add_memory_buffer_mmio(const struct HDIF_common_hdr *msarea)
     511                 :            : {
     512                 :            :         const struct HDIF_ms_area_ocmb_mmio *mmio;
     513                 :          2 :         uint64_t min_addr = ~0ull, hbrt_id = 0;
     514                 :            :         const struct HDIF_array_hdr *array;
     515                 :          2 :         unsigned int i, count, ranges = 0;
     516                 :            :         struct dt_node *membuf;
     517                 :            :         beint64_t *reg, *flags;
     518                 :            : 
     519                 :          2 :         if (proc_gen <= proc_gen_p9 && PVR_TYPE(mfspr(SPR_PVR)) != PVR_TYPE_P9P)
     520                 :          2 :                 return;
     521                 :            : 
     522                 :          0 :         if (be16_to_cpu(msarea->version) < 0x50) {
     523                 :          0 :                 prlog(PR_WARNING, "MS AREA: Inconsistent MSAREA version %x for P9P system",
     524                 :            :                         be16_to_cpu(msarea->version));
     525                 :          0 :                 return;
     526                 :            :         }
     527                 :            : 
     528                 :          0 :         array = HDIF_get_iarray(msarea, MSAREA_IDATA_MMIO_IDX, &count);
     529                 :          0 :         if (!array || count <= 0) {
     530                 :          0 :                 prerror("MS AREA: No OCMB MMIO array at MS Area %p\n", msarea);
     531                 :          0 :                 return;
     532                 :            :         }
     533                 :            : 
     534                 :          0 :         reg = zalloc(count * 2 * sizeof(*reg));
     535                 :          0 :         flags = zalloc(count * sizeof(*flags));
     536                 :            : 
     537                 :            :         /* grab the hbrt id from the first range. */
     538                 :          0 :         HDIF_iarray_for_each(array, i, mmio) {
     539                 :          0 :                 hbrt_id = be64_to_cpu(mmio->hbrt_id);
     540                 :          0 :                 break;
     541                 :            :         }
     542                 :            : 
     543                 :          0 :         prlog(PR_DEBUG, "Adding memory buffer MMIO ranges for %"PRIx64"\n",
     544                 :            :               hbrt_id);
     545                 :            : 
     546                 :          0 :         HDIF_iarray_for_each(array, i, mmio) {
     547                 :            :                 uint64_t start, end;
     548                 :            : 
     549                 :          0 :                 if (hbrt_id != be64_to_cpu(mmio->hbrt_id)) {
     550                 :          0 :                         prerror("HBRT ID mismatch!\n");
     551                 :          0 :                         continue;
     552                 :            :                 }
     553                 :            : 
     554                 :          0 :                 start = cleanup_addr(be64_to_cpu(mmio->range_start));
     555                 :          0 :                 end   = cleanup_addr(be64_to_cpu(mmio->range_end));
     556                 :          0 :                 if (start < min_addr)
     557                 :          0 :                         min_addr = start;
     558                 :            : 
     559                 :          0 :                 prlog(PR_DEBUG, "  %"PRIx64" - [%016"PRIx64"-%016"PRIx64")\n",
     560                 :            :                         hbrt_id, start, end);
     561                 :            : 
     562                 :          0 :                 reg[2 * ranges    ] = cpu_to_be64(start);
     563                 :          0 :                 reg[2 * ranges + 1] = cpu_to_be64(end - start + 1);
     564                 :          0 :                 flags[ranges] = mmio->flags; /* both are BE */
     565                 :          0 :                 ranges++;
     566                 :            :         }
     567                 :            : 
     568                 :          0 :         membuf = dt_find_by_name_addr(dt_root, "memory-buffer", min_addr);
     569                 :          0 :         if (membuf) {
     570                 :          0 :                 prerror("attempted to duplicate %s\n", membuf->name);
     571                 :          0 :                 goto out;
     572                 :            :         }
     573                 :            : 
     574                 :          0 :         membuf = dt_new_addr(dt_root, "memory-buffer", min_addr);
     575                 :          0 :         assert(membuf);
     576                 :            : 
     577                 :          0 :         dt_add_property_string(membuf, "compatible", "ibm,explorer");
     578                 :          0 :         dt_add_property_cells(membuf, "ibm,chip-id", hbrt_id);
     579                 :            : 
     580                 :            :         /*
     581                 :            :          * FIXME: We should probably be sorting the address ranges based
     582                 :            :          * on the starting address.
     583                 :            :          */
     584                 :          0 :         dt_add_property(membuf, "reg",   reg,   sizeof(*reg) * 2 * ranges);
     585                 :          0 :         dt_add_property(membuf, "flags", flags, sizeof(*flags)   * ranges);
     586                 :            : 
     587                 :          0 : out:
     588                 :          0 :         free(flags);
     589                 :          0 :         free(reg);
     590                 :            : }
     591                 :            : 
     592                 :          2 : static void add_memory_controller(const struct HDIF_common_hdr *msarea,
     593                 :            :                                   const struct HDIF_ms_area_address_range *arange)
     594                 :            : {
     595                 :          2 :         const uint32_t version = PVR_TYPE(mfspr(SPR_PVR));
     596                 :            :         /*
     597                 :            :          * Memory hierarchy may change between processor version. Presently
     598                 :            :          * it's only creating memory hierarchy for P9 (Nimbus) and P9P (Axone).
     599                 :            :          */
     600                 :            : 
     601                 :          2 :         if (version == PVR_TYPE_P9)
     602                 :          0 :                 return add_memory_controller_p9n(msarea, arange);
     603                 :          2 :         else if (version == PVR_TYPE_P9P)
     604                 :          0 :                 return; //return add_memory_controller_p9p(msarea, arange);
     605                 :            :         else
     606                 :          2 :                 return;
     607                 :            : }
     608                 :            : 
     609                 :          1 : static void get_msareas(struct dt_node *root,
     610                 :            :                         const struct HDIF_common_hdr *ms_vpd)
     611                 :            : {
     612                 :            :         unsigned int i;
     613                 :            :         const struct HDIF_child_ptr *msptr;
     614                 :            : 
     615                 :            :         /* First childptr refers to msareas. */
     616                 :          1 :         msptr = HDIF_child_arr(ms_vpd, MSVPD_CHILD_MS_AREAS);
     617                 :          1 :         if (!CHECK_SPPTR(msptr)) {
     618                 :          0 :                 prerror("MS VPD: no children at %p\n", ms_vpd);
     619                 :          0 :                 return;
     620                 :            :         }
     621                 :            : 
     622                 :          3 :         for (i = 0; i < be32_to_cpu(msptr->count); i++) {
     623                 :            :                 const struct HDIF_common_hdr *msarea;
     624                 :            :                 const struct HDIF_array_hdr *arr;
     625                 :            :                 const struct HDIF_ms_area_address_range *arange;
     626                 :            :                 const struct HDIF_ms_area_id *id;
     627                 :            :                 const void *fruid;
     628                 :            :                 unsigned int size, j, offset;
     629                 :            :                 u16 flags;
     630                 :            : 
     631                 :          2 :                 msarea = HDIF_child(ms_vpd, msptr, i, "MSAREA");
     632                 :          2 :                 if (!CHECK_SPPTR(msarea))
     633                 :          0 :                         return;
     634                 :            : 
     635                 :          2 :                 id = HDIF_get_idata(msarea, 2, &size);
     636                 :          2 :                 if (!CHECK_SPPTR(id))
     637                 :          0 :                         return;
     638                 :          2 :                 if (size < sizeof(*id)) {
     639                 :          0 :                         prerror("MS VPD: %p msarea #%i id size too small!\n",
     640                 :            :                                 ms_vpd, i);
     641                 :          0 :                         return;
     642                 :            :                 }
     643                 :            : 
     644                 :          2 :                 flags = be16_to_cpu(id->flags);
     645                 :          2 :                 prlog(PR_DEBUG, "MS VPD: %p, area %i: %s %s %s\n",
     646                 :            :                        ms_vpd, i,
     647                 :            :                        flags & MS_AREA_INSTALLED ?
     648                 :            :                        "installed" : "not installed",
     649                 :            :                        flags & MS_AREA_FUNCTIONAL ?
     650                 :            :                        "functional" : "not functional",
     651                 :            :                        flags & MS_AREA_SHARED ?
     652                 :            :                        "shared" : "not shared");
     653                 :            : 
     654                 :          2 :                 if ((flags & (MS_AREA_INSTALLED|MS_AREA_FUNCTIONAL))
     655                 :            :                     != (MS_AREA_INSTALLED|MS_AREA_FUNCTIONAL))
     656                 :          0 :                         continue;
     657                 :            : 
     658                 :          2 :                 arr = HDIF_get_idata(msarea, 4, &size);
     659                 :          2 :                 if (!CHECK_SPPTR(arr))
     660                 :          0 :                         continue;
     661                 :            : 
     662                 :          2 :                 if (size < sizeof(*arr)) {
     663                 :          0 :                         prerror("MS VPD: %p msarea #%i arr size too small!\n",
     664                 :            :                                 ms_vpd, i);
     665                 :          0 :                         return;
     666                 :            :                 }
     667                 :            : 
     668                 :          2 :                 offset = offsetof(struct HDIF_ms_area_address_range, mirror_start);
     669                 :          2 :                 if (be32_to_cpu(arr->eactsz) < offset) {
     670                 :          0 :                         prerror("MS VPD: %p msarea #%i arange size too small!\n",
     671                 :            :                                 ms_vpd, i);
     672                 :          0 :                         return;
     673                 :            :                 }
     674                 :            : 
     675                 :          2 :                 fruid = HDIF_get_idata(msarea, 0, &size);
     676                 :          2 :                 if (!CHECK_SPPTR(fruid))
     677                 :          0 :                         return;
     678                 :            : 
     679                 :            :                 /* Add Raiser card VPD */
     680                 :          2 :                 if (be16_to_cpu(id->parent_type) & MS_PTYPE_RISER_CARD)
     681                 :          0 :                         dt_add_vpd_node(msarea, 0, 1);
     682                 :            : 
     683                 :            :                 /* Add RAM Area VPD */
     684                 :          2 :                 vpd_add_ram_area(msarea);
     685                 :            : 
     686                 :          2 :                 add_memory_buffer_mmio(msarea);
     687                 :            : 
     688                 :            :                 /* This offset is from the arr, not the header! */
     689                 :          2 :                 arange = (void *)arr + be32_to_cpu(arr->offset);
     690                 :          4 :                 for (j = 0; j < be32_to_cpu(arr->ecnt); j++) {
     691                 :          2 :                         uint32_t type = 0, status = 0;
     692                 :            : 
     693                 :            :                         /*
     694                 :            :                          * Check that the required fields are present in this
     695                 :            :                          * version of the HDAT structure.
     696                 :            :                          */
     697                 :          2 :                         offset = offsetof(struct HDIF_ms_area_address_range, controller_id);
     698                 :          2 :                         if (be32_to_cpu(arr->eactsz) >= offset)
     699                 :          2 :                                 add_memory_controller(msarea, arange);
     700                 :            : 
     701                 :          2 :                         offset = offsetof(struct HDIF_ms_area_address_range, phys_attr);
     702                 :          2 :                         if (be32_to_cpu(arr->eactsz) >= offset) {
     703                 :          0 :                                 uint32_t attr = be32_to_cpu(arange->phys_attr);
     704                 :            : 
     705                 :          0 :                                 type = GETFIELD(PHYS_ATTR_TYPE_MASK, attr);
     706                 :          0 :                                 status = GETFIELD(PHYS_ATTR_STATUS_MASK, attr);
     707                 :            :                         }
     708                 :            : 
     709                 :          2 :                         if (!add_address_range(root, id, arange, type, status))
     710                 :          0 :                                 prerror("Unable to use memory range %d from MSAREA %d\n", j, i);
     711                 :            : 
     712                 :          2 :                         arange = (void *)arange + be32_to_cpu(arr->esize);
     713                 :            :                 }
     714                 :            :         }
     715                 :            : }
     716                 :            : 
     717                 :            : static struct dt_node *dt_hb_reserves;
     718                 :            : 
     719                 :          0 : static struct dt_node *add_hb_reserve_node(const char *name, u64 start, u64 end)
     720                 :            : {
     721                 :            :         /* label size + "ibm," + NULL */
     722                 :          0 :         char node_name[HB_RESERVE_MEM_LABEL_SIZE + 5] = { 0 };
     723                 :            :         struct dt_node *node, *hb;
     724                 :            : 
     725                 :          0 :         if (!dt_hb_reserves) {
     726                 :          0 :                 hb = dt_new_check(dt_root, "ibm,hostboot");
     727                 :          0 :                 dt_add_property_cells(hb, "#size-cells", 2);
     728                 :          0 :                 dt_add_property_cells(hb, "#address-cells", 2);
     729                 :            : 
     730                 :          0 :                 dt_hb_reserves = dt_new_check(hb, "reserved-memory");
     731                 :          0 :                 dt_add_property(dt_hb_reserves, "ranges", NULL, 0);
     732                 :          0 :                 dt_add_property_cells(dt_hb_reserves, "#size-cells", 2);
     733                 :          0 :                 dt_add_property_cells(dt_hb_reserves, "#address-cells", 2);
     734                 :            :         }
     735                 :            : 
     736                 :            :         /* Add "ibm," to reserved node name */
     737                 :          0 :         if (strncasecmp(name, "ibm", 3))
     738                 :          0 :                 snprintf(node_name, 5, "ibm,");
     739                 :          0 :         strcat(node_name, name);
     740                 :            : 
     741                 :          0 :         node = dt_new_addr(dt_hb_reserves, node_name, start);
     742                 :          0 :         if (!node) {
     743                 :          0 :                 prerror("Unable to create node for %s@%llx\n",
     744                 :            :                         node_name, (unsigned long long) start);
     745                 :          0 :                 return NULL;
     746                 :            :         }
     747                 :            : 
     748                 :          0 :         dt_add_property_u64s(node, "reg", start, end - start + 1);
     749                 :            : 
     750                 :          0 :         return node;
     751                 :            : }
     752                 :            : 
     753                 :          1 : static void get_hb_reserved_mem(struct HDIF_common_hdr *ms_vpd)
     754                 :            : {
     755                 :            :         const struct msvpd_hb_reserved_mem *hb_resv_mem;
     756                 :            :         u64 start_addr, end_addr, label_size;
     757                 :            :         struct dt_node *node;
     758                 :            :         int count, i;
     759                 :            :         char label[HB_RESERVE_MEM_LABEL_SIZE + 1];
     760                 :            : 
     761                 :            :         /*
     762                 :            :          * XXX: Reservation names only exist on P9 and on P7/8 we get the
     763                 :            :          *      reserved ranges through the hostboot mini-FDT instead.
     764                 :            :          */
     765                 :          1 :         if (proc_gen < proc_gen_p9)
     766                 :          1 :                 return;
     767                 :            : 
     768                 :          0 :         count = HDIF_get_iarray_size(ms_vpd, MSVPD_IDATA_HB_RESERVED_MEM);
     769                 :          0 :         if (count <= 0) {
     770                 :          0 :                 prerror("MS VPD: No hostboot reserved memory found\n");
     771                 :          0 :                 return;
     772                 :            :         }
     773                 :            : 
     774                 :          0 :         for (i = 0; i < count; i++) {
     775                 :          0 :                 hb_resv_mem = HDIF_get_iarray_item(ms_vpd,
     776                 :            :                                                    MSVPD_IDATA_HB_RESERVED_MEM,
     777                 :            :                                                    i, NULL);
     778                 :          0 :                 if (!CHECK_SPPTR(hb_resv_mem))
     779                 :          0 :                         continue;
     780                 :            : 
     781                 :          0 :                 label_size = be32_to_cpu(hb_resv_mem->label_size);
     782                 :          0 :                 start_addr = be64_to_cpu(hb_resv_mem->start_addr);
     783                 :          0 :                 end_addr = be64_to_cpu(hb_resv_mem->end_addr);
     784                 :            : 
     785                 :            :                 /* Zero length regions are a normal, but should be ignored */
     786                 :          0 :                 if (start_addr - end_addr == 0) {
     787                 :          0 :                         prlog(PR_DEBUG, "MEM: Ignoring zero length range\n");
     788                 :          0 :                         continue;
     789                 :            :                 }
     790                 :            : 
     791                 :            :                 /*
     792                 :            :                  * Workaround broken HDAT reserve regions which are
     793                 :            :                  * bigger than 512MB
     794                 :            :                  */
     795                 :          0 :                 if ((end_addr - start_addr) > 0x20000000) {
     796                 :          0 :                         prlog(PR_ERR, "MEM: Ignoring Bad HDAT reserve: too big\n");
     797                 :          0 :                         continue;
     798                 :            :                 }
     799                 :            : 
     800                 :            :                 /* remove the HRMOR bypass bit */
     801                 :          0 :                 start_addr &= ~HRMOR_BIT;
     802                 :          0 :                 end_addr &= ~HRMOR_BIT;
     803                 :          0 :                 if (label_size > HB_RESERVE_MEM_LABEL_SIZE)
     804                 :          0 :                         label_size = HB_RESERVE_MEM_LABEL_SIZE;
     805                 :            : 
     806                 :          0 :                 memset(label, 0, HB_RESERVE_MEM_LABEL_SIZE + 1);
     807                 :          0 :                 memcpy(label, hb_resv_mem->label, label_size);
     808                 :          0 :                 label[label_size] = '\0';
     809                 :            : 
     810                 :            :                 /* Unnamed reservations are always broken. Ignore them. */
     811                 :          0 :                 if (strlen(label) == 0)
     812                 :          0 :                         continue;
     813                 :            : 
     814                 :          0 :                 prlog(PR_DEBUG, "MEM: Reserve '%s' %#" PRIx64 "-%#" PRIx64 " (type/inst=0x%08x)\n",
     815                 :            :                       label, start_addr, end_addr, be32_to_cpu(hb_resv_mem->type_instance));
     816                 :            : 
     817                 :          0 :                 node = add_hb_reserve_node(label, start_addr, end_addr);
     818                 :          0 :                 if (!node) {
     819                 :          0 :                         prerror("unable to add node?\n");
     820                 :          0 :                         continue;
     821                 :            :                 }
     822                 :            : 
     823                 :            :                 /* the three low bytes of type_instance is the instance data */
     824                 :          0 :                 dt_add_property_cells(node, "ibm,prd-instance",
     825                 :            :                         (be32_to_cpu(hb_resv_mem->type_instance) & 0xffffff));
     826                 :            : 
     827                 :            :                 /*
     828                 :            :                  * Most reservations are used by HBRT itself so we should leave
     829                 :            :                  * the label as-is. The exception is hbrt-code-image which is
     830                 :            :                  * used by opal-prd to locate the HBRT image. Older versions
     831                 :            :                  * of opal-prd expect this to be "ibm,hbrt-code-image" so make
     832                 :            :                  * sure the prefix is there.
     833                 :            :                  */
     834                 :          0 :                 if (!strcmp(label, "hbrt-code-image"))
     835                 :          0 :                         strcpy(label, "ibm,hbrt-code-image");
     836                 :          0 :                 dt_add_property_string(node, "ibm,prd-label", label);
     837                 :            :         }
     838                 :            : }
     839                 :            : 
     840                 :          1 : static void parse_trace_reservations(struct HDIF_common_hdr *ms_vpd)
     841                 :            : {
     842                 :            :         unsigned int size;
     843                 :            :         int count, i;
     844                 :            : 
     845                 :            :         /*
     846                 :            :          * The trace arrays are only setup when hostboot is explicitly
     847                 :            :          * configured to enable them. We need to check and gracefully handle
     848                 :            :          * when they're not present.
     849                 :            :          */
     850                 :            : 
     851                 :          1 :         if (!HDIF_get_idata(ms_vpd, MSVPD_IDATA_TRACE_AREAS, &size) || !size) {
     852                 :          0 :                 prlog(PR_DEBUG, "MS VPD: No trace areas found\n");
     853                 :          1 :                 return;
     854                 :            :         }
     855                 :            : 
     856                 :          1 :         count = HDIF_get_iarray_size(ms_vpd, MSVPD_IDATA_TRACE_AREAS);
     857                 :          1 :         if (count <= 0) {
     858                 :          1 :                 prlog(PR_DEBUG, "MS VPD: No trace areas found\n");
     859                 :          1 :                 return;
     860                 :            :         }
     861                 :            : 
     862                 :          0 :         prlog(PR_INFO, "MS VPD: Found %d trace areas\n", count);
     863                 :            : 
     864                 :          0 :         for (i = 0; i < count; i++) {
     865                 :            :                 const struct msvpd_trace *trace_area;
     866                 :            :                 struct dt_node *node;
     867                 :            :                 u64 start, end;
     868                 :            : 
     869                 :          0 :                 trace_area = HDIF_get_iarray_item(ms_vpd,
     870                 :            :                                 MSVPD_IDATA_TRACE_AREAS, i, &size);
     871                 :            : 
     872                 :          0 :                 if (!trace_area)
     873                 :          0 :                         return; /* shouldn't happen */
     874                 :            : 
     875                 :          0 :                 start = be64_to_cpu(trace_area->start) & ~HRMOR_BIT;
     876                 :          0 :                 end = be64_to_cpu(trace_area->end) & ~HRMOR_BIT;
     877                 :            : 
     878                 :          0 :                 prlog(PR_INFO,
     879                 :            :                         "MS VPD: Trace area: 0x%.16"PRIx64"-0x%.16"PRIx64"\n",
     880                 :            :                         start, end);
     881                 :            : 
     882                 :          0 :                 node = add_hb_reserve_node("trace-area", start, end);
     883                 :          0 :                 if (!node) {
     884                 :          0 :                         prerror("MEM: Unable to reserve trace area %p-%p\n",
     885                 :            :                                 (void *) start, (void *) end);
     886                 :          0 :                         continue;
     887                 :            :                 }
     888                 :            : 
     889                 :          0 :                 dt_add_property(node, "no-map", NULL, 0);
     890                 :            :         }
     891                 :            : }
     892                 :            : 
     893                 :          1 : static bool __memory_parse(struct dt_node *root)
     894                 :            : {
     895                 :            :         struct HDIF_common_hdr *ms_vpd;
     896                 :            :         const struct msvpd_ms_addr_config *msac;
     897                 :            :         const struct msvpd_total_config_ms *tcms;
     898                 :            :         unsigned int size;
     899                 :            : 
     900                 :          1 :         ms_vpd = get_hdif(&spiras->ntuples.ms_vpd, MSVPD_HDIF_SIG);
     901                 :          1 :         if (!ms_vpd) {
     902                 :          0 :                 prerror("MS VPD: invalid\n");
     903                 :          0 :                 op_display(OP_FATAL, OP_MOD_MEM, 0x0000);
     904                 :          0 :                 return false;
     905                 :            :         }
     906                 :          1 :         if (be32_to_cpu(spiras->ntuples.ms_vpd.act_len) < sizeof(*ms_vpd)) {
     907                 :          0 :                 prerror("MS VPD: invalid size %u\n",
     908                 :            :                         be32_to_cpu(spiras->ntuples.ms_vpd.act_len));
     909                 :          0 :                 op_display(OP_FATAL, OP_MOD_MEM, 0x0001);
     910                 :          0 :                 return false;
     911                 :            :         }
     912                 :            : 
     913                 :          1 :         prlog(PR_DEBUG, "MS VPD: is at %p\n", ms_vpd);
     914                 :            : 
     915                 :          1 :         msac = HDIF_get_idata(ms_vpd, MSVPD_IDATA_MS_ADDR_CONFIG, &size);
     916                 :          1 :         if (!CHECK_SPPTR(msac) ||
     917                 :          1 :             size < offsetof(struct msvpd_ms_addr_config, max_possible_ms_address)) {
     918                 :          0 :                 prerror("MS VPD: bad msac size %u @ %p\n", size, msac);
     919                 :          0 :                 op_display(OP_FATAL, OP_MOD_MEM, 0x0002);
     920                 :          0 :                 return false;
     921                 :            :         }
     922                 :          1 :         prlog(PR_DEBUG, "MS VPD: MSAC is at %p\n", msac);
     923                 :            : 
     924                 :          1 :         dt_add_property_u64(dt_root, DT_PRIVATE "maxmem",
     925                 :          1 :                             be64_to_cpu(msac->max_configured_ms_address));
     926                 :            : 
     927                 :          1 :         tcms = HDIF_get_idata(ms_vpd, MSVPD_IDATA_TOTAL_CONFIG_MS, &size);
     928                 :          1 :         if (!CHECK_SPPTR(tcms) || size < sizeof(*tcms)) {
     929                 :          0 :                 prerror("MS VPD: Bad tcms size %u @ %p\n", size, tcms);
     930                 :          0 :                 op_display(OP_FATAL, OP_MOD_MEM, 0x0003);
     931                 :          0 :                 return false;
     932                 :            :         }
     933                 :          1 :         prlog(PR_DEBUG, "MS VPD: TCMS is at %p\n", tcms);
     934                 :            : 
     935                 :          1 :         prlog(PR_DEBUG, "MS VPD: Maximum configured address: 0x%llx\n",
     936                 :            :               (long long)be64_to_cpu(msac->max_configured_ms_address));
     937                 :          1 :         prlog(PR_DEBUG, "MS VPD: Maximum possible address: 0x%llx\n",
     938                 :            :               (long long)be64_to_cpu(msac->max_possible_ms_address));
     939                 :            : 
     940                 :          1 :         get_msareas(root, ms_vpd);
     941                 :            : 
     942                 :          1 :         get_hb_reserved_mem(ms_vpd);
     943                 :            : 
     944                 :          1 :         parse_trace_reservations(ms_vpd);
     945                 :            : 
     946                 :          1 :         prlog(PR_INFO, "MS VPD: Total MB of RAM: 0x%llx\n",
     947                 :            :                (long long)be64_to_cpu(tcms->total_in_mb));
     948                 :            : 
     949                 :          1 :         return true;
     950                 :            : }
     951                 :            : 
     952                 :          1 : void memory_parse(void)
     953                 :            : {
     954                 :          1 :         if (!__memory_parse(dt_root)) {
     955                 :          0 :                 prerror("MS VPD: Failed memory init !\n");
     956                 :          0 :                 abort();
     957                 :            :         }
     958                 :          1 : }

Generated by: LCOV version 1.14