]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
ppc: flush QEMU JIT after 68k cache changes
authorDimitris Panokostas <midwan@gmail.com>
Wed, 1 Jul 2026 18:50:05 +0000 (20:50 +0200)
committerDimitris Panokostas <midwan@gmail.com>
Wed, 1 Jul 2026 18:50:05 +0000 (20:50 +0200)
OS3.x/WarpOS can patch PPC code and page tables from the m68k side in shared RAM. QEMU does not see those writes through the PPC softmmu, so stale translation blocks can survive until the m68k/PPC handoff deadlocks.

Import the optional ppc_cpu_flush_jit hook, mark QEMU PPC code cache state dirty on 68040 instruction-cache and MMU ATC flushes, and consume one coalesced flush at the next m68k-to-PPC handoff. Skip the flush while the m68k is halted so PPC-only OS4 execution is not forced to retranslate continuously.

cpummu.cpp
include/uae/ppc.h
newcpu.cpp
ppc/ppc.cpp

index 4e6d4f8dd3342f4ed4172517c36bb95807f7656c..6a371ed6709f58f6b52f2e52a09b2aee8fec50e4 100644 (file)
@@ -32,6 +32,9 @@
 #include "newcpu.h"
 #include "cpummu.h"
 #include "debug.h"
+#ifdef WITH_PPC
+#include "uae/ppc.h"
+#endif
 
 #define MMUDUMP 1
 
@@ -1403,6 +1406,9 @@ void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra)
                        mmu_flush_atc(addr, super, glob);
                }
                flush_internals();
+#ifdef WITH_PPC
+               uae_ppc_mark_code_cache_dirty();
+#endif
 #ifdef USE_JIT
                flush_icache(0);
 #endif
index e1e9982b49ee1b79f521eb0e5d3396ab95754bae..621f3d8a366cdb4362d0a3c85c1e0e33591ed7ee 100644 (file)
@@ -47,6 +47,7 @@ void uae_ppc_wakeup_main(void);
 
 void uae_ppc_execute_quick(void);
 void uae_ppc_execute_check(void);
+void uae_ppc_mark_code_cache_dirty(void);
 void uae_ppc_spinlock_reset(void);
 void uae_ppc_spinlock_get(void);
 void uae_ppc_spinlock_release(void);
@@ -108,6 +109,7 @@ void PPCCALL ppc_cpu_stop(void);
 void PPCCALL ppc_cpu_atomic_raise_ext_exception(void);
 void PPCCALL ppc_cpu_atomic_cancel_ext_exception(void);
 void PPCCALL ppc_cpu_map_memory(PPCMemoryRegion *regions, int count);
+void PPCCALL ppc_cpu_flush_jit(void);
 void PPCCALL ppc_cpu_set_pc(int cpu, uint32_t value);
 void PPCCALL ppc_cpu_run_continuous(void);
 void PPCCALL ppc_cpu_run_single(int count);
index ea536cb186949a0e7d90d7f9db211927df5f979b..445f1a4267bd5d573ee6bb2b41bb93f41c63c398 100644 (file)
@@ -1779,6 +1779,11 @@ void flush_cpu_caches_040(uae_u16 opcode)
        bool pushinv = (regs.cacr & 0x01000000) == 0; // 68060 DPI
 
        flush_cpu_caches_040_2(cache, scope, addr, push, pushinv);
+#ifdef WITH_PPC
+       if (cache & 2) {
+               uae_ppc_mark_code_cache_dirty();
+       }
+#endif
        mmu_flush_cache();
 }
 
index 4ec0953bcb9b848485d3b05f6f02ab9242302648..bbb787ce7fe6901ee4b40a4abef073eee92581a7 100644 (file)
@@ -6,6 +6,7 @@
 #include "threaddep/thread.h"
 #include "machdep/rpt.h"
 #include "memory.h"
+#include "newcpu.h"
 #include "cpuboard.h"
 #include "debug.h"
 #include "custom.h"
@@ -41,6 +42,7 @@ static volatile int spinlock_cnt;
 #endif
 
 static volatile bool ppc_spinlock_waiting;
+static volatile bool qemu_ppc_jit_flush_pending;
 
 #ifdef WIN32_SPINLOCK
 #define CRITICAL_SECTION_SPIN_COUNT 5000
@@ -157,6 +159,7 @@ typedef void (PPCCALL *ppc_cpu_pause_function)(int pause);
 typedef bool (PPCCALL *ppc_cpu_check_state_function)(int state);
 typedef void (PPCCALL *ppc_cpu_set_state_function)(int state);
 typedef void (PPCCALL *ppc_cpu_reset_function)(void);
+typedef void (PPCCALL *ppc_cpu_flush_jit_function)(void);
 
 /* Function pointers to active PPC implementation */
 
@@ -182,6 +185,7 @@ static struct impl {
        ppc_cpu_check_state_function check_state;
        ppc_cpu_set_state_function set_state;
        ppc_cpu_reset_function reset;
+       ppc_cpu_flush_jit_function flush_jit;
        qemu_uae_ppc_in_cpu_thread_function in_cpu_thread;
        qemu_uae_ppc_external_interrupt_function external_interrupt;
        qemu_uae_lock_function lock;
@@ -248,6 +252,10 @@ static bool load_qemu_implementation(void)
        impl.check_state = (ppc_cpu_check_state_function) uae_dlsym(handle, "ppc_cpu_check_state");
        impl.set_state = (ppc_cpu_set_state_function) uae_dlsym(handle, "ppc_cpu_set_state");
        impl.reset = (ppc_cpu_reset_function) uae_dlsym(handle, "ppc_cpu_reset");
+       impl.flush_jit = (ppc_cpu_flush_jit_function) uae_dlsym(handle, "ppc_cpu_flush_jit");
+       if (impl.flush_jit) {
+               write_log(_T("PPC: Imported optional ppc_cpu_flush_jit\n"));
+       }
        impl.in_cpu_thread = (qemu_uae_ppc_in_cpu_thread_function) uae_dlsym(handle, "qemu_uae_ppc_in_cpu_thread");
        impl.lock = (qemu_uae_lock_function) uae_dlsym(handle, "qemu_uae_lock");
 
@@ -312,6 +320,22 @@ static bool using_pearpc(void)
        return ppc_implementation == PPC_IMPLEMENTATION_PEARPC;
 }
 
+void uae_ppc_mark_code_cache_dirty(void)
+{
+       qemu_ppc_jit_flush_pending = true;
+}
+
+static void request_qemu_ppc_jit_flush(void)
+{
+       /* OS3.x/WarpOS can patch PPC code/page tables from the m68k side,
+        * bypassing QEMU's PPC softmmu. Flush once at the next m68k->PPC handoff. */
+       if (!qemu_ppc_jit_flush_pending || !using_qemu() || !impl.flush_jit || regs.halted) {
+               return;
+       }
+       qemu_ppc_jit_flush_pending = false;
+       impl.flush_jit();
+}
+
 enum PPCLockMethod {
        PPC_RELEASE_SPINLOCK,
        PPC_KEEP_SPINLOCK,
@@ -599,6 +623,7 @@ static void uae_ppc_cpu_reset(void)
 
        if (using_qemu()) {
                impl.reset();
+               qemu_ppc_jit_flush_pending = true;
        } else if (using_pearpc()) {
                write_log(_T("PPC: Init\n"));
                impl.set_pc(0, 0xfff00100);
@@ -627,6 +652,7 @@ static void ppc_thread(void *v)
 void uae_ppc_execute_check(void)
 {
        if (ppc_spinlock_waiting) {
+               request_qemu_ppc_jit_flush();
                uae_ppc_spinlock_release();
                uae_ppc_spinlock_get();
        }
@@ -634,6 +660,7 @@ void uae_ppc_execute_check(void)
 
 void uae_ppc_execute_quick()
 {
+       request_qemu_ppc_jit_flush();
        uae_ppc_spinlock_release();
        sleep_millis_main(1);
        uae_ppc_spinlock_get();