summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am6
-rw-r--r--libpdbg/chip.c327
-rw-r--r--libpdbg/operations.h16
-rw-r--r--libpdbg/p8chip.c344
-rw-r--r--libpdbg/p9chip.c240
-rw-r--r--libpdbg/target.c18
-rw-r--r--libpdbg/target.h11
-rw-r--r--p9-fsi.dtsi47
-rw-r--r--p9-fsi.dtsi.m4120
-rw-r--r--src/main.c14
10 files changed, 781 insertions, 362 deletions
diff --git a/Makefile.am b/Makefile.am
index 8309ccb..9b1ccd9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,6 +35,8 @@ libpdbg_la_SOURCES = \
libpdbg/kernel.c \
libpdbg/fakepib.c \
libpdbg/chip.c \
+ libpdbg/p8chip.c \
+ libpdbg/p9chip.c \
libpdbg/bmcfsi.c \
libpdbg/cfam.c \
libpdbg/i2c.c \
@@ -45,6 +47,10 @@ libpdbg_la_SOURCES = \
%.dts: %.dts.m4
m4 -Isrc $< > $@
+%.dtsi: %.dtsi.m4
+ m4 -Isrc $< > $@
+
+p9w-fsi.dtb.o: p9w-fsi.dts p9-fsi.dtsi
%.dtb.o: %.dts
dtc -I dts $< -O dtb > $@.tmp
diff --git a/libpdbg/chip.c b/libpdbg/chip.c
index cde11a3..5265afe 100644
--- a/libpdbg/chip.c
+++ b/libpdbg/chip.c
@@ -24,62 +24,6 @@
#include "operations.h"
#include "bitutils.h"
-#define RAS_STATUS_TIMEOUT 100
-
-#define DIRECT_CONTROLS_REG 0x0
-#define DIRECT_CONTROL_SP_STEP PPC_BIT(61)
-#define DIRECT_CONTROL_SP_START PPC_BIT(62)
-#define DIRECT_CONTROL_SP_STOP PPC_BIT(63)
-#define RAS_MODE_REG 0x1
-#define MR_THREAD_IN_DEBUG PPC_BIT(43)
-#define MR_DO_SINGLE_MODE PPC_BIT(50)
-#define RAS_STATUS_REG 0x2
-#define RAS_STATUS_SRQ_EMPTY PPC_BIT(8)
-#define RAS_STATUS_LSU_QUIESCED PPC_BIT(9)
-#define RAS_STATUS_INST_COMPLETE PPC_BIT(12)
-#define RAS_STATUS_THREAD_ACTIVE PPC_BIT(48)
-#define RAS_STATUS_TS_QUIESCE PPC_BIT(49)
-#define POW_STATUS_REG 0x4
-#define PMC_POW_STATE PPC_BITMASK(4, 5)
-#define CORE_POW_STATE PPC_BITMASK(23, 25)
-#define THREAD_ACTIVE_REG 0x1310e
-#define THREAD_ACTIVE PPC_BITMASK(0, 7)
-#define RAM_THREAD_ACTIVE PPC_BITMASK(8, 15)
-#define SPR_MODE_REG 0x13281
-#define SPR_MODE_SPRC_WR_EN PPC_BIT(3)
-#define SPR_MODE_SPRC_SEL PPC_BITMASK(16, 19)
-#define SPR_MODE_SPRC_T_SEL PPC_BITMASK(20, 27)
-#define L0_SCOM_SPRC_REG 0x13280
-#define SCOM_SPRC_SCRATCH_SPR 0x40
-#define SCR0_REG 0x13283
-#define RAM_MODE_REG 0x13c00
-#define RAM_MODE_ENABLE PPC_BIT(0)
-#define RAM_CTRL_REG 0x13c01
-#define RAM_THREAD_SELECT PPC_BITMASK(0, 2)
-#define RAM_INSTR PPC_BITMASK(3, 34)
-#define RAM_STATUS_REG 0x13c02
-#define RAM_CONTROL_RECOV PPC_BIT(0)
-#define RAM_STATUS PPC_BIT(1)
-#define RAM_EXCEPTION PPC_BIT(2)
-#define LSU_EMPTY PPC_BIT(3)
-#define SCOM_EX_GP3 0xf0012
-#define PMSPCWKUPFSP_REG 0xf010d
-#define FSP_SPECIAL_WAKEUP PPC_BIT(0)
-#define EX_PM_GP0_REG 0xf0100
-#define SPECIAL_WKUP_DONE PPC_BIT(31)
-
-/* How long (in us) to wait for a special wakeup to complete */
-#define SPECIAL_WKUP_TIMEOUT 10
-
-/* Opcodes */
-#define MTNIA_OPCODE 0x00000002UL
-#define MFNIA_OPCODE 0x00000004UL
-#define MFMSR_OPCODE 0x7c0000a6UL
-#define MTMSR_OPCODE 0x7c000124UL
-#define MFSPR_OPCODE 0x7c0002a6UL
-#define MTSPR_OPCODE 0x7c0003a6UL
-#define LD_OPCODE 0xe8000000UL
-
static uint64_t mfspr(uint64_t reg, uint64_t spr)
{
if (reg > 31)
@@ -136,168 +80,39 @@ static uint64_t ld(uint64_t rt, uint64_t ds, uint64_t ra)
return LD_OPCODE | (rt << 21) | (ra << 16) | (ds << 2);
}
-static int assert_special_wakeup(struct chiplet *chip)
-{
- int i = 0;
- uint64_t gp0;
-
- /* Assert special wakeup to prevent low power states */
- CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, FSP_SPECIAL_WAKEUP));
-
- /* Poll for completion */
- do {
- usleep(1);
- CHECK_ERR(pib_read(&chip->target, EX_PM_GP0_REG, &gp0));
-
- if (i++ > SPECIAL_WKUP_TIMEOUT) {
- PR_ERROR("Timeout waiting for special wakeup on %s@0x%08lx\n", chip->target.name,
- dt_get_address(chip->target.dn, 0, NULL));
- return -1;
- }
- } while (!(gp0 & SPECIAL_WKUP_DONE));
-
- return 0;
-}
-
-static int deassert_special_wakeup(struct chiplet *chip)
-{
- /* Assert special wakeup to prevent low power states */
- CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, 0));
-
- return 0;
-}
-
uint64_t thread_status(struct thread *thread)
{
return thread->status;
}
-static uint64_t get_thread_status(struct thread *thread)
-{
- uint64_t val, mode_reg, thread_status = thread->status;
-
- /* Need to activete debug mode to get complete status */
- CHECK_ERR(pib_read(&thread->target, RAS_MODE_REG, &mode_reg));
- mode_reg |= MR_THREAD_IN_DEBUG;
- CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, mode_reg));
-
- /* Read status */
- CHECK_ERR(pib_read(&thread->target, RAS_STATUS_REG, &val));
-
- thread_status = SETFIELD(THREAD_STATUS_ACTIVE, thread_status, !!(val & RAS_STATUS_THREAD_ACTIVE));
- thread_status = SETFIELD(THREAD_STATUS_QUIESCE, thread_status, !!(val & RAS_STATUS_TS_QUIESCE));
-
- /* Read POW status */
- CHECK_ERR(pib_read(&thread->target, POW_STATUS_REG, &val));
- thread_status = SETFIELD(THREAD_STATUS_STATE, thread_status, GETFIELD(PMC_POW_STATE, val));
-
- /* Clear debug mode */
- mode_reg &= ~MR_THREAD_IN_DEBUG;
- CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, mode_reg));
-
- return thread_status;
-}
-
/*
* Single step the thread count instructions.
*/
-int ram_step_thread(struct thread *thread, int count)
-{
- int i;
- uint64_t ras_mode, ras_status;
-
- /* Activate single-step mode */
- CHECK_ERR(pib_read(&thread->target, RAS_MODE_REG, &ras_mode));
- ras_mode |= MR_DO_SINGLE_MODE;
- CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, ras_mode));
-
- /* Step the core */
- for (i = 0; i < count; i++) {
- CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_STEP));
-
- /* Wait for step to complete */
- do {
- CHECK_ERR(pib_read(&thread->target, RAS_STATUS_REG, &ras_status));
- } while (!(ras_status & RAS_STATUS_INST_COMPLETE));
- }
-
- /* Deactivate single-step mode */
- ras_mode &= ~MR_DO_SINGLE_MODE;
- CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, ras_mode));
-
- return 0;
-}
-
-int ram_stop_thread(struct thread *thread)
+int ram_step_thread(struct target *thread_target, int count)
{
- int i = 0;
- uint64_t val;
- struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
-
- do {
- /* Quiese active thread */
- CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_STOP));
-
- /* Wait for thread to quiese */
- CHECK_ERR(pib_read(&chip->target, RAS_STATUS_REG, &val));
- if (i++ > RAS_STATUS_TIMEOUT) {
- PR_ERROR("Unable to quiesce thread %d (0x%016llx).\n",
- thread->id, val);
- PR_ERROR("Continuing anyway.\n");
- if (val & PPC_BIT(48)) {
- PR_ERROR("Unable to continue\n");
- }
- break;
- }
-
- /* We can continue ramming if either the
- * thread is not active or the SRQ/LSU/TS bits
- * are set. */
- } while ((val & RAS_STATUS_THREAD_ACTIVE) &&
- !((val & RAS_STATUS_SRQ_EMPTY)
- && (val & RAS_STATUS_LSU_QUIESCED)
- && (val & RAS_STATUS_TS_QUIESCE)));
-
+ struct thread *thread;
- /* Make the threads RAM thread active */
- CHECK_ERR(pib_read(&chip->target, THREAD_ACTIVE_REG, &val));
- val |= PPC_BIT(8) >> thread->id;
- CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
-
- return 0;
+ assert(!strcmp(thread_target->class, "thread"));
+ thread = target_to_thread(thread_target);
+ return thread->step(thread, count);
}
-int ram_start_thread(struct thread *thread)
+int ram_start_thread(struct target *thread_target)
{
- uint64_t val;
- struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
-
- /* Activate thread */
- CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_START));
-
- /* Restore thread active */
- CHECK_ERR(pib_read(&chip->target, THREAD_ACTIVE_REG, &val));
- val &= ~(PPC_BIT(8) >> thread->id);
- val |= PPC_BIT(thread->id);
- CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
+ struct thread *thread;
- return 0;
+ assert(!strcmp(thread_target->class, "thread"));
+ thread = target_to_thread(thread_target);
+ return thread->start(thread);
}
-/* We can only ram a thread if all the threads on the core/chip are
- * quiesced */
-int ram_status(struct chiplet *chip)
+int ram_stop_thread(struct target *thread_target)
{
- struct dt_node *dn;
-
- dt_for_each_compatible(chip->target.dn, dn, "ibm,power8-thread") {
- struct thread *thread;
- thread = target_to_thread(dn->target);
- if (!(get_thread_status(thread) & THREAD_STATUS_QUIESCE))
- return -1;
- }
+ struct thread *thread;
- return 0;
+ assert(!strcmp(thread_target->class, "thread"));
+ thread = target_to_thread(thread_target);
+ return thread->stop(thread);
}
/*
@@ -311,29 +126,11 @@ int ram_status(struct chiplet *chip)
static int ram_instructions(struct thread *thread, uint64_t *opcodes,
uint64_t *results, int len, unsigned int lpar)
{
- uint64_t ram_mode, val, opcode, r0 = 0, r1 = 0;
- struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t ram_mode, opcode, r0 = 0, r1 = 0, scratch = 0;
int i;
int exception = 0;
- /* Check to see if the parent chip is in a state that can RAM instructions */
- if (ram_status(chip))
- return 1;
-
- if (!(thread_status(thread) & THREAD_STATUS_ACTIVE))
- return 2;
-
- /* Activate RAM mode */
- CHECK_ERR(pib_read(&chip->target, RAM_MODE_REG, &ram_mode));
- ram_mode |= RAM_MODE_ENABLE;
- CHECK_ERR(pib_write(&chip->target, RAM_MODE_REG, ram_mode));
-
- /* Setup SPRC to use SPRD */
- val = SPR_MODE_SPRC_WR_EN;
- val = SETFIELD(SPR_MODE_SPRC_SEL, val, 1 << (3 - lpar));
- val = SETFIELD(SPR_MODE_SPRC_T_SEL, val, 1 << (7 - thread->id));
- CHECK_ERR(pib_write(&chip->target, SPR_MODE_REG, val));
- CHECK_ERR(pib_write(&chip->target, L0_SCOM_SPRC_REG, SCOM_SPRC_SCRATCH_SPR));
+ CHECK_ERR(thread->ram_setup(thread));
/* RAM instructions */
for (i = -2; i < len + 2; i++) {
@@ -343,51 +140,29 @@ static int ram_instructions(struct thread *thread, uint64_t *opcodes,
/* Save r0 (assumes opcodes don't touch other registers) */
opcode = mtspr(277, 0);
else if (i < len) {
- CHECK_ERR(pib_write(&chip->target, SCR0_REG, results[i]));
+ scratch = results[i];
opcode = opcodes[i];
} else if (i == len) {
/* Restore r0 */
- CHECK_ERR(pib_write(&chip->target, SCR0_REG, r0));
+ scratch = r0;
opcode = mfspr(0, 277);
} else if (i == len + 1) {
/* Restore r1 */
- CHECK_ERR(pib_write(&chip->target, SCR0_REG, r1));
+ scratch = r1;
opcode = mfspr(0, 277);
}
- /* ram instruction */
- val = SETFIELD(RAM_THREAD_SELECT, 0ULL, thread->id);
- val = SETFIELD(RAM_INSTR, val, opcode);
- CHECK_ERR(pib_write(&chip->target, RAM_CTRL_REG, val));
-
- /* wait for completion */
- do {
- CHECK_ERR(pib_read(&chip->target, RAM_STATUS_REG, &val));
- } while (!((val & PPC_BIT(1)) || ((val & PPC_BIT(2)) && (val & PPC_BIT(3)))));
-
- if (!(val & PPC_BIT(1))) {
- exception = GETFIELD(PPC_BITMASK(2,3), val) == 0x3;
- if (exception) {
- /* Skip remaining instructions */
- i = len - 1;
- continue;
- } else
- PR_ERROR("RAMMING failed with status 0x%llx\n", val);
- }
+ CHECK_ERR(thread->ram_instruction(thread, opcode, &scratch));
- /* Save the results */
- CHECK_ERR(pib_read(&chip->target, SCR0_REG, &val));
if (i == -2)
- r1 = val;
+ r1 = scratch;
else if (i == -1)
- r0 = val;
+ r0 = scratch;
else if (i < len)
- results[i] = val;
+ results[i] = scratch;
}
- /* Disable RAM mode */
- ram_mode &= ~RAM_MODE_ENABLE;
- CHECK_ERR(pib_write(&chip->target, RAM_MODE_REG, ram_mode));
+ CHECK_ERR(thread->ram_destroy(thread));
return exception;
}
@@ -481,55 +256,3 @@ int ram_getmem(struct thread *thread, uint64_t addr, uint64_t *value)
*value = results[3];
return 0;
}
-
-/*
- * Initialise all viable threads for ramming on the given chiplet.
- */
-static int p8_thread_probe(struct target *target)
-{
- struct thread *thread = target_to_thread(target);
-
- thread->id = (dt_get_address(target->dn, 0, NULL) >> 4) & 0xf;
- thread->status = get_thread_status(thread);
-
- return 0;
-}
-
-struct thread p8_thread = {
- .target = {
- .name = "POWER8 Thread",
- .compatible = "ibm,power8-thread",
- .class = "thread",
- .probe = p8_thread_probe,
- },
-};
-DECLARE_HW_UNIT(p8_thread);
-
-static int p8_chiplet_probe(struct target *target)
-{
- uint64_t value;
- struct chiplet *chiplet = target_to_chiplet(target);
- int i, count = 0, rc = 0;
-
- /* Work out if this chip is actually present */
- if (pib_read(target, SCOM_EX_GP3, &value)) {
- PR_DEBUG("Error reading chip GP3 register\n");
- return -1;
- }
-
- if (!GETFIELD(PPC_BIT(0), value))
- return -1;
-
- assert_special_wakeup(chiplet);
- return 0;
-}
-
-struct chiplet p8_chiplet = {
- .target = {
- .name = "POWER8 Chiplet",
- .compatible = "ibm,power8-core",
- .class = "chiplet",
- .probe = p8_chiplet_probe,
- },
-};
-DECLARE_HW_UNIT(p8_chiplet);
diff --git a/libpdbg/operations.h b/libpdbg/operations.h
index 4175af3..62ff5c4 100644
--- a/libpdbg/operations.h
+++ b/libpdbg/operations.h
@@ -45,6 +45,16 @@ int adu_putmem(struct target *target, uint64_t start_addr, uint8_t *input, uint6
#define THREAD_STATUS_SLEEP PPC_BITMASK(61, 62)
#define THREAD_STATUS_QUIESCE PPC_BIT(60)
+/* Opcodes for instruction ramming */
+#define OPCODE_MASK 0xfc0003ffUL
+#define MTNIA_OPCODE 0x00000002UL
+#define MFNIA_OPCODE 0x00000004UL
+#define MFMSR_OPCODE 0x7c0000a6UL
+#define MTMSR_OPCODE 0x7c000124UL
+#define MFSPR_OPCODE 0x7c0002a6UL
+#define MTSPR_OPCODE 0x7c0003a6UL
+#define LD_OPCODE 0xe8000000UL
+
int ram_getgpr(struct thread *thread, int gpr, uint64_t *value);
int ram_putgpr(struct thread *thread, int gpr, uint64_t value);
int ram_getnia(struct thread *thread, uint64_t *value);
@@ -55,9 +65,9 @@ int ram_getmsr(struct thread *thread, uint64_t *value);
int ram_putmsr(struct thread *thread, uint64_t value);
int ram_getmem(struct thread *thread, uint64_t addr, uint64_t *value);
uint64_t thread_status(struct thread *thread);
-int ram_stop_thread(struct thread *thread);
-int ram_step_thread(struct thread *thread, int count);
-int ram_start_thread(struct thread *thread);
+int ram_stop_thread(struct target *thread);
+int ram_step_thread(struct target *thread, int count);
+int ram_start_thread(struct target *thread);
void fsi_destroy(struct target *target);
/* GDB server functionality */
diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c
new file mode 100644
index 0000000..c11b68c
--- /dev/null
+++ b/libpdbg/p8chip.c
@@ -0,0 +1,344 @@
+/* Copyright 2016 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 <ccan/array_size/array_size.h>
+#include <unistd.h>
+
+#include "target.h"
+#include "operations.h"
+#include "bitutils.h"
+
+#define RAS_STATUS_TIMEOUT 100
+
+#define DIRECT_CONTROLS_REG 0x0
+#define DIRECT_CONTROL_SP_STEP PPC_BIT(61)
+#define DIRECT_CONTROL_SP_START PPC_BIT(62)
+#define DIRECT_CONTROL_SP_STOP PPC_BIT(63)
+#define RAS_MODE_REG 0x1
+#define MR_THREAD_IN_DEBUG PPC_BIT(43)
+#define MR_DO_SINGLE_MODE PPC_BIT(50)
+#define RAS_STATUS_REG 0x2
+#define RAS_STATUS_SRQ_EMPTY PPC_BIT(8)
+#define RAS_STATUS_LSU_QUIESCED PPC_BIT(9)
+#define RAS_STATUS_INST_COMPLETE PPC_BIT(12)
+#define RAS_STATUS_THREAD_ACTIVE PPC_BIT(48)
+#define RAS_STATUS_TS_QUIESCE PPC_BIT(49)
+#define POW_STATUS_REG 0x4
+#define PMC_POW_STATE PPC_BITMASK(4, 5)
+#define CORE_POW_STATE PPC_BITMASK(23, 25)
+#define THREAD_ACTIVE_REG 0x1310e
+#define THREAD_ACTIVE PPC_BITMASK(0, 7)
+#define RAM_THREAD_ACTIVE PPC_BITMASK(8, 15)
+#define SPR_MODE_REG 0x13281
+#define SPR_MODE_SPRC_WR_EN PPC_BIT(3)
+#define SPR_MODE_SPRC_SEL PPC_BITMASK(16, 19)
+#define SPR_MODE_SPRC_T_SEL PPC_BITMASK(20, 27)
+#define L0_SCOM_SPRC_REG 0x13280
+#define SCOM_SPRC_SCRATCH_SPR 0x40
+#define SCR0_REG 0x13283
+#define RAM_MODE_REG 0x13c00
+#define RAM_MODE_ENABLE PPC_BIT(0)
+#define RAM_CTRL_REG 0x13c01
+#define RAM_THREAD_SELECT PPC_BITMASK(0, 2)
+#define RAM_INSTR PPC_BITMASK(3, 34)
+#define RAM_STATUS_REG 0x13c02
+#define RAM_CONTROL_RECOV PPC_BIT(0)
+#define RAM_STATUS PPC_BIT(1)
+#define RAM_EXCEPTION PPC_BIT(2)
+#define LSU_EMPTY PPC_BIT(3)
+#define SCOM_EX_GP3 0xf0012
+#define PMSPCWKUPFSP_REG 0xf010d
+#define FSP_SPECIAL_WAKEUP PPC_BIT(0)
+#define EX_PM_GP0_REG 0xf0100
+#define SPECIAL_WKUP_DONE PPC_BIT(31)
+
+/* How long (in us) to wait for a special wakeup to complete */
+#define SPECIAL_WKUP_TIMEOUT 10
+
+static int assert_special_wakeup(struct chiplet *chip)
+{
+ int i = 0;
+ uint64_t gp0;
+
+ /* Assert special wakeup to prevent low power states */
+ CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, FSP_SPECIAL_WAKEUP));
+
+ /* Poll for completion */
+ do {
+ usleep(1);
+ CHECK_ERR(pib_read(&chip->target, EX_PM_GP0_REG, &gp0));
+
+ if (i++ > SPECIAL_WKUP_TIMEOUT) {
+ PR_ERROR("Timeout waiting for special wakeup on %s@0x%08lx\n", chip->target.name,
+ dt_get_address(chip->target.dn, 0, NULL));
+ return -1;
+ }
+ } while (!(gp0 & SPECIAL_WKUP_DONE));
+
+ return 0;
+}
+
+static int deassert_special_wakeup(struct chiplet *chip)
+{
+ /* Assert special wakeup to prevent low power states */
+ CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, 0));
+
+ return 0;
+}
+
+static uint64_t get_thread_status(struct thread *thread)
+{
+ uint64_t val, mode_reg, thread_status = thread->status;
+
+ /* Need to activete debug mode to get complete status */
+ CHECK_ERR(pib_read(&thread->target, RAS_MODE_REG, &mode_reg));
+ mode_reg |= MR_THREAD_IN_DEBUG;
+ CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, mode_reg));
+
+ /* Read status */
+ CHECK_ERR(pib_read(&thread->target, RAS_STATUS_REG, &val));
+
+ thread_status = SETFIELD(THREAD_STATUS_ACTIVE, thread_status, !!(val & RAS_STATUS_THREAD_ACTIVE));
+ thread_status = SETFIELD(THREAD_STATUS_QUIESCE, thread_status, !!(val & RAS_STATUS_TS_QUIESCE));
+
+ /* Read POW status */
+ CHECK_ERR(pib_read(&thread->target, POW_STATUS_REG, &val));
+ thread_status = SETFIELD(THREAD_STATUS_STATE, thread_status, GETFIELD(PMC_POW_STATE, val));
+
+ /* Clear debug mode */
+ mode_reg &= ~MR_THREAD_IN_DEBUG;
+ CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, mode_reg));
+
+ return thread_status;
+}
+
+static int p8_thread_step(struct thread *thread, int count)
+{
+ int i;
+ uint64_t ras_mode, ras_status;
+
+ /* Activate single-step mode */
+ CHECK_ERR(pib_read(&thread->target, RAS_MODE_REG, &ras_mode));
+ ras_mode |= MR_DO_SINGLE_MODE;
+ CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, ras_mode));
+
+ /* Step the core */
+ for (i = 0; i < count; i++) {
+ CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_STEP));
+
+ /* Wait for step to complete */
+ do {
+ CHECK_ERR(pib_read(&thread->target, RAS_STATUS_REG, &ras_status));
+ } while (!(ras_status & RAS_STATUS_INST_COMPLETE));
+ }
+
+ /* Deactivate single-step mode */
+ ras_mode &= ~MR_DO_SINGLE_MODE;
+ CHECK_ERR(pib_write(&thread->target, RAS_MODE_REG, ras_mode));
+
+ return 0;
+}
+
+static int p8_thread_stop(struct thread *thread)
+{
+ int i = 0;
+ uint64_t val;
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+
+ do {
+ /* Quiese active thread */
+ CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_STOP));
+
+ /* Wait for thread to quiese */
+ CHECK_ERR(pib_read(&chip->target, RAS_STATUS_REG, &val));
+ if (i++ > RAS_STATUS_TIMEOUT) {
+ PR_ERROR("Unable to quiesce thread %d (0x%016llx).\n",
+ thread->id, val);
+ PR_ERROR("Continuing anyway.\n");
+ if (val & PPC_BIT(48)) {
+ PR_ERROR("Unable to continue\n");
+ }
+ break;
+ }
+
+ /* We can continue ramming if either the
+ * thread is not active or the SRQ/LSU/TS bits
+ * are set. */
+ } while ((val & RAS_STATUS_THREAD_ACTIVE) &&
+ !((val & RAS_STATUS_SRQ_EMPTY)
+ && (val & RAS_STATUS_LSU_QUIESCED)
+ && (val & RAS_STATUS_TS_QUIESCE)));
+
+
+ /* Make the threads RAM thread active */
+ CHECK_ERR(pib_read(&chip->target, THREAD_ACTIVE_REG, &val));
+ val |= PPC_BIT(8) >> thread->id;
+ CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
+
+ return 0;
+}
+
+static int p8_thread_start(struct thread *thread)
+{
+ uint64_t val;
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+
+ /* Activate thread */
+ CHECK_ERR(pib_write(&thread->target, DIRECT_CONTROLS_REG, DIRECT_CONTROL_SP_START));
+
+ /* Restore thread active */
+ CHECK_ERR(pib_read(&chip->target, THREAD_ACTIVE_REG, &val));
+ val &= ~(PPC_BIT(8) >> thread->id);
+ val |= PPC_BIT(thread->id);
+ CHECK_ERR(pib_write(&chip->target, THREAD_ACTIVE_REG, val));
+
+ return 0;
+}
+
+static int p8_ram_setup(struct thread *thread)
+{
+ struct dt_node *dn;
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t ram_mode, val;
+
+ /* We can only ram a thread if all the threads on the core/chip are
+ * quiesced */
+ dt_for_each_compatible(chip->target.dn, dn, "ibm,power8-thread") {
+ struct thread *tmp;
+ tmp = target_to_thread(dn->target);
+ if (!(get_thread_status(tmp) & THREAD_STATUS_QUIESCE))
+ return 1;
+ }
+
+ if (!(thread_status(thread) & THREAD_STATUS_ACTIVE))
+ return 2;
+
+ /* Activate RAM mode */
+ CHECK_ERR(pib_read(&chip->target, RAM_MODE_REG, &ram_mode));
+ ram_mode |= RAM_MODE_ENABLE;
+ CHECK_ERR(pib_write(&chip->target, RAM_MODE_REG, ram_mode));
+
+ /* Setup SPRC to use SPRD */
+ val = SPR_MODE_SPRC_WR_EN;
+ val = SETFIELD(SPR_MODE_SPRC_SEL, val, 1 << (3 - 0));
+ val = SETFIELD(SPR_MODE_SPRC_T_SEL, val, 1 << (7 - thread->id));
+ CHECK_ERR(pib_write(&chip->target, SPR_MODE_REG, val));
+ CHECK_ERR(pib_write(&chip->target, L0_SCOM_SPRC_REG, SCOM_SPRC_SCRATCH_SPR));
+
+ return 0;
+}
+
+static int p8_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t *scratch)
+{
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t val;
+
+ CHECK_ERR(pib_write(&chip->target, SCR0_REG, *scratch));
+
+ /* ram instruction */
+ val = SETFIELD(RAM_THREAD_SELECT, 0ULL, thread->id);
+ val = SETFIELD(RAM_INSTR, val, opcode);
+ CHECK_ERR(pib_write(&chip->target, RAM_CTRL_REG, val));
+
+ /* wait for completion */
+ do {
+ CHECK_ERR(pib_read(&chip->target, RAM_STATUS_REG, &val));
+ } while (!((val & PPC_BIT(1)) || ((val & PPC_BIT(2)) && (val & PPC_BIT(3)))));
+
+ if (!(val & PPC_BIT(1))) {
+ if (GETFIELD(PPC_BITMASK(2,3), val) == 0x3) {
+ return 1;
+ } else {
+ PR_ERROR("RAMMING failed with status 0x%llx\n", val);
+ return 2;
+ }
+ }
+
+ /* Save the results */
+ CHECK_ERR(pib_read(&chip->target, SCR0_REG, scratch));
+}
+
+static int p8_ram_destroy(struct thread *thread)
+{
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t ram_mode;
+
+ /* Disable RAM mode */
+ CHECK_ERR(pib_read(&chip->target, RAM_MODE_REG, &ram_mode));
+ ram_mode &= ~RAM_MODE_ENABLE;
+ CHECK_ERR(pib_write(&chip->target, RAM_MODE_REG, ram_mode));
+}
+
+/*
+ * Initialise all viable threads for ramming on the given chiplet.
+ */
+static int p8_thread_probe(struct target *target)
+{
+ struct thread *thread = target_to_thread(target);
+
+ thread->id = (dt_get_address(target->dn, 0, NULL) >> 4) & 0xf;
+ thread->status = get_thread_status(thread);
+
+ return 0;
+}
+
+struct thread p8_thread = {
+ .target = {
+ .name = "POWER8 Thread",
+ .compatible = "ibm,power8-thread",
+ .class = "thread",
+ .probe = p8_thread_probe,
+ },
+ .step = p8_thread_step,
+ .start = p8_thread_start,
+ .stop = p8_thread_stop,
+ .ram_setup = p8_ram_setup,
+ .ram_instruction = p8_ram_instruction,
+ .ram_destroy = p8_ram_destroy,
+};
+DECLARE_HW_UNIT(p8_thread);
+
+static int p8_chiplet_probe(struct target *target)
+{
+ uint64_t value;
+ struct chiplet *chiplet = target_to_chiplet(target);
+ int i, count = 0, rc = 0;
+
+ /* Work out if this chip is actually present */
+ if (pib_read(target, SCOM_EX_GP3, &value)) {
+ PR_DEBUG("Error reading chip GP3 register\n");
+ return -1;
+ }
+
+ if (!GETFIELD(PPC_BIT(0), value))
+ return -1;
+
+ assert_special_wakeup(chiplet);
+ return 0;
+}
+
+struct chiplet p8_chiplet = {
+ .target = {
+ .name = "POWER8 Chiplet",
+ .compatible = "ibm,power8-core",
+ .class = "chiplet",
+ .probe = p8_chiplet_probe,
+ },
+};
+DECLARE_HW_UNIT(p8_chiplet);
diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c
new file mode 100644
index 0000000..ed0fdeb
--- /dev/null
+++ b/libpdbg/p9chip.c
@@ -0,0 +1,240 @@
+/* Copyright 2016 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 "target.h"
+#include "operations.h"
+#include "bitutils.h"
+
+#define P9_RAS_STATUS 0x10a02
+#define P9_THREAD_INFO 0x10a9b
+#define P9_DIRECT_CONTROL 0x10a9c
+#define P9_RAS_MODEREG 0x10a9d
+#define P9_RAM_MODEREG 0x10a4e
+#define P9_RAM_CTRL 0x10a4f
+#define P9_RAM_STATUS 0x10a50
+#define P9_SCOMC 0x10a80
+#define P9_SPR_MODE 0x10a84
+#define P9_SCR0_REG 0x10a86
+
+/* PCB Slave Registers */
+#define NET_CTRL0 0xf0040
+#define NET_CTRL0_CHIPLET_ENABLE PPC_BIT(0)
+#define PPM_GPMMR 0xf0100
+#define PPM_SPWKUP_OTR 0xf010a
+#define SPECIAL_WKUP_DONE PPC_BIT(1)
+
+#define RAS_STATUS_TIMEOUT 100
+#define SPECIAL_WKUP_TIMEOUT 10
+
+static uint64_t thread_read(struct thread *thread, uint64_t addr, uint64_t *data)
+{
+ struct target *chip = require_target_parent(&thread->target);
+
+ return pib_read(chip, addr, data);
+}
+
+static uint64_t thread_write(struct thread *thread, uint64_t addr, uint64_t data)
+{
+ struct target *chip = require_target_parent(&thread->target);
+
+ return pib_write(chip, addr, data);
+}
+
+static uint64_t p9_get_thread_status(struct thread *thread)
+{
+ uint64_t value, status = THREAD_STATUS_ACTIVE;
+
+ thread_read(thread, P9_RAS_STATUS, &value);
+ if (GETFIELD(PPC_BITMASK(8*thread->id, 3 + 8*thread->id), value) == 0xf)
+ status |= THREAD_STATUS_QUIESCE;
+
+ return status;
+}
+
+static int p9_thread_probe(struct target *target)
+{
+ struct thread *thread = target_to_thread(target);
+ uint64_t value;
+
+ thread->id = dt_prop_get_u32(target->dn, "tid");
+ thread->status = p9_get_thread_status(thread);
+
+ return 0;
+}
+
+static int p9_thread_start(struct thread *thread)
+{
+ uint64_t value;
+
+ thread_write(thread, P9_DIRECT_CONTROL, PPC_BIT(6 + 8*thread->id));
+ thread_write(thread, P9_RAS_MODEREG, 0);
+
+ return 0;
+}
+
+static int p9_thread_stop(struct thread *thread)
+{
+ int i = 0;
+ uint64_t value;
+
+ thread_write(thread, P9_DIRECT_CONTROL, PPC_BIT(7 + 8*thread->id));
+ while(!(p9_get_thread_status(thread) & THREAD_STATUS_QUIESCE)) {
+ if (i++ > RAS_STATUS_TIMEOUT) {
+ PR_ERROR("Unable to quiesce thread\n");
+ break;
+ }
+ }
+
+ /* Fence interrupts. We can't do a read-modify-write here due to an
+ * errata */
+ thread_write(thread, P9_RAS_MODEREG, PPC_BIT(57));
+
+ return 0;
+}
+
+static int p9_ram_setup(struct thread *thread)
+{
+ struct dt_node *dn;
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t ras_status;
+
+ /* We can only ram a thread if all the threads on the core/chip are
+ * quiesced */
+ dt_for_each_compatible(chip->target.dn, dn, "ibm,power9-thread") {
+ struct thread *tmp;
+
+ /* If this thread wasn't enabled it may not yet have been probed
+ so do that now. This will also update the thread status */
+ p9_thread_probe(dn->target);
+ tmp = target_to_thread(dn->target);
+ if (tmp->status != (THREAD_STATUS_QUIESCE | THREAD_STATUS_ACTIVE))
+ return 1;
+ }
+
+ /* Enable ram mode */
+ CHECK_ERR(thread_write(thread, P9_RAM_MODEREG, PPC_BIT(0)));
+
+ /* Setup SPRC to use SPRD */
+ CHECK_ERR(thread_write(thread, P9_SPR_MODE, 0x00000ff000000000));
+ CHECK_ERR(thread_write(thread, P9_SCOMC, 0x0));
+
+ return 0;
+}
+
+static int p9_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t *scratch)
+{
+ struct chiplet *chip = target_to_chiplet(thread->target.dn->parent->target);
+ uint64_t predecode, value;
+
+ switch(opcode & OPCODE_MASK) {
+ case MTNIA_OPCODE:
+ predecode = 8;
+
+ /* Not currently supported as we can only MTNIA from LR */
+ PR_ERROR("MTNIA is not currently supported\n");
+ break;
+
+ case MFNIA_OPCODE:
+ opcode = 0x1ac804;
+ predecode = 2;
+ break;
+
+ case MTMSR_OPCODE:
+ predecode = 8;
+ break;
+
+ default:
+ predecode = 0;
+ }
+
+ CHECK_ERR(thread_write(thread, P9_SCR0_REG, *scratch));
+ value = SETFIELD(PPC_BITMASK(0, 1), 0ull, thread->id);
+ value = SETFIELD(PPC_BITMASK(2, 5), value, predecode);
+ value = SETFIELD(PPC_BITMASK(8, 39), value, opcode);
+ CHECK_ERR(thread_write(thread, P9_RAM_CTRL, value));
+ do {
+ CHECK_ERR(thread_read(thread, P9_RAM_STATUS, &value));
+ if (((value & PPC_BIT(0)) || (value & PPC_BIT(2))))
+ return 1;
+ } while (!(value & PPC_BIT(1) && !(value & PPC_BIT(3))));
+ CHECK_ERR(thread_read(thread, P9_SCR0_REG, scratch));
+
+ return 0;
+}
+
+static int p9_ram_destroy(struct thread *thread)
+{
+ /* Disable ram mode */
+ CHECK_ERR(thread_write(thread, P9_RAM_MODEREG, 0));
+
+ return 0;
+}
+
+struct thread p9_thread = {
+ .target = {
+ .name = "POWER9 Thread",
+ .compatible = "ibm,power9-thread",
+ .class = "thread",
+ .probe = p9_thread_probe,
+ },
+ .start = p9_thread_start,
+ .stop = p9_thread_stop,
+ .ram_setup = p9_ram_setup,
+ .ram_instruction = p9_ram_instruction,
+ .ram_destroy = p9_ram_destroy,
+};
+DECLARE_HW_UNIT(p9_thread);
+
+static int p9_chiplet_probe(struct target *target)
+{
+ int i;
+ uint64_t value;
+
+ if (pib_read(target, NET_CTRL0, &value))
+ return -1;
+
+ if (!(value & NET_CTRL0_CHIPLET_ENABLE))
+ return -1;
+
+ CHECK_ERR(pib_write(target, PPM_SPWKUP_OTR, PPC_BIT(0)));
+ do {
+ usleep(1);
+ CHECK_ERR(pib_read(target, PPM_GPMMR, &value));
+
+ if (i++ > SPECIAL_WKUP_TIMEOUT) {
+ PR_ERROR("Timeout waiting for special wakeup on %s@0x%08lx\n", target->name,
+ dt_get_address(target->dn, 0, NULL));
+ return -1;
+ }
+ } while (!(value & SPECIAL_WKUP_DONE));
+
+ return 0;
+}
+
+struct chiplet p9_chiplet = {
+ .target = {
+ .name = "POWER9 Chiplet",
+ .compatible = "ibm,power9-core",
+ .class = "chiplet",
+ .probe = p9_chiplet_probe,
+ },
+};
+DECLARE_HW_UNIT(p9_chiplet);
diff --git a/libpdbg/target.c b/libpdbg/target.c
index c733dad..7642e18 100644
--- a/libpdbg/target.c
+++ b/libpdbg/target.c
@@ -37,22 +37,28 @@ int pib_read(struct target *pib_dt, uint64_t addr, uint64_t *data)
{
struct pib *pib;
struct dt_node *dn = pib_dt->dn;
+ int rc;
dn = get_class_target_addr(dn, "pib", &addr);
pib_dt = dn->target;
pib = target_to_pib(pib_dt);
- return pib->read(pib, addr, data);
+ rc = pib->read(pib, addr, data);
+// printf("pib_read 0x%016llx = 0x%016llx\n", addr, *data);
+ return rc;
}
int pib_write(struct target *pib_dt, uint64_t addr, uint64_t data)
{
struct pib *pib;
struct dt_node *dn = pib_dt->dn;
+ int rc;
dn = get_class_target_addr(dn, "pib", &addr);
pib_dt = dn->target;
pib = target_to_pib(pib_dt);
- return pib->write(pib, addr, data);
+ rc = pib->write(pib, addr, data);
+// printf("pib_write 0x%016llx = 0x%016llx\n", addr, data);
+ return rc;
}
int opb_read(struct target *opb_dt, uint32_t addr, uint32_t *data)
@@ -105,6 +111,14 @@ int fsi_write(struct target *fsi_dt, uint32_t addr, uint32_t data)
return fsi->write(fsi, addr64, data);
}
+struct target *require_target_parent(struct target *target)
+{
+ struct dt_node *dn;
+
+ assert((dn = target->dn));
+ return dn->parent->target;
+}
+
/* Finds the given class. Returns NULL if not found. */
struct target_class *find_target_class(const char *name)
{
diff --git a/libpdbg/target.h b/libpdbg/target.h
index 651ab3c..ba91cf5 100644
--- a/libpdbg/target.h
+++ b/libpdbg/target.h
@@ -47,6 +47,7 @@ struct target {
struct list_node class_link;
};
+struct target *require_target_parent(struct target *target);
struct target_class *find_target_class(const char *name);
struct target_class *require_target_class(const char *name);
@@ -108,6 +109,16 @@ struct thread {
struct target target;
uint64_t status;
int id;
+ int (*step)(struct thread *, int);
+ int (*start)(struct thread *);
+ int (*stop)(struct thread *);
+
+ /* ram_setup() should be called prior to using ram_instruction() to
+ * actually ram the instruction and return the result. ram_destroy()
+ * should be called at completion to clean-up. */
+ int (*ram_setup)(struct thread *);
+ int (*ram_instruction)(struct thread *, uint64_t opcode, uint64_t *scratch);
+ int (*ram_destroy)(struct thread *);
};
#define target_to_thread(x) container_of(x, struct thread, target)
diff --git a/p9-fsi.dtsi b/p9-fsi.dtsi
deleted file mode 100644
index 0181a19..0000000
--- a/p9-fsi.dtsi
+++ /dev/null
@@ -1,47 +0,0 @@
-/ {
- #address-cells = <0x1>;
- #size-cells = <0x0>;
-
- fsi0: fsi@0 {
- #address-cells = <0x2>;
- #size-cells = <0x1>;
- compatible = "ibm,bmcfsi";
- reg = <0x0 0x0 0x0>;
-
- index = <0x0>;
- status = "hidden";
-
- pib@1000 {
- #address-cells = <0x2>;
- #size-cells = <0x1>;
- reg = <0x0 0x1000 0x7>;
- compatible = "ibm,fsi-pib", "ibm,power9-fsi-pib";
- index = <0x0>;
-
- adu@90000 {
- compatible = "ibm,power9-adu";
- reg = <0x0 0x90000 0x5>;
- };
- };
-
- hmfsi@100000 {
- compatible = "ibm,fsi-hmfsi";
- reg = <0x0 0x100000 0x8000>;
- index = <0x1>;
-
- pib@1000 {
- #address-cells = <0x2>;
- #size-cells = <0x1>;
- reg = <0x0 0x1000 0x7>;
- compatible = "ibm,fsi-pib", "ibm,power9-fsi-pib";
- index = <0x1>;
-
- adu@90000 {
- compatible = "ibm,power9-adu";
- reg = <0x0 0x90000 0x5>;
- };
- };
- };
-
- };
-};
diff --git a/p9-fsi.dtsi.m4 b/p9-fsi.dtsi.m4
new file mode 100644
index 0000000..24eaabe
--- /dev/null
+++ b/p9-fsi.dtsi.m4
@@ -0,0 +1,120 @@
+define(`CONCAT', `$1$2')dnl
+define(`HEX', `CONCAT(0x, $1)')dnl
+define(`CORE_BASE', `eval(0x20000000 + $1 * 0x1000000, 16)')dnl
+define(`CORE', `core@CORE_BASE($1) {
+#address-cells = <0x1>;
+#size-cells = <0x0>;
+compatible = "ibm,power9-core";
+reg = <0x0 HEX(CORE_BASE($1)) 0xfffff>;
+index = <HEX(eval($2, 16))>;
+
+THREAD(0);
+THREAD(1);
+THREAD(2);
+THREAD(3);
+}')dnl
+define(`THREAD_BASE', `eval($1, 16)')dnl
+define(`THREAD',`thread@THREAD_BASE($1) {
+compatible = "ibm,power9-thread";
+reg = <0x0>;
+tid = <HEX(eval($1, 16))>;
+index = <HEX(eval($1, 16))>;
+}')dnl
+
+/ {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ fsi0: fsi@0 {
+ #address-cells = <0x2>;
+ #size-cells = <0x1>;
+ compatible = "ibm,bmcfsi";
+ reg = <0x0 0x0 0x0>;
+
+ index = <0x0>;
+ status = "hidden";
+
+ pib@1000 {
+ #address-cells = <0x2>;
+ #size-cells = <0x1>;
+ reg = <0x0 0x1000 0x7>;
+ compatible = "ibm,fsi-pib", "ibm,power9-fsi-pib";
+ index = <0x0>;
+
+ adu@90000 {
+ compatible = "ibm,power9-adu";
+ reg = <0x0 0x90000 0x5>;
+ };
+
+ CORE(0, 0);
+ CORE(1, 1);
+ CORE(2, 2);
+ CORE(3, 3);
+ CORE(4, 4);
+ CORE(5, 5);
+ CORE(6, 6);
+ CORE(7, 7);
+ CORE(8, 8);
+ CORE(9, 9);
+ CORE(10, 10);
+ CORE(11, 11);
+ CORE(12, 12);
+ CORE(13, 13);
+ CORE(14, 14);
+ CORE(15, 15);
+ CORE(16, 16);
+ CORE(17, 17);
+ CORE(18, 18);
+ CORE(19, 19);
+ CORE(20, 20);
+ CORE(21, 21);
+ CORE(22, 22);
+ CORE(23, 23);
+ };
+
+ hmfsi@100000 {
+ compatible = "ibm,fsi-hmfsi";
+ reg = <0x0 0x100000 0x8000>;
+ index = <0x1>;
+
+ pib@1000 {
+ #address-cells = <0x2>;
+ #size-cells = <0x1>;
+ reg = <0x0 0x1000 0x7>;
+ compatible = "ibm,fsi-pib", "ibm,power9-fsi-pib";
+ index = <0x1>;
+
+ adu@90000 {
+ compatible = "ibm,power9-adu";
+ reg = <0x0 0x90000 0x5>;
+ };
+
+ CORE(0, 0);
+ CORE(1, 1);
+ CORE(2, 2);
+ CORE(3, 3);
+ CORE(4, 4);
+ CORE(5, 5);
+ CORE(6, 6);
+ CORE(7, 7);
+ CORE(8, 8);
+ CORE(9, 9);
+ CORE(10, 10);
+ CORE(11, 11);
+ CORE(12, 12);
+ CORE(13, 13);
+ CORE(14, 14);
+ CORE(15, 15);
+ CORE(16, 16);
+ CORE(17, 17);
+ CORE(18, 18);
+ CORE(19, 19);
+ CORE(20, 20);
+ CORE(21, 21);
+ CORE(22, 22);
+ CORE(23, 23);
+ };
+ };
+
+ };
+};
diff --git a/src/main.c b/src/main.c
index 1f38e94..e0c4424 100644
--- a/src/main.c
+++ b/src/main.c
@@ -59,7 +59,7 @@ static char const *device_node;
static int i2c_addr = 0x50;
#define MAX_PROCESSORS 16
-#define MAX_CHIPS 16
+#define MAX_CHIPS 24
#define MAX_THREADS THREADS_PER_CORE
static int **processorsel[MAX_PROCESSORS];
@@ -479,9 +479,9 @@ static void print_proc_reg(struct thread *thread, uint64_t reg, uint64_t value,
else if (reg >= 0 && reg <= 31)
printf("gpr%02" PRIu64 ": ", reg);
- if (rc == 1)
- printf("Chiplet in incorrect state\n");
- else if (rc == 2)
+ if (rc == 1) {
+ printf("Check threadstatus - not all threads on this chiplet are quiesced\n");
+ } else if (rc == 2)
printf("Thread in incorrect state\n");
else
printf("0x%016" PRIx64 "\n", value);
@@ -556,7 +556,7 @@ static int start_thread(struct target *thread_target, uint32_t index, uint64_t *
{
struct thread *thread = target_to_thread(thread_target);
- return ram_start_thread(thread) ? 1 : 0;
+ return ram_start_thread(thread_target) ? 1 : 0;
}
static int step_thread(struct target *thread_target, uint32_t index, uint64_t *count, uint64_t *unused1)
@@ -568,9 +568,7 @@ static int step_thread(struct target *thread_target, uint32_t index, uint64_t *c
static int stop_thread(struct target *thread_target, uint32_t index, uint64_t *unused, uint64_t *unused1)
{
- struct thread *thread = target_to_thread(thread_target);
-
- return ram_stop_thread(thread) ? 1 : 0;
+ return ram_stop_thread(thread_target) ? 1 : 0;
}
static void enable_dn(struct dt_node *dn)
OpenPOWER on IntegriCloud