mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* malloc() alignment on 32 bit
@ 2022-09-19 12:37 Enrico Scholz
  2022-09-19 13:33 ` Ahmad Fatoum
  2022-09-19 13:57 ` Sascha Hauer
  0 siblings, 2 replies; 6+ messages in thread
From: Enrico Scholz @ 2022-09-19 12:37 UTC (permalink / raw)
  To: barebox

Hello,

on an iMX6ull I stumpled across

| zstd_decomp_init:536 workspace=8ff1a004+161320
| ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument

which is caused by

| static int zstd_decomp_init(void)
|	void *wksp = malloc(wksp_size);
| ...
| ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */


Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
malloc() for 32 bit has only an alignment of 4?

Relevant code seems to be in common/tlsf.c

| enum tlsf_private
| {
| #if defined (TLSF_64BIT)
| 	/* All allocation sizes and addresses are aligned to 8 bytes. */
| 	ALIGN_SIZE_LOG2 = 3,
| #else
| 	/* All allocation sizes and addresses are aligned to 4 bytes. */
| 	ALIGN_SIZE_LOG2 = 2,
| #endif

'ldrd/strd' require 8 byte alignment which might break with such
alignment.


Enrico



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: malloc() alignment on 32 bit
  2022-09-19 12:37 malloc() alignment on 32 bit Enrico Scholz
@ 2022-09-19 13:33 ` Ahmad Fatoum
  2022-09-19 13:57 ` Sascha Hauer
  1 sibling, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2022-09-19 13:33 UTC (permalink / raw)
  To: Enrico Scholz, barebox

On 19.09.22 13:37, Enrico Scholz wrote:
> Hello,
> 
> on an iMX6ull I stumpled across
> 
> | zstd_decomp_init:536 workspace=8ff1a004+161320
> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> 
> which is caused by
> 
> | static int zstd_decomp_init(void)
> |	void *wksp = malloc(wksp_size);
> | ...
> | ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
> |    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
> 
> 
> Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
> malloc() for 32 bit has only an alignment of 4?
> 
> Relevant code seems to be in common/tlsf.c
> 
> | enum tlsf_private
> | {
> | #if defined (TLSF_64BIT)
> | 	/* All allocation sizes and addresses are aligned to 8 bytes. */
> | 	ALIGN_SIZE_LOG2 = 3,
> | #else
> | 	/* All allocation sizes and addresses are aligned to 4 bytes. */
> | 	ALIGN_SIZE_LOG2 = 2,
> | #endif
> 
> 'ldrd/strd' require 8 byte alignment which might break with such
> alignment.

I recently learnt too that on 32-bit TLSF only has 4 byte alignment.
I also think that this is too low. 8 byte alignment sounds good IMO.

Cheers,
Ahmad

> 
> 
> Enrico
> 
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: malloc() alignment on 32 bit
  2022-09-19 12:37 malloc() alignment on 32 bit Enrico Scholz
  2022-09-19 13:33 ` Ahmad Fatoum
@ 2022-09-19 13:57 ` Sascha Hauer
  2022-09-19 14:24   ` Enrico Scholz
  1 sibling, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2022-09-19 13:57 UTC (permalink / raw)
  To: Enrico Scholz; +Cc: barebox

Hi Enrico,

On Mon, Sep 19, 2022 at 02:37:59PM +0200, Enrico Scholz wrote:
> Hello,
> 
> on an iMX6ull I stumpled across
> 
> | zstd_decomp_init:536 workspace=8ff1a004+161320
> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> 
> which is caused by
> 
> | static int zstd_decomp_init(void)
> |	void *wksp = malloc(wksp_size);
> | ...
> | ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
> |    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
> 
> 
> Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
> malloc() for 32 bit has only an alignment of 4?
> 
> Relevant code seems to be in common/tlsf.c
> 
> | enum tlsf_private
> | {
> | #if defined (TLSF_64BIT)
> | 	/* All allocation sizes and addresses are aligned to 8 bytes. */
> | 	ALIGN_SIZE_LOG2 = 3,
> | #else
> | 	/* All allocation sizes and addresses are aligned to 4 bytes. */
> | 	ALIGN_SIZE_LOG2 = 2,
> | #endif
> 
> 'ldrd/strd' require 8 byte alignment which might break with such
> alignment.

If you had asked me which alignment we have then I would have said it's
bigger. OTOH I never received any reports about insufficient alignment
on ARM or any other 32bit architecture.

I suspect we could just drop the check without any harm, but that's just
a gut feeling because we never had any alignment issues.

BTW are you sure ldrd/strd need 8 byte alignment? I just tested it with
the following patch and this works without problems. I verified the
compiler indeed generates ldrd/strd for accessing the 64bit field.

Sascha

-------------------------8<----------------------------

diff --git a/common/startup.c b/common/startup.c
index f53b73f81a..f261b1bdac 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -334,10 +334,31 @@ static void do_ctors(void)
 
 int (*barebox_main)(void);
 
+struct bar {
+	uint64_t foo;
+};
+
+struct bar *myfoo(void)
+{
+	struct bar *x;
+	void *ptr;
+
+	ptr = malloc(16);
+
+	ptr = (void *)((unsigned long)ptr | 4);
+
+	x = ptr;
+
+	x->foo = get_time_ns();
+
+	return x;
+}
+
 void __noreturn start_barebox(void)
 {
 	initcall_t *initcall;
 	int result;
+	struct bar *b;
 
 	if (!IS_ENABLED(CONFIG_SHELL_NONE) && IS_ENABLED(CONFIG_COMMAND_SUPPORT))
 		barebox_main = run_init;
@@ -355,6 +376,9 @@ void __noreturn start_barebox(void)
 
 	pr_debug("initcalls done\n");
 
+	b = myfoo();
+	printf("V: %lld\n", b->foo);
+
 	if (IS_ENABLED(CONFIG_SELFTEST_AUTORUN))
 		selftests_run();
 
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: malloc() alignment on 32 bit
  2022-09-19 13:57 ` Sascha Hauer
@ 2022-09-19 14:24   ` Enrico Scholz
  2022-09-20  7:36     ` Sascha Hauer
  0 siblings, 1 reply; 6+ messages in thread
From: Enrico Scholz @ 2022-09-19 14:24 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <sha@pengutronix.de> writes:

>> | zstd_decomp_init:536 workspace=8ff1a004+161320
>> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
>> 
> If you had asked me which alignment we have then I would have said it's
> bigger. OTOH I never received any reports about insufficient alignment
> on ARM or any other 32bit architecture.

The code which failed for me was added 3 months ago

| commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
| Author: Ahmad Fatoum <a.fatoum@pengutronix.de>
| Date:   Wed Jul 13 12:09:18 2022 +0200
| 
|     lib: zstd: sync with Linux

and the Kconfig options (FS_UBIFS_COMPRESSION_ZSTD) are set to "off"...


> I suspect we could just drop the check without any harm, but that's just
> a gut feeling because we never had any alignment issues.
>
> BTW are you sure ldrd/strd need 8 byte alignment?

Their EX variants (LDREXD + STREXD; see [1]).  Unaligned access on
plain LDRD/STRD is allowed on ARMv7-A.  But not on ARMv7-M or ARMv6 and
earlier.




Enrico

Footnotes:
[1]  https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Application-Level-Memory-Model/Alignment-support/Unaligned-data-access



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: malloc() alignment on 32 bit
  2022-09-19 14:24   ` Enrico Scholz
@ 2022-09-20  7:36     ` Sascha Hauer
  2022-09-28 10:24       ` Enrico Scholz
  0 siblings, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2022-09-20  7:36 UTC (permalink / raw)
  To: Enrico Scholz; +Cc: barebox

On Mon, Sep 19, 2022 at 04:24:19PM +0200, Enrico Scholz wrote:
> Sascha Hauer <sha@pengutronix.de> writes:
> 
> >> | zstd_decomp_init:536 workspace=8ff1a004+161320
> >> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> >> 
> > If you had asked me which alignment we have then I would have said it's
> > bigger. OTOH I never received any reports about insufficient alignment
> > on ARM or any other 32bit architecture.
> 
> The code which failed for me was added 3 months ago
> 
> | commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
> | Author: Ahmad Fatoum <a.fatoum@pengutronix.de>
> | Date:   Wed Jul 13 12:09:18 2022 +0200
> | 
> |     lib: zstd: sync with Linux
> 
> and the Kconfig options (FS_UBIFS_COMPRESSION_ZSTD) are set to "off"...

When I said I received no reports about insufficient malloc alignment I
meant reports about erroneous accesses, like wrong data read/writes or data
aborts.

> 
> 
> > I suspect we could just drop the check without any harm, but that's just
> > a gut feeling because we never had any alignment issues.
> >
> > BTW are you sure ldrd/strd need 8 byte alignment?
> 
> Their EX variants (LDREXD + STREXD; see [1]).  Unaligned access on
> plain LDRD/STRD is allowed on ARMv7-A.  But not on ARMv7-M or ARMv6 and
> earlier.

Ok, I found this for the LDRD instruction:

| Prior to ARMv6, if the memory address is not 64-bit aligned, the data read from memory is
| UNPREDICTABLE. Alignment checking (taking a data abort), and support for a big-endian
| (BE-32) data format are implementation options.

So it seems it's really a good idea to increase malloc alignment
accordingly.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: malloc() alignment on 32 bit
  2022-09-20  7:36     ` Sascha Hauer
@ 2022-09-28 10:24       ` Enrico Scholz
  0 siblings, 0 replies; 6+ messages in thread
From: Enrico Scholz @ 2022-09-28 10:24 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <sha@pengutronix.de> writes:

> So it seems it's really a good idea to increase malloc alignment
> accordingly.

But this does not seem to be trivial :(

A naive

| -	ALIGN_SIZE_LOG2 = 2,
| +	ALIGN_SIZE_LOG2 = 3,

triggers a lot of warnings.


I think, ALIGN_SIZE in tlsf_add_pool() and in the higher level functions
(tlsf_malloc(), _memalign(), _realloc()) should be replaced by a new,
bigger constant.

But this appears invasive and I have no idea about tlsf and the sideeffects :(


There exists https://github.com/mattconte/tlsf/issues/16 which asks for
proper alignment; but project seems to be unmaintained.


Replacing 'malloc()' with 'memalign()' on problems, seems the best idea
for now.


Enrico



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-09-28 10:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-19 12:37 malloc() alignment on 32 bit Enrico Scholz
2022-09-19 13:33 ` Ahmad Fatoum
2022-09-19 13:57 ` Sascha Hauer
2022-09-19 14:24   ` Enrico Scholz
2022-09-20  7:36     ` Sascha Hauer
2022-09-28 10:24       ` Enrico Scholz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox