[Pdbg] [PATCH 04/18] libpdbg: Introduce p10 FAPI targets and address translation
Amitay Isaacs
amitay at ozlabs.org
Thu Sep 24 14:42:22 AEST 2020
From: Alistair Popple <alistair at popple.id.au>
Signed-off-by: Alistair Popple <alistair at popple.id.au>
---
Makefile.am | 2 +
libpdbg/hwunit.h | 14 +
libpdbg/p10_fapi_targets.c | 583 +++++++++++++++++++++++++++++++++++++
libpdbg/p10_scom_addr.h | 133 +++++++++
4 files changed, 732 insertions(+)
create mode 100644 libpdbg/p10_fapi_targets.c
create mode 100644 libpdbg/p10_scom_addr.h
diff --git a/Makefile.am b/Makefile.am
index d4f7dc1..779c52c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -180,6 +180,8 @@ libpdbg_la_SOURCES = \
libpdbg/p9chip.c \
libpdbg/p9_fapi_targets.c \
libpdbg/p9_scom_addr.h \
+ libpdbg/p10_fapi_targets.c \
+ libpdbg/p10_scom_addr.h \
libpdbg/sbefifo.c \
libpdbg/sprs.h \
libpdbg/target.c \
diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h
index ee825bb..52fdaf0 100644
--- a/libpdbg/hwunit.h
+++ b/libpdbg/hwunit.h
@@ -306,4 +306,18 @@ struct capp {
};
#define target_to_capp(x) container_of(x, struct capp, target)
+struct omi {
+ struct pdbg_target target;
+};
+#define target_to_omi(x) container_of(x, struct omi, target)
+
+struct omic {
+ struct pdbg_target target;
+};
+#define target_to_omic(x) container_of(x, struct omic, target)
+
+struct mcc {
+ struct pdbg_target target;
+};
+#define target_to_mcc(x) container_of(x, struct mcc, target)
#endif /* __HWUNIT_H */
diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c
new file mode 100644
index 0000000..76299f5
--- /dev/null
+++ b/libpdbg/p10_fapi_targets.c
@@ -0,0 +1,583 @@
+/* Copyright 2020 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "hwunit.h"
+#include "bitutils.h"
+#include "p10_scom_addr.h"
+
+#define t(x) (&(x)->target)
+
+static uint64_t p10_eq_translate(struct eq *eq, uint64_t addr)
+{
+ addr = set_chiplet_id(addr, EQ0_CHIPLET_ID + pdbg_target_index(t(eq)));
+
+ return addr;
+}
+
+struct eq p10_eq = {
+ .target = {
+ .name = "POWER10 eq",
+ .compatible = "ibm,power10-eq",
+ .class = "eq",
+ .translate = translate_cast(p10_eq_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_eq);
+
+#define NUM_CORES_PER_EQ 4
+static uint64_t p10_core_translate(struct core *c, uint64_t addr)
+{
+ int region = 0;
+ int chip_unitnum = pdbg_target_index(t(c));
+
+ switch(chip_unitnum % NUM_CORES_PER_EQ) {
+ case 0:
+ region = 8;
+ break;
+ case 1:
+ region = 4;
+ break;
+ case 2:
+ region = 2;
+ break;
+ case 3:
+ region = 1;
+ break;
+ }
+ addr = set_chiplet_id(addr, EQ0_CHIPLET_ID + pdbg_target_index(t(c)) / 4);
+ addr &= 0xFFFFFFFFFFFF0FFFULL;
+ addr |= ((region & 0xF) << 12);
+
+ return addr;
+}
+
+struct core p10_core = {
+ .target = {
+ .name = "POWER10 core",
+ .compatible = "ibm,power10-core",
+ .class = "core",
+ .translate = translate_cast(p10_core_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_core);
+
+static uint64_t p10_pec_translate(struct pec *pec, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(pec));
+
+ if (get_chiplet_id(addr) >= N0_CHIPLET_ID &&
+ get_chiplet_id(addr) <= N1_CHIPLET_ID)
+ return set_chiplet_id(addr,
+ chip_unitnum ? N0_CHIPLET_ID : N1_CHIPLET_ID );
+ else
+ return set_chiplet_id(addr, PCI0_CHIPLET_ID + pdbg_target_index(t(pec)));
+}
+
+struct pec p10_pec = {
+ .target = {
+ .name = "POWER10 pec",
+ .compatible = "ibm,power10-pec",
+ .class = "pec",
+ .translate = translate_cast(p10_pec_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_pec);
+
+static uint64_t p10_phb_translate(struct phb *phb, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(phb));
+
+ if (get_chiplet_id(addr) >= N0_CHIPLET_ID && get_chiplet_id(addr) <= N1_CHIPLET_ID) {
+ addr = set_chiplet_id(addr, chip_unitnum / 3 ? N0_CHIPLET_ID : N1_CHIPLET_ID);
+ return set_sat_id(addr, 1 + chip_unitnum % 3);
+ } else {
+ addr = set_chiplet_id(addr, chip_unitnum / 3 + PCI0_CHIPLET_ID);
+ if (get_ring_id(addr) == 2) {
+ if (get_sat_id(addr) >= 1 && get_sat_id(addr) <= 3)
+ return set_sat_id(addr, 1 + chip_unitnum % 3);
+ else
+ return set_sat_id(addr, 4 + chip_unitnum % 3);
+ }
+ }
+
+ /* We'll never get here due to the assert but gcc complains */
+ return addr;
+}
+
+struct phb p10_phb = {
+ .target = {
+ .name = "POWER10 phb",
+ .compatible = "ibm,power10-phb",
+ .class = "phb",
+ .translate = translate_cast(p10_phb_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_phb);
+
+static uint64_t p10_nmmu_translate(struct nmmu *nmmu, uint64_t addr)
+{
+ return set_chiplet_id(addr, pdbg_target_index(t(nmmu)) + N0_CHIPLET_ID);
+}
+
+struct nmmu p10_nmmu = {
+ .target = {
+ .name = "POWER10 nmmu",
+ .compatible = "ibm,power10-nmmu",
+ .class = "nmmu",
+ .translate = translate_cast(p10_nmmu_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_nmmu);
+
+static uint64_t p10_iohs_translate(struct iohs *iohs, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(iohs));
+
+ if (get_chiplet_id(addr) >= AXON0_CHIPLET_ID &&
+ get_chiplet_id(addr) <= AXON7_CHIPLET_ID)
+ addr = set_chiplet_id(addr, AXON0_CHIPLET_ID + chip_unitnum);
+ else if (get_chiplet_id(addr) >= PAU0_CHIPLET_ID &&
+ get_chiplet_id(addr) <= PAU3_CHIPLET_ID) {
+ addr = set_chiplet_id(addr, chip_unitnum/2 + PAU0_CHIPLET_ID);
+ } else
+ /* We should bail here with an assert but it makes testing hard and we
+ * should never hit it anyway as all code will have been validated
+ * through the EKB CI process (LOL). */
+ assert(1);
+
+ if (get_chiplet_id(addr) >= PAU0_CHIPLET_ID &&
+ get_chiplet_id(addr) <= PAU3_CHIPLET_ID) {
+ if (chip_unitnum % 2)
+ addr = set_io_group_addr(addr, 0x1);
+ else
+ addr = set_io_group_addr(addr, 0x0);
+ }
+
+ return addr;
+}
+
+struct iohs p10_iohs = {
+ .target = {
+ .name = "POWER10 iohs",
+ .compatible = "ibm,power10-iohs",
+ .class = "iohs",
+ .translate = translate_cast(p10_iohs_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_iohs);
+
+/* We take a struct pdbg_target and avoid the casting here as the translation is
+ * the same for both target types. */
+static uint64_t p10_mimc_translate(struct pdbg_target *mimc, uint64_t addr)
+{
+ return set_chiplet_id(addr, pdbg_target_index(mimc) + MC0_CHIPLET_ID);
+}
+
+struct mi p10_mi = {
+ .target = {
+ .name = "POWER10 mi",
+ .compatible = "ibm,power10-mi",
+ .class = "mi",
+ .translate = p10_mimc_translate,
+ },
+};
+DECLARE_HW_UNIT(p10_mi);
+
+struct mc p10_mc = {
+ .target = {
+ .name = "POWER10 mc",
+ .compatible = "ibm,power10-mc",
+ .class = "mc",
+ .translate = p10_mimc_translate,
+ },
+};
+DECLARE_HW_UNIT(p10_mc);
+
+static uint64_t p10_mcc_translate(struct mcc *mcc, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(mcc));
+ uint8_t offset = get_sat_offset(addr);
+
+ addr = set_chiplet_id(addr, chip_unitnum/2 + MC0_CHIPLET_ID);
+ if (chip_unitnum % 2) {
+ switch (get_sat_id(addr)) {
+ case 0x4:
+ addr = set_sat_id(addr, 0x5);
+ break;
+ case 0x8:
+ addr = set_sat_id(addr, 0x9);
+ break;
+ case 0x0:
+ if (offset >= 0x22 && offset <= 0x2b)
+ addr = set_sat_offset(addr, offset + 0x10);
+ break;
+ case 0xd:
+ if (offset >= 0x00 && offset <= 0x1f)
+ addr = set_sat_offset(addr, offset + 0x20);
+ break;
+ }
+ } else {
+ switch (get_sat_id(addr)) {
+ case 0x5:
+ addr = set_sat_id(addr, 0x4);
+ break;
+ case 0x9:
+ addr = set_sat_id(addr, 0x8);
+ break;
+ case 0x0:
+ if (offset >= 0x32 && offset <= 0x3b)
+ addr = set_sat_offset(addr, offset - 0x10);
+ break;
+ case 0xd:
+ if (offset >= 0x20 && offset <= 0x3f)
+ addr = set_sat_offset(addr, offset - 0x20);
+ break;
+ }
+ }
+
+ return addr;
+}
+
+struct mcc p10_mcc = {
+ .target = {
+ .name = "POWER10 mcc",
+ .compatible = "ibm,power10-mcc",
+ .class = "mcc",
+ .translate = translate_cast(p10_mcc_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_mcc);
+
+static uint64_t p10_omic_translate(struct omic *omic, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(omic));
+ int chiplet_id = get_chiplet_id(addr);
+
+ if (chiplet_id >= PAU0_CHIPLET_ID && chiplet_id <= PAU3_CHIPLET_ID) {
+ if (chip_unitnum == 0 || chip_unitnum == 1)
+ addr = set_chiplet_id(addr, PAU0_CHIPLET_ID);
+ else if (chip_unitnum == 2 || chip_unitnum == 3)
+ addr = set_chiplet_id(addr, PAU2_CHIPLET_ID);
+ else if (chip_unitnum == 4 || chip_unitnum == 5)
+ addr = set_chiplet_id(addr, PAU1_CHIPLET_ID);
+ else if (chip_unitnum == 6 || chip_unitnum == 7)
+ addr = set_chiplet_id(addr, PAU3_CHIPLET_ID);
+ else
+ assert(0);
+
+ if (chip_unitnum % 2)
+ addr = set_io_group_addr(addr, 0x3);
+ else
+ addr = set_io_group_addr(addr, 0x2);
+ } else {
+ addr = set_chiplet_id(addr, chip_unitnum/2 + MC0_CHIPLET_ID);
+
+ if (chip_unitnum % 2)
+ addr = set_ring_id(addr, 0x6);
+ else
+ addr = set_ring_id(addr, 0x5);
+ }
+
+ return addr;
+}
+
+static struct omic p10_omic = {
+ .target = {
+ .name = "POWER10 omic",
+ .compatible = "ibm,power10-omic",
+ .class = "omic",
+ .translate = translate_cast(p10_omic_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_omic);
+
+static uint64_t p10_omi_translate(struct omi *omi, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(omi));
+ int chiplet_id = get_chiplet_id(addr);
+
+ if (chiplet_id >= PAU0_CHIPLET_ID && chiplet_id <= PAU3_CHIPLET_ID) {
+ if (chip_unitnum >= 0 && chip_unitnum <= 3)
+ addr = set_chiplet_id(addr, PAU0_CHIPLET_ID);
+ else if (chip_unitnum >= 4 && chip_unitnum <= 7)
+ addr = set_chiplet_id(addr, PAU2_CHIPLET_ID);
+ else if (chip_unitnum >= 8 && chip_unitnum <= 11)
+ addr = set_chiplet_id(addr, PAU1_CHIPLET_ID);
+ else if (chip_unitnum >= 12 && chip_unitnum <= 15)
+ addr = set_chiplet_id(addr, PAU3_CHIPLET_ID);
+ else
+ assert(0);
+
+ if (chip_unitnum % 2)
+ addr = set_io_lane(addr, 8 + get_io_lane(addr) % 8);
+ else
+ addr = set_io_lane(addr, get_io_lane(addr) % 8);
+
+ if ((chip_unitnum / 2) % 2)
+ addr = set_io_group_addr(addr, 0x3);
+ else
+ addr = set_io_group_addr(addr, 0x2);
+ } else {
+ addr = set_chiplet_id(addr, chip_unitnum/4 + MC0_CHIPLET_ID);
+
+ if (get_sat_offset(addr) >= 16 && get_sat_offset(addr) <= 47) {
+ if (chip_unitnum % 2)
+ addr = set_sat_offset(addr, 32 + get_sat_offset(addr) % 16);
+ else
+ addr = set_sat_offset(addr, 16 + get_sat_offset(addr) % 16);
+ } else {
+ if (chip_unitnum % 2)
+ addr = set_sat_offset(addr, 56 + get_sat_offset(addr) % 4);
+ else
+ addr = set_sat_offset(addr, 48 + get_sat_offset(addr) % 4);
+ }
+
+ if ((chip_unitnum / 2) %2)
+ addr = set_ring_id(addr, 0x6);
+ else
+ addr = set_ring_id(addr, 0x5);
+ }
+
+ return addr;
+}
+
+static struct omi p10_omi = {
+ .target = {
+ .name = "POWER10 omi",
+ .compatible = "ibm,power10-omi",
+ .class = "omi",
+ .translate = translate_cast(p10_omi_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_omi);
+
+static uint64_t p10_pauc_translate(struct pauc *pauc, uint64_t addr)
+{
+ return set_chiplet_id(addr, pdbg_target_index(t(pauc)) + PAU0_CHIPLET_ID);
+}
+
+static struct pauc p10_pauc = {
+ .target = {
+ .name = "POWER10 pauc",
+ .compatible = "ibm,power10-pauc",
+ .class = "pauc",
+ .translate = translate_cast(p10_pauc_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_pauc);
+
+static uint64_t p10_pau_translate(struct pau *pau, uint64_t addr)
+{
+ int chip_unitnum = pdbg_target_index(t(pau));
+
+ addr = set_chiplet_id(addr, chip_unitnum/2 + PAU0_CHIPLET_ID);
+
+ switch (chip_unitnum) {
+ case 0:
+ case 3:
+ case 4:
+ case 6:
+ if (get_ring_id(addr) == 0x4)
+ addr = set_ring_id(addr, 0x2);
+ else if (get_ring_id(addr) == 0x5)
+ addr = set_ring_id(addr, 0x3);
+ break;
+
+ case 1:
+ case 2:
+ case 5:
+ case 7:
+ if (get_ring_id(addr) == 0x2)
+ addr = set_ring_id(addr, 0x4);
+ else if (get_ring_id(addr) == 0x3)
+ addr = set_ring_id(addr, 0x5);
+ break;
+ }
+
+ return addr;
+}
+
+struct pau p10_pau = {
+ .target = {
+ .name = "POWER10 pau",
+ .compatible = "ibm,power10-pau",
+ .class = "pau",
+ .translate = translate_cast(p10_pau_translate),
+ },
+};
+DECLARE_HW_UNIT(p10_pau);
+
+#define HEADER_CHECK_DATA ((uint64_t) 0xc0ffee03 << 32)
+
+static int p10_chiplet_getring(struct chiplet *chiplet, uint64_t ring_addr, int64_t ring_len, uint32_t result[])
+{
+ uint64_t scan_type_addr;
+ uint64_t scan_data_addr;
+ uint64_t scan_header_addr;
+ uint64_t scan_type_data;
+ uint64_t set_pulse = 1;
+ uint64_t bits = 32;
+ uint64_t data;
+
+ /* We skip the first word in the results so we can write it later as it
+ * should contain the header read out at the end */
+ int i = 0;
+
+ scan_type_addr = (ring_addr & 0x7fff0000) | 0x7;
+ scan_data_addr = (scan_type_addr & 0xffff0000) | 0x8000;
+ scan_header_addr = scan_data_addr & 0xffffe000;
+
+ scan_type_data = (ring_addr & 0xfff0) << 13;
+ scan_type_data |= 0x800 >> (ring_addr & 0xf);
+ scan_type_data <<= 32;
+
+ pib_write(&chiplet->target, scan_type_addr, scan_type_data);
+ pib_write(&chiplet->target, scan_header_addr, HEADER_CHECK_DATA);
+
+ /* The final 32 bit read is the header which we do at the end */
+ ring_len -= 32;
+ i = 1;
+
+ while (ring_len > 0) {
+ ring_len -= bits;
+ if (set_pulse) {
+ scan_data_addr |= 0x4000;
+ set_pulse = 0;
+ } else
+ scan_data_addr &= ~0x4000ULL;
+
+ scan_data_addr &= ~0xffull;
+ scan_data_addr |= bits;
+ pib_read(&chiplet->target, scan_data_addr, &data);
+
+ /* Discard lower 32 bits */
+ /* TODO: We always read 64-bits from the ring on P9 so we could
+ * optimise here by reading 64-bits at a time, but I'm not
+ * confident I've figured that out and 32-bits is what Hostboot
+ * does and seems to work. */
+ data >>= 32;
+
+ /* Left-align data */
+ data <<= 32 - bits;
+ result[i++] = data;
+ if (ring_len > 0 && (ring_len < bits))
+ bits = ring_len;
+ }
+
+ pib_read(&chiplet->target, scan_header_addr | 0x20, &data);
+ data &= 0xffffffff00000000;
+ result[0] = data >> 32;
+ if (data != HEADER_CHECK_DATA)
+ printf("WARNING: Header check failed. Make sure you specified the right ring length!\n"
+ "Ring data is probably corrupt now.\n");
+
+ return 0;
+}
+
+#define NET_CTRL0 0xf0040
+#define NET_CTRL0_CHIPLET_ENABLE PPC_BIT(0)
+static int p10_chiplet_probe(struct pdbg_target *target)
+{
+ uint64_t value;
+
+ if (pib_read(target, NET_CTRL0, &value))
+ return -1;
+
+ if (!(value & NET_CTRL0_CHIPLET_ENABLE))
+ return -1;
+
+ return 0;
+}
+
+static uint64_t p10_chiplet_translate(struct chiplet *chiplet, uint64_t addr)
+{
+ return set_chiplet_id(addr, pdbg_target_index(t(chiplet)));
+}
+
+static struct chiplet p10_chiplet = {
+ .target = {
+ .name = "POWER10 Chiplet",
+ .compatible = "ibm,power10-chiplet",
+ .class = "chiplet",
+ .probe = p10_chiplet_probe,
+ .translate = translate_cast(p10_chiplet_translate),
+ },
+ .getring = p10_chiplet_getring,
+};
+DECLARE_HW_UNIT(p10_chiplet);
+
+static int p10_thread_probe(struct pdbg_target *target)
+{
+ struct thread *thread = target_to_thread(target);
+
+ thread->id = pdbg_target_index(target);
+
+ return 0;
+}
+
+static struct thread p10_thread = {
+ .target = {
+ .name = "POWER10 Thread",
+ .compatible = "ibm,power10-thread",
+ .class = "thread",
+ .probe = p10_thread_probe,
+ },
+};
+DECLARE_HW_UNIT(p10_thread);
+
+static uint64_t no_translate(struct pdbg_target *target, uint64_t addr)
+{
+ /* No translation performed */
+ return 0;
+}
+
+static struct fc p10_fc = {
+ .target = {
+ .name = "POWER10 Fused Core",
+ .compatible = "ibm,power10-fc",
+ .class = "fc",
+ .translate = no_translate,
+ },
+};
+DECLARE_HW_UNIT(p10_fc);
+
+__attribute__((constructor))
+static void register_p10_fapi_targets(void)
+{
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_eq_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_core_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pec_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_phb_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_nmmu_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_iohs_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_mi_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_mc_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_mcc_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_omic_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_omi_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pauc_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_chiplet_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit);
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_fc_hw_unit);
+}
diff --git a/libpdbg/p10_scom_addr.h b/libpdbg/p10_scom_addr.h
new file mode 100644
index 0000000..f307e46
--- /dev/null
+++ b/libpdbg/p10_scom_addr.h
@@ -0,0 +1,133 @@
+/* Copyright 2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBPDBG_SCOM_ADDR
+#define LIBPDBG_SCOM_ADDR
+
+/* Helpers and defines from the ekb. See p10_scom_addr.H */
+
+/* P10 Chiplet ID enumeration */
+enum {
+ PIB_CHIPLET_ID = 0x00, ///< PIB chiplet (FSI)
+ PERV_CHIPLET_ID = 0x01, ///< TP chiplet
+
+ N0_CHIPLET_ID = 0x02, ///< Nest0 (North) chiplet
+ N1_CHIPLET_ID = 0x03, ///< Nest1 (South) chiplet
+
+ PCI0_CHIPLET_ID = 0x08, ///< PCIe0 chiplet
+ PCI1_CHIPLET_ID = 0x09, ///< PCIe1 chiplet
+
+ MC0_CHIPLET_ID = 0x0C, ///< MC0 chiplet
+ MC1_CHIPLET_ID = 0x0D, ///< MC1 chiplet
+ MC2_CHIPLET_ID = 0x0E, ///< MC2 chiplet
+ MC3_CHIPLET_ID = 0x0F, ///< MC3 chiplet
+
+ PAU0_CHIPLET_ID = 0x10, ///< PAU0 chiplet
+ PAU1_CHIPLET_ID = 0x11, ///< PAU1 chiplet
+ PAU2_CHIPLET_ID = 0x12, ///< PAU2 chiplet
+ PAU3_CHIPLET_ID = 0x13, ///< PAU3 chiplet
+
+ AXON0_CHIPLET_ID = 0x18, ///< AXON0 chiplet (high speed io)
+ AXON1_CHIPLET_ID = 0x19, ///< AXON1 chiplet (high speed io)
+ AXON2_CHIPLET_ID = 0x1A, ///< AXON2 chiplet (high speed io)
+ AXON3_CHIPLET_ID = 0x1B, ///< AXON3 chiplet (high speed io)
+ AXON4_CHIPLET_ID = 0x1C, ///< AXON4 chiplet (high speed io)
+ AXON5_CHIPLET_ID = 0x1D, ///< AXON5 chiplet (high speed io)
+ AXON6_CHIPLET_ID = 0x1E, ///< AXON6 chiplet (high speed io)
+ AXON7_CHIPLET_ID = 0x1F, ///< AXON7 chiplet (high speed io)
+
+ EQ0_CHIPLET_ID = 0x20, ///< Quad0 chiplet (super chiplet)
+ EQ1_CHIPLET_ID = 0x21, ///< Quad1 chiplet (super chiplet)
+ EQ2_CHIPLET_ID = 0x22, ///< Quad2 chiplet (super chiplet)
+ EQ3_CHIPLET_ID = 0x23, ///< Quad3 chiplet (super chiplet)
+ EQ4_CHIPLET_ID = 0x24, ///< Quad4 chiplet (super chiplet)
+ EQ5_CHIPLET_ID = 0x25, ///< Quad5 chiplet (super chiplet)
+ EQ6_CHIPLET_ID = 0x26, ///< Quad6 chiplet (super chiplet)
+ EQ7_CHIPLET_ID = 0x27, ///< Quad7 chiplet (super chiplet)
+};
+
+/* Extract pervasive chiplet ID from SCOM address */
+static uint8_t get_chiplet_id(uint64_t addr)
+{
+ return ((addr >> 24) & 0x3F);
+}
+
+/* Modify SCOM address to update pervasive chiplet ID */
+static uint64_t set_chiplet_id(uint64_t addr, uint8_t chiplet_id)
+{
+ addr &= 0xFFFFFFFFC0FFFFFFULL;
+ addr |= ((chiplet_id & 0x3F) << 24);
+ return addr;
+}
+
+static uint8_t get_ring_id(uint64_t addr)
+{
+ return (addr >> 10) & 0xF;
+}
+
+static uint64_t set_ring_id(uint64_t addr, uint64_t ring)
+{
+ addr &= 0xFFFFFFFFFFFF03FFULL;
+ addr |= ((ring & 0x3F) << 10);
+ return addr;
+}
+
+static uint32_t get_io_lane(uint64_t addr)
+{
+ return (addr >> 32) & 0x1F;
+}
+
+static uint64_t set_io_lane(uint64_t addr, uint64_t lane)
+{
+ addr &= 0xFFFFFFE0FFFFFFFFULL;
+ addr |= (lane & 0x1F) << 32;
+ return addr;
+}
+
+static uint8_t get_sat_id(uint64_t addr)
+{
+ return ((addr >> 6) & 0xF);
+}
+
+/* Modify SCOM address to update satellite ID field */
+static uint64_t set_sat_id(uint64_t addr, uint8_t sat_id)
+{
+ addr &= 0xFFFFFFFFFFFFFC3FULL;
+ addr |= ((sat_id & 0xF) << 6);
+ return addr;
+}
+
+static uint8_t get_sat_offset(uint64_t addr)
+{
+ return addr & 0x3F;
+}
+
+static uint64_t set_sat_offset(uint64_t addr, uint8_t sat_offset)
+{
+ addr &= 0xFFFFFFFFFFFFFFC0ULL;
+ addr |= (sat_offset & 0x3F);
+ return addr;
+}
+
+static uint64_t set_io_group_addr(uint64_t addr, uint64_t group_addr)
+{
+ addr &= 0xFFFFFC1FFFFFFFFFULL;
+ addr |= (group_addr & 0x1F) << 37;
+
+ return addr;
+}
+
+#endif
--
2.26.2
More information about the Pdbg
mailing list