[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Qemu-ppc Implementing Decrementer With Auto-Reload Register

From: sdicaro
Subject: Qemu-ppc Implementing Decrementer With Auto-Reload Register
Date: Fri, 31 Mar 2023 09:36:28 -0700

I am using qemu 7.1.0 to emulate a PPC e6500 built on Ubuntu Linux. The issue I found relates to setting the decrementer. Qemu hangs forever when the decrementer is set to a logically negative value stored in the auto reload register. 

Expected behavior is to enable/clear the decrementer and set it to 0. The transition of the decrementer value should cause it to reset to the value stored in the auto-reload register. The code sets the DECAR register value to 0xffffffff. The max 32 bit value.

Below is the implementation of the BookE decrementer.

#define mfspr(rn) ({unsigned long rval; \
                   asm volatile("mfspr %0, %1": "=r" (rval) : "i"(rn)); \

#define mtspr(rn, v) asm volatile("mtspr %1, %0" : : "r" ((unsigned long)(v)), "i"(rn) : "memory")

#define BOOKE_TCR 340
#define TCR_DIE_BIT (0X80000000 >> 5)
#define BOOKE_DECAR 54
#define TCR_ARE_BIT (0X80000000 >> 9)
#define DEC 22
#define BOOKE_TSR 336
#define TSR_DIS_BIT (0x80000000 >> 4)

uint32_t tcr = mfspr(BOOKE_TCR);
mtspr(BOOKE_TCR, (tcr & ~(TCR_DIE_BIT)));

mtspr(BOOKE_DECAR, 0xffffffff);

tcr = mfspr(BOOKE_TCR);
mtspr(BOOKE_TCR, (tcr|TCR_ARE_BIT));

mtspr(DEC, 0x00000000);

The issue was resolved by undoing the sign extension used in the __cpu_ppc_store_decr function in hw/ppc/ppc.c. DECAR values with 1 in the most significant bit were being passed as a sign extended 32 bit value in the function arguments. Therefore, the decrementer was being reset to a truncated 64 bit -1 instead of a 0xffffffff. This caused an infinite transition from 0 -> -1, which prevented further execution.

+++ qemu-7.1.0/hw/ppc/ppc.c     2023-01-13 10:53:27.112516808 -0700
@@ -813,6 +813,9 @@
     /* Truncate value to decr_width and sign extend for simplicity */ 
     signed_value = sextract64(value, 0, nr_bits);
     signed_decr = sextract64(decr, 0, nr_bits);
+    // Undo 64 bit sign extension.
+    value = (value & 0xffffffff);
     trace_ppc_decr_store(nr_bits, decr, value);

Is there an issue with the implementation of the BookE decrementer shown above? Basic decrementer functionality as per the BookE reference manual is such: Enable DECAR->Set DECAR to max value->Enable/Clear DECR->reset DECR to DECAR value and wait. Is it possible this is a bug in qemu-ppc implementation?

reply via email to

[Prev in Thread] Current Thread [Next in Thread]