summaryrefslogtreecommitdiffstats
path: root/libpdbg/p9chip.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2018-05-02 16:28:05 +1000
committerAlistair Popple <alistair@popple.id.au>2018-05-08 11:45:28 +1000
commitbf7c669f64748e3657c803e4666aa6a2980b21a8 (patch)
treeaf690d578f5aa8be73e5b556bc39dc15258593ce /libpdbg/p9chip.c
parent678ffe6bc91b460a8575050f8f8e75b9f2e64acf (diff)
downloadpdbg-bf7c669f64748e3657c803e4666aa6a2980b21a8.tar.gz
pdbg-bf7c669f64748e3657c803e4666aa6a2980b21a8.zip
libpdbg/p9chip.c: fix ram instruction status sequence
This comes from the workbook. Without this, some types of mfspr loops forever despite having completed with bit 1 status set. Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Diffstat (limited to 'libpdbg/p9chip.c')
-rw-r--r--libpdbg/p9chip.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c
index 8c03476..2cb87c9 100644
--- a/libpdbg/p9chip.c
+++ b/libpdbg/p9chip.c
@@ -209,6 +209,7 @@ static int p9_ram_setup(struct thread *thread)
static int p9_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t *scratch)
{
uint64_t predecode, value;
+ int rc;
switch(opcode & OPCODE_MASK) {
case MTNIA_OPCODE:
@@ -236,14 +237,35 @@ static int p9_ram_instruction(struct thread *thread, uint64_t opcode, uint64_t *
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;
+ CHECK_ERR(thread_read(thread, P9_RAM_STATUS, &value));
+
+ rc = 0;
+ if (value & PPC_BIT(0)) {
+ printf("Error RAMing opcode=%" PRIx64 " attempting to RAM while in recovery (status=%" PRIx64")\n", opcode, value);
+ rc = 1;
+ goto out;
+ }
+ if (value & PPC_BIT(2)) {
+ printf("Error RAMing opcode=%" PRIx64 " exception or interrupt (status=%" PRIx64")\n", opcode, value);
+ rc = 1;
+ goto out;
+ }
+ if (!(value & PPC_BIT(1))) {
+ printf("Warning RAMing opcode=%" PRIx64 " unexpected status=%" PRIx64"\n", opcode, value);
+ }
+
+out:
+ if ((opcode & OPCODE_MASK) == LD_OPCODE) {
+ while (!(value & PPC_BIT(3))) {
+ CHECK_ERR(thread_read(thread, P9_RAM_STATUS, &value));
+ }
+ }
+
+ if (!rc)
+ CHECK_ERR(thread_read(thread, P9_SCR0_REG, scratch));
+
+ return rc;
}
static int p9_ram_destroy(struct thread *thread)
OpenPOWER on IntegriCloud