All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
To: laurent@vivier.eu, qemu-devel@nongnu.org
Subject: [PATCH 30/30] mac_via: work around QEMU unaligned MMIO access bug
Date: Wed, 24 May 2023 22:11:04 +0100	[thread overview]
Message-ID: <20230524211104.686087-31-mark.cave-ayland@ilande.co.uk> (raw)
In-Reply-To: <20230524211104.686087-1-mark.cave-ayland@ilande.co.uk>

During the kernel timer calibration routine A/UX performs an unaligned access
across the T1CL and T1CH registers to read the entire 16-bit value in a
single memory access.

This triggers a bug in the QEMU softtlb implementation whereby the 2 separate
accesses are combined incorrectly losing the high byte of the counter (see
https://gitlab.com/qemu-project/qemu/-/issues/360 for more detail). Since
A/UX requires a minimum difference of 0x500 between 2 subsequent reads to
succeed then this causes the timer calibration routine to get stuck in an
infinite loop.

Add a temporary workaround for the QEMU unaligned MMIO access bug whereby
these special accesses are detected and the 8-byte result copied into both
halves of the 16-bit access which allows the existing softtlb implementation
to return the correct result.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
 hw/m68k/q800.c            |  1 +
 hw/misc/mac_via.c         | 42 +++++++++++++++++++++++++++++++++++++++
 hw/misc/trace-events      |  1 +
 include/hw/misc/mac_via.h |  4 +++-
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index bf4acb5db7..918cc8f695 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -443,6 +443,7 @@ static const MemoryRegionOps macio_alias_ops = {
     .valid = {
         .min_access_size = 1,
         .max_access_size = 4,
+        .unaligned = true,     /* For VIA1 via1_unaligned_hack_state() */
     },
 };
 
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 4ec1ee18dd..45c8dee9f4 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -1026,12 +1026,47 @@ static void via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
     }
 }
 
+static bool via1_unaligned_hack_state(MOS6522Q800VIA1State *v1s, hwaddr addr,
+                                      int size)
+{
+    /*
+     * Workaround for bug in QEMU whereby load_helper() doesn't correctly
+     * handle combining unaligned memory accesses: see QEMU issue
+     * https://gitlab.com/qemu-project/qemu/-/issues/360 for all the
+     * details.
+     *
+     * Its only known use is during the A/UX timer calibration loop which
+     * runs on kernel startup.
+     */
+    switch (v1s->unaligned_hack_state) {
+    case 0:
+        /* First half of unaligned access */
+        if (addr == 0x11fe && size == 2) {
+            v1s->unaligned_hack_state = 1;
+            trace_via1_unaligned_hack_state(v1s->unaligned_hack_state);
+            return true;
+        }
+        return false;
+    case 1:
+        /* Second half of unaligned access */
+        if (addr == 0x1200 && size == 2) {
+            v1s->unaligned_hack_state = 0;
+            trace_via1_unaligned_hack_state(v1s->unaligned_hack_state);
+            return true;
+        }
+        return false;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
 {
     MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
     MOS6522State *ms = MOS6522(v1s);
     int64_t now;
     uint64_t ret;
+    hwaddr oldaddr = addr;
 
     addr = (addr >> 9) & 0xf;
     ret = mos6522_read(ms, addr, size);
@@ -1059,6 +1094,12 @@ static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
         }
         break;
     }
+
+    if (via1_unaligned_hack_state(v1s, oldaddr, size)) {
+        /* Splat return byte into word to fix unaligned access combine */
+        ret |= ret << 8;
+    }
+
     return ret;
 }
 
@@ -1126,6 +1167,7 @@ static const MemoryRegionOps mos6522_q800_via1_ops = {
     .valid = {
         .min_access_size = 1,
         .max_access_size = 4,
+        .unaligned = true,     /* For VIA1 via1_unaligned_hack_state() */
     },
 };
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 7206bd5d93..8867cef356 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -252,6 +252,7 @@ via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size
 via1_adb_netbsd_enum_hack(void) "using NetBSD enum hack"
 via1_auxmode(int mode) "setting auxmode to %d"
 via1_timer_hack_state(int state) "setting timer_hack_state to %d"
+via1_unaligned_hack_state(int state) "setting unaligned_hack_state to %d"
 
 # grlib_ahb_apb_pnp.c
 grlib_ahb_pnp_read(uint64_t addr, unsigned size, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" size:%u data:0x%08x"
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 63cdcf7c69..0a12737552 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -77,8 +77,10 @@ struct MOS6522Q800VIA1State {
 
     /* SETUPTIMEK hack */
     int timer_hack_state;
-};
 
+    /* Unaligned access hack */
+    int unaligned_hack_state;
+};
 
 /* VIA 2 */
 #define VIA2_IRQ_SCSI_DATA_BIT  CA2_INT_BIT
