[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