diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2018-05-02 16:28:05 +1000 |
---|---|---|
committer | Alistair Popple <alistair@popple.id.au> | 2018-05-08 11:45:28 +1000 |
commit | bf7c669f64748e3657c803e4666aa6a2980b21a8 (patch) | |
tree | af690d578f5aa8be73e5b556bc39dc15258593ce /libpdbg/p9chip.c | |
parent | 678ffe6bc91b460a8575050f8f8e75b9f2e64acf (diff) | |
download | pdbg-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.c | 36 |
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) |