From a939aa56b3af4418d0c026a3775fde7288b0cca7 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 20 Nov 2018 08:41:14 -0800 Subject: mga_drv: fix image corruption due to memcpy reordering The memcpy specification doesn't specify how the destination is written - and on glibc 2.19 memcpy is doing some bytewise writes with the rep stosb instruction. These bytewise writes confuse the hardware (because it expects 32-bit writes) and result in image corruption. This patch replaces memcpy with explicit writes, so that the sequential write order and 32-bit write size is guaranteed. We use the "volatile" attribute to make sure that compiler optimizations won't cause write reordering. When reading the memory, we use a structure with "packed" attribute to avoid unaligned traps on RISC machines. Tested-by: Kevin Brace Signed-off-by: Mikulas Patocka --- src/mga_exa.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/mga_exa.c b/src/mga_exa.c index c4e4d90..86ec09e 100644 --- a/src/mga_exa.c +++ b/src/mga_exa.c @@ -695,6 +695,14 @@ mgaComposite(PixmapPtr pDst, int srcx, int srcy, int maskx, int masky, OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (dsty << 16) | (h & 0xffff)); } +struct unaligned_32 { + uint32_t val; +} __attribute__((packed)); + +struct unaligned_64 { + uint64_t val; +} __attribute__((packed)); + static Bool mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) @@ -720,7 +728,15 @@ mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (y << 16) | (h & 0xffff)); while (h--) { - memcpy (pMga->ILOADBase, src, bytes_padded); + int i = 0; + + if (sizeof(long) == 8) { + for (; i + 4 < bytes_padded; i += 8) + *(volatile uint64_t *)(pMga->ILOADBase + i) = ((struct unaligned_64 *)(src + i))->val; + } + + for (; i < bytes_padded; i += 4) + *(volatile uint32_t *)(pMga->ILOADBase + i) = ((struct unaligned_32 *)(src + i))->val; src += src_pitch; } -- cgit v1.2.3