[Skiboot] [PATCH 18/61] phys/P10: Use topology index to get phys mapping

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Jul 19 23:19:29 AEST 2021


This fixes multipchip rainier boot issue.

for Rainer:

chip0: ibm,primary-topology-index = < 0x0>;
chip1: ibm,primary-topology-index = < 0x4>;
chip2: ibm,primary-topology-index = < 0x8>;
chip3: ibm,primary-topology-index = < 0xc>;

for Denali:

node0:
chip0: ibm,primary-topology-index = < 0x0>;
chip1: ibm,primary-topology-index = < 0x1>;
chip2: ibm,primary-topology-index = < 0x2>;
chip3: ibm,primary-topology-index = < 0x3>;

node1:
chip0: ibm,primary-topology-index = < 0x4>;
chip1: ibm,primary-topology-index = < 0x5>;
chip2: ibm,primary-topology-index = < 0x6>;
chip3: ibm,primary-topology-index = < 0x7>;

Note that bmc_create_node() gets called very early in the boot process.
Hence we have to traverse through HDAT ntuple to get right topology index.

May be we can optimize pcid_to_topology_idx() function as its pretty
much duplicate of pcid_to_chip_id(). But for now lets keep it as
separate function.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
Signed-off-by: Ryan Grimm <grimm at linux.ibm.com>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 hdata/fsp.c             |  4 +++-
 hdata/hdata.h           |  1 +
 hdata/spira.c           | 28 ++++++++++++++++++++++++++++
 hw/phys-map.c           | 18 ++++++++++++++++--
 hw/test/phys-map-test.c |  7 ++++++-
 include/phys-map.h      |  3 +++
 6 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/hdata/fsp.c b/hdata/fsp.c
index 42f1121ab..30cda53f6 100644
--- a/hdata/fsp.c
+++ b/hdata/fsp.c
@@ -361,6 +361,7 @@ static void bmc_create_node(const struct HDIF_common_hdr *sp)
 	struct dt_node *lpcm, *lpc, *n;
 	u64 lpcm_base, lpcm_end;
 	uint32_t chip_id;
+	uint32_t topology_idx;
 	int size;
 
 	bmc_node = dt_new(dt_root, "bmc");
@@ -399,8 +400,9 @@ static void bmc_create_node(const struct HDIF_common_hdr *sp)
 	 * phys map offset
 	 */
 	chip_id = pcid_to_chip_id(be32_to_cpu(iopath->lpc.chip_id));
+	topology_idx = pcid_to_topology_idx(be32_to_cpu(iopath->lpc.chip_id));
 
-	phys_map_get(chip_id, LPC_BUS, 0, &lpcm_base, NULL);
+	__phys_map_get(topology_idx, chip_id, LPC_BUS, 0, &lpcm_base, NULL);
 	lpcm = dt_new_addr(dt_root, "lpcm-opb", lpcm_base);
 	assert(lpcm);
 
diff --git a/hdata/hdata.h b/hdata/hdata.h
index bae4eaa58..6aad82932 100644
--- a/hdata/hdata.h
+++ b/hdata/hdata.h
@@ -24,6 +24,7 @@ extern void vpd_data_parse(struct dt_node *node,
 
 extern struct dt_node *find_xscom_for_chip(uint32_t chip_id);
 extern uint32_t pcid_to_chip_id(uint32_t proc_chip_id);
+extern uint32_t pcid_to_topology_idx(uint32_t proc_chip_id);
 extern uint32_t get_xscom_id(const struct sppcrd_chip_info *cinfo);
 
 extern struct dt_node *add_core_common(struct dt_node *cpus,
diff --git a/hdata/spira.c b/hdata/spira.c
index 7d56f3f29..baa23751d 100644
--- a/hdata/spira.c
+++ b/hdata/spira.c
@@ -1418,6 +1418,34 @@ uint32_t pcid_to_chip_id(uint32_t proc_chip_id)
 	return (uint32_t)-1;
 }
 
+uint32_t pcid_to_topology_idx(uint32_t proc_chip_id)
+{
+	unsigned int i;
+	const void *hdif;
+
+	/* First, try the proc_chip ntuples for chip data */
+	for_each_ntuple_idx(&spira.ntuples.proc_chip, hdif, i,
+			    SPPCRD_HDIF_SIG) {
+		const struct sppcrd_chip_info *cinfo;
+
+		cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
+		if (!CHECK_SPPTR(cinfo)) {
+			prerror("XSCOM: Bad ChipID data %d\n", i);
+			continue;
+		}
+		if (proc_chip_id == be32_to_cpu(cinfo->proc_chip_id)) {
+			if (proc_gen <= proc_gen_p9)
+				return get_xscom_id(cinfo);
+			else
+				return ((u32)cinfo->topology_id_table[cinfo->primary_topology_loc]);
+		}
+	}
+
+	/* Not found, what to do ? Assert ? For now return a number
+	 * guaranteed to not exist
+	 */
+	return (uint32_t)-1;
+}
 /* Create '/ibm,opal/led' node */
 static void dt_init_led_node(void)
 {
diff --git a/hw/phys-map.c b/hw/phys-map.c
index 2c4d8e45f..194e4953d 100644
--- a/hw/phys-map.c
+++ b/hw/phys-map.c
@@ -277,7 +277,7 @@ static inline bool phys_map_entry_null(const struct phys_map_entry *e)
 /* This crashes skiboot on error as any bad calls here are almost
  *  certainly a developer error
  */
-void phys_map_get(uint64_t gcid, enum phys_map_type type,
+void __phys_map_get(uint64_t topology_idx, uint64_t gcid, enum phys_map_type type,
 		  int index, uint64_t *addr, uint64_t *size) {
 	const struct phys_map_entry *e;
 	uint64_t a;
@@ -302,7 +302,7 @@ void phys_map_get(uint64_t gcid, enum phys_map_type type,
 		break;
 	}
 	a = e->addr;
-	a += gcid << phys_map->chip_select_shift;
+	a += topology_idx << (phys_map->chip_select_shift);
 
 	if (addr)
 		*addr = a;
@@ -322,6 +322,20 @@ error:
 	assert(0);
 }
 
+void phys_map_get(uint64_t gcid, enum phys_map_type type,
+		  int index, uint64_t *addr, uint64_t *size)
+{
+	struct proc_chip *chip;
+	uint64_t topology_idx = gcid;
+
+	if (proc_gen >= proc_gen_p10) {
+		chip = get_chip(gcid);
+		topology_idx = chip->primary_topology;
+	}
+
+	return __phys_map_get(topology_idx, gcid, type, index, addr, size);
+}
+
 void phys_map_init(unsigned long pvr)
 {
 	const char *name = "unused";
diff --git a/hw/test/phys-map-test.c b/hw/test/phys-map-test.c
index 2aabdb826..aa5b7339a 100644
--- a/hw/test/phys-map-test.c
+++ b/hw/test/phys-map-test.c
@@ -79,6 +79,11 @@ static inline bool map_call_entry_null(const struct map_call_entry *t)
 /* Pick a chip ID, any ID. */
 #define FAKE_CHIP_ID 8
 
+struct proc_chip *get_chip(uint32_t chip_id __unused)
+{
+	return NULL;
+}
+
 static void check_map_call(void)
 {
 	uint64_t start, size, end;
@@ -98,7 +103,7 @@ static void check_map_call(void)
 
 	/* Loop over table entries ...  */
 	for (e = phys_map->table; !phys_map_entry_null(e); e++) {
-		phys_map_get(FAKE_CHIP_ID, e->type, e->index, &start, &size);
+		__phys_map_get(FAKE_CHIP_ID, FAKE_CHIP_ID, e->type, e->index, &start, &size);
 
 		/* Check for alignment */
 		if ((e->type != SYSTEM_MEM) && (e->type != RESV)) {
diff --git a/include/phys-map.h b/include/phys-map.h
index ae7a4aa55..97351a720 100644
--- a/include/phys-map.h
+++ b/include/phys-map.h
@@ -48,6 +48,9 @@ enum phys_map_type {
 extern void phys_map_get(uint64_t gcid, enum phys_map_type type,
 			 int index, uint64_t *addr, uint64_t *size);
 
+extern void __phys_map_get(uint64_t topology_idx, uint64_t gcid,
+			   enum phys_map_type type, int index, uint64_t *addr, uint64_t *size);
+
 extern void phys_map_init(unsigned long pvr);
 
 #endif /* __PHYS_MAP_H */
-- 
2.31.1



More information about the Skiboot mailing list