-- 
2.30.2



      parent reply	other threads:[~2023-05-24 21:14 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-24 21:10 [PATCH 00/30] q800: add support for booting MacOS Classic Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 01/30] q800: fix up minor spacing issues in hw_compat_q800 GlobalProperty array Mark Cave-Ayland
2023-05-30 11:15   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 02/30] q800: introduce Q800MachineState Mark Cave-Ayland
2023-05-30 11:15   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 03/30] q800: rename q800_init() to q800_machine_init() Mark Cave-Ayland
2023-05-30 11:16   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 04/30] q800: move CPU object into Q800MachineState Mark Cave-Ayland
2023-05-25  8:07   ` Philippe Mathieu-Daudé
2023-05-30 11:18   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 05/30] q800: move ROM memory region to Q800MachineState Mark Cave-Ayland
2023-05-25  8:08   ` Philippe Mathieu-Daudé
2023-05-30 11:19   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 06/30] q800: move GLUE device " Mark Cave-Ayland
2023-05-30 11:19   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 07/30] q800: introduce mac-io container memory region Mark Cave-Ayland
2023-05-30 11:23   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 08/30] q800: reimplement mac-io region aliasing using IO " Mark Cave-Ayland
2023-05-30 11:23   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 09/30] q800: add djMEMC memory controller Mark Cave-Ayland
2023-05-25  8:12   ` Philippe Mathieu-Daudé
2023-05-30  8:07     ` Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 10/30] q800: add machine id register Mark Cave-Ayland
2023-05-25  8:14   ` Philippe Mathieu-Daudé
2023-05-24 21:10 ` [PATCH 11/30] q800: implement additional machine id bits on VIA1 port A Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 12/30] q800: add IOSB subsystem Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 13/30] q800: allow accesses to RAM area even if less memory is available Mark Cave-Ayland
2023-05-25  8:20   ` Philippe Mathieu-Daudé
2023-05-30 11:25   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 14/30] audio: add Apple Sound Chip (ASC) emulation Mark Cave-Ayland
2023-05-29 11:43   ` Volker Rümelin
2023-05-24 21:10 ` [PATCH 15/30] asc: generate silence if FIFO empty but engine still running Mark Cave-Ayland
2023-05-29 11:40   ` Volker Rümelin
2023-05-30 11:27   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 16/30] q800: add Apple Sound Chip (ASC) audio to machine Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 17/30] q800: add easc bool machine class property to switch between ASC and EASC Mark Cave-Ayland
2023-05-30 11:28   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 18/30] swim: add trace events for IWM and ISM registers Mark Cave-Ayland
2023-05-25 17:58   ` Philippe Mathieu-Daudé
2023-05-30 11:29   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 19/30] swim: split into separate IWM and ISM register blocks Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 20/30] swim: update IWM/ISM register block decoding Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 21/30] mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 22/30] mac_via: fix rtc command decoding from PRAM addresses 0x0 to 0xf Mark Cave-Ayland
2023-05-30 13:37   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 23/30] mac_via: fix rtc command decoding for the PRAM seconds registers Mark Cave-Ayland
2023-05-30 13:38   ` Laurent Vivier
2023-05-24 21:10 ` [PATCH 24/30] mac_via: workaround NetBSD ADB bus enumeration issue Mark Cave-Ayland
2023-05-24 21:10 ` [PATCH 25/30] mac_via: implement ADB_STATE_IDLE state if shift register in input mode Mark Cave-Ayland
2023-05-24 21:11 ` [PATCH 26/30] mac_via: always clear ADB interrupt when switching to A/UX mode Mark Cave-Ayland
2023-05-24 21:11 ` [PATCH 27/30] q800: add ESCC alias at 0xc000 Mark Cave-Ayland
2023-05-24 21:11 ` [PATCH 28/30] q800: add alias for MacOS toolbox ROM at 0x40000000 Mark Cave-Ayland
2023-05-24 21:11 ` [PATCH 29/30] mac_via: extend timer calibration hack to work with A/UX Mark Cave-Ayland
2023-05-24 21:11 ` Mark Cave-Ayland [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230524211104.686087-31-mark.cave-ayland@ilande.co.uk \
    --to=mark.cave-ayland@ilande.co.uk \
    --cc=laurent@vivier.eu \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.