fix(ppc64): std/ld raise UC_ERR_EXCEPTION on UC_MODE_PPC64 (#1779)#2340
fix(ppc64): std/ld raise UC_ERR_EXCEPTION on UC_MODE_PPC64 (#1779)#2340iMoD1998 wants to merge 6 commits into
Conversation
When a PPC64 CPU model is set via uc_ctl_set_cpu_model(), uc->cpu_model holds a PPC64-relative index (0 = E5500, 10 = POWER5+ etc.), but ppc_cpus[] is a flat array starting with all PPC32 entries. The range check already adds UC_CPU_PPC32_7457A_V1_2+1 as the offset to validate bounds, but that offset was never applied before the array lookup, causing the wrong (PPC32) CPU family class to be loaded. This meant all user-set PPC64 CPU models resolved to a PPC32 entry, loading insns_flags without PPC_64B and leaving std/ld/other 64-bit instructions unregistered, resulting in UC_ERR_EXCEPTION on any 64-bit memory instruction. Fixes: unicorn-engine#1779
…t reset hreg_store_msr's HV-preservation check gates on whether env->msr already has MSR_HV set. Since env->msr is zeroed by cpu_common_reset() before ppc_cpu_reset() calls hreg_store_msr(…, 1), the HV bit is silently dropped for every CPU that has it in msr_mask (POWER5+, POWER7-10). For POWER5–8 this was harmless because their real-mode path falls back to RMO (RMLS-bounded) access with LPCR[VPM0]=0. POWER9/10 (MMU_3_00) always use VRMA and have no RMO fallback: a real-mode instruction fetch with msr_hv=0 ends up in ppc_hash64_set_isi with vpm=true, producing a Hypervisor Instruction Storage Exception (POWERPC_EXCP_HISI=70) before the first instruction executes. Pre-seeding env->msr with the masked reset value before the hreg_store_msr call means the condition !(env->msr & MSR_HVB) is false, so the HV bit flows through correctly. All eight PPC64 models (970/fx/mp, POWER5+, POWER7–10) now pass the std/ld test.
a better approach would be to handle this transparent in uc_ctl. so when setting the model add
Can you also put some tests in tests/unit. |
|
At least be honest and add whatever AI did this as the Co-Author. |
There is nothing to be honest about. Claude found 3 line fix and i just submitted for other people. Regression test is based on #1779. |
I've now set the cpu model index in Ive also changed the default cpu case to use UC_CPU_PPC32_ENDING aswell in I have also added some random 64 bit tests which should catch any weird bugs. Just made a simple one for loading a 64 bit value into a register as that could possibly silently fail?? |
|
Bug 1 seems exactly #2308 |
|
Anything else y'all need from me? |
Fixes #1779
stdandldinstructions raiseUC_ERR_EXCEPTIONwhen emulating PPC64code. Two independent bugs in
qemu/target/ppc/translate_init.inc.cwereresponsible.
Bug 1 —
cpu_modelindex not offset for user-set PPC64 modelsppc_cpus[]is a flat array with PPC32 entries first, followed by PPC64entries.
UC_CPU_PPC64_*enum values are PPC64-relative (starting at 0),so they must be offset by
UC_CPU_PPC32_7457A_V1_2 + 1to reach thecorrect slot in the array.
The existing code applied this offset only for the default model
(
INT_MAX). When a caller passed an explicitUC_CPU_PPC64_*value viauc_ctl_set_cpu_model, the offset was never applied, socpu_ppc_initselected a PPC32 CPU definition. That definition lacks the
PPC_64Bflagin
insns_flags, socreate_ppc_opcodesnever registered 64-bitinstructions like
std/ld, causing them to fall through togen_invalidand raise
UC_ERR_EXCEPTION.Fix: add an
elsebranch that applies the offset for explicitly setPPC64 models.
Bug 2 —
MSR[HV]silently dropped at reset, breaking POWER9/10ppc_cpu_resetcallshreg_store_msr(env, msr, 1)to apply the reset MSRvalue.
hreg_store_msronly propagatesMSR[HV]whenenv->msralreadyhas that bit set:
cpu_common_reset zeroes env->msr before ppc_cpu_reset runs, so the
condition is always true and MSR[HV] is always cleared — even for CPUs
whose reset vector requires it.
On POWER9/10 (POWERPC_MMU_3_00) ppc_hash64_use_vrma() always returns
true, meaning the MMU always uses VRMA and never falls back to real-mode.
ppc_hash64_set_isi then raises POWERPC_EXCP_HISI (exception 70) when
vpm=1 && msr_hv=0, which is exactly what happens after reset. Earlier
CPUs (POWER5–8) use a real-mode path that doesn't require msr_hv=1 so
they were unaffected.
Fix: pre-seed env->msr with the masked reset value before calling
hreg_store_msr, so the MSR[HV] guard passes and the bit is preserved.
Testing
A regression test covering all eight PPC64 CPU models (970, 970fx, POWER5+,
POWER7, POWER8, POWER9, POWER10, and the default) is added in
tests/regress/ppc64_std_ld.c. Each case executes std r3, 0(r4) followed
by ld r5, 0(r4) and asserts that the round-trip value is correct.