mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>,
	Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v2 4/7] tlsf: give malloc 8-byte alignment on 32-bit as well
Date: Mon, 11 Sep 2023 17:24:30 +0200	[thread overview]
Message-ID: <20230911152433.3640781-5-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20230911152433.3640781-1-a.fatoum@pengutronix.de>

The current alignment of 4 bytes is too low. Access to 64-bit data via
ldrd/strd requires at least an eight byte alignment:

  | 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.

We already have at least an 8 byte alignment for dlmalloc, so have TLSF
follow suit by aligning the accounting structures appropriately.

Instead of adding manual padding, we could also enlarge block_header_t::size
to an uint64_t unconditionally, but mark block_header_t __packed. This
comes with a runtime cost though or ugly __builtin_assume_aligned
annotations, so we stick to the simpler version.

Reported-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
Link: https://lore.barebox.org/barebox/ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de/
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/tlsf.c          | 12 ++++++------
 include/linux/bitops.h |  1 +
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/common/tlsf.c b/common/tlsf.c
index 0986c7c457e3..692dabbdedd9 100644
--- a/common/tlsf.c
+++ b/common/tlsf.c
@@ -30,13 +30,8 @@ enum tlsf_public
 /* Private constants: do not modify. */
 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
 	ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
 
 	/*
@@ -122,6 +117,7 @@ typedef struct block_header_t
 
 	/* The size of this block, excluding the block header. */
 	size_t size;
+	u32 : BYTES_TO_BITS(ALIGN_SIZE - sizeof(size_t));
 
 	/* Next and previous free blocks. */
 	struct block_header_t* next_free;
@@ -142,7 +138,7 @@ typedef struct block_header_t
 ** The prev_phys_block field is stored *inside* the previous free block.
 */
 #define block_header_shift		offsetof(block_header_t, size)
-#define block_header_overhead		sizeof(size_t)
+#define block_header_overhead		ALIGN_SIZE
 
 /* User data starts directly after the size field in a used block. */
 #define block_start_offset		(block_header_shift + block_header_overhead)
@@ -155,6 +151,8 @@ typedef struct block_header_t
 #define block_size_min			(sizeof(block_header_t) - sizeof(block_header_t*))
 #define block_size_max			(tlsf_cast(size_t, 1) << FL_INDEX_MAX)
 
+tlsf_static_assert(block_size_min % ALIGN_SIZE == 0);
+tlsf_static_assert(block_size_max % ALIGN_SIZE == 0);
 
 /* The TLSF control structure. */
 typedef struct control_t
@@ -165,10 +163,12 @@ typedef struct control_t
 	/* Bitmaps for free lists. */
 	unsigned int fl_bitmap;
 	unsigned int sl_bitmap[FL_INDEX_COUNT];
+	u32 : BYTES_TO_BITS(ALIGN_SIZE - sizeof(size_t));
 
 	/* Head of free lists. */
 	block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
 } control_t;
+tlsf_static_assert(sizeof(control_t) % ALIGN_SIZE == 0);
 
 /* A type used for casting when doing pointer arithmetic. */
 typedef ptrdiff_t tlsfptr_t;
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index a5f6ac6545ee..b0d6ca6ac87f 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -19,6 +19,7 @@
 #define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
 #define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
 #define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
+#define BYTES_TO_BITS(nb)	(((BITS_PER_LONG * (nb)) / sizeof(long)))
 #endif
 
 /*
-- 
2.39.2




  parent reply	other threads:[~2023-09-11 15:26 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-11 15:24 [PATCH v2 0/7] tlsf: use 8-byte alignment for normal malloc allocations Ahmad Fatoum
2023-09-11 15:24 ` [PATCH v2 1/7] tlsf: turn static const variables into compiletime constant expressions Ahmad Fatoum
2023-09-11 15:24 ` [PATCH v2 2/7] tlsf: ensure malloc pool is aligned Ahmad Fatoum
2023-09-11 15:24 ` [PATCH v2 3/7] tlsf: fix sizeof(size_t) == sizeof(void *) assumption Ahmad Fatoum
2023-09-11 15:24 ` Ahmad Fatoum [this message]
2023-09-11 15:24 ` [PATCH v2 5/7] common: malloc: ensure alignment is always at least 8 byte Ahmad Fatoum
2023-09-11 15:24 ` [PATCH v2 6/7] test: self: refactor to allow alignment check Ahmad Fatoum
2023-09-11 15:24 ` [PATCH v2 7/7] test: self: malloc: fix memory leaks Ahmad Fatoum
2023-09-26 10:57 ` [PATCH v2 0/7] tlsf: use 8-byte alignment for normal malloc allocations Sascha Hauer

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=20230911152433.3640781-5-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=enrico.scholz@sigma-chemnitz.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox