11/3/21 2:25 PM, Daniel Schwierzeck:
Am Dienstag, dem 02.11.2021 um 23:35 +0100 schrieb Mathias Kresin:
At least since gcc 7.3.0 (OpenWrt 18.06) lwr/lwl are used in the
assembly of LzmaProps_Decode. The instructions are using unaligned
access, which locks up danube boards using memory mapped NOR flash.
It isn't clear whether it is a limitation of the flash chip or a
limitation of the EBU.
Moving the pointer to the next int position and accessing accessing
just
the first byte, let gcc use sll instead of lwr/lwl and prevents the
unaligned access.
Signed-off-by: Mathias Kresin <d...@kresin.me>
---
.../0030-lzma-fix-unaligned-access.patch | 32
+++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 package/boot/uboot-lantiq/patches/0030-lzma-fix-
unaligned-access.patch
diff --git a/package/boot/uboot-lantiq/patches/0030-lzma-fix-
unaligned-access.patch b/package/boot/uboot-lantiq/patches/0030-lzma-
fix-unaligned-access.patch
new file mode 100644
index 0000000000..de9afe0bf5
--- /dev/null
+++ b/package/boot/uboot-lantiq/patches/0030-lzma-fix-unaligned-
access.patch
@@ -0,0 +1,32 @@
+From a335c4c0532cf0d09b31e73f8461d3b4d0ce6f9a Mon Sep 17 00:00:00
2001
+From: Mathias Kresin <d...@kresin.me>
+Date: Sun, 31 Oct 2021 23:04:54 +0100
+Subject: [PATCH] lzma: fix unaligned access
+
+At least since gcc 7.3.0 (OpenWrt 18.06) lwr/lwl are used in the
+assembly of LzmaProps_Decode. The instructions are using unaligned
+access, which locks up danube boards using memory mapped NOR flash.
+
+It isn't clear whether it is a limitation of the flash chip or a
+limitation of the EBU.
I think the problem is not the unaligned access but the 32bit read
operation. The internal EBU data bus has a 16 bit width and can access
8bit or 16bit flash devices. So 8bit read operations at odd addresses
shouldn't be a problem. I'm not sure what happens exactly at 32bit
reads but this maybe involves multiple reads from flash and also some
internal endianess swapping.
I've done more testing and the behaviour can be only described as
strange. The system only hangs if the offset is 1.
lwl s0,0(a1) - 0x6d000080
lwl s0,1(a1) - hangs
lwl s0,2(a1) - 0x0080xxxx
lwl s0,3(a1) - 0x80xxxxxx
Looks like 32bit reads via the EBU on a flash device are working fine
with exception to offset 1. So, it doesn't look like a 32bit read issue
and obviously it isn't an issue with unaligned access...
Maybe a more robust solution would be to use readb(data[n] to always
force 8bit reads.
It isn't just more robust, it's the only reliable way.
While checking the generated assembler code, I spotted that with my
change the read to offset 4 is completely gone. No idea what the
compiler is doing here. It only worked by accident.
+
+Moving the pointer to the next int position and accessing accessing
just
+the first byte, let gcc use sll instead of lwr/lwl and prevents the
+unaligned access.
+
+Signed-off-by: Mathias Kresin <d...@kresin.me>
+---
+ lib/lzma/LzmaDec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/lib/lzma/LzmaDec.c
++++ b/lib/lzma/LzmaDec.c
+@@ -929,7 +929,7 @@ SRes LzmaProps_Decode(CLzmaProps *p, con
+ if (size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_UNSUPPORTED;
+ else
+- dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3]
<< 16) | ((UInt32)data[4] << 24);
++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3]
<< 16) | ((UInt32)(data+1)[0] << 24);
+
+ if (dicSize < LZMA_DIC_MIN)
+ dicSize = LZMA_DIC_MIN;
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel