Hi David,
On Mon, 2018-07-09 at 09:16 +0000, David Laight wrote:
From: Alexey Brodkin
Sent: 09 July 2018 05:45 Depending on ABI "long long" type of a particular 32-bit CPU might be aligned by either word (32-bits) or double word (64-bits). Make sure "data" is really 64-bit aligned for any 32-bit CPU.
At least for 32-bit ARC cores ABI requires "long long" types to be aligned by normal 32-bit word. This makes "data" field aligned to 12 bytes. Which is still OK as long as we use 32-bit data only.
But once we want to use native atomic64_t type (i.e. when we use special instructions LLOCKD/SCONDD for accessing 64-bit data) we easily hit misaligned access exception.
Shouldn't there be a typedef for the actual type. Perhaps it is even atomic64_t ? And have the __aligned(8) applied to that typedef ??
That's a good idea indeed but it doesn't solve the problem with struct devres_node. Consider the following snippet: -------------------------------->8------------------------------- struct mystruct { atomic64_t myvar; }
struct mystruct *p; p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); -------------------------------->8-------------------------------
Here myvar address will match address of "data" member of struct devres_node. So if "data" is has offset of 12 bytes from the beginning of a page then myvar won't be 64-bit aligned regardless of myvar's attribute, right?
That's because even on CPUs capable of non-aligned data access LL/SC instructions require strict alignment.
...
--- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -24,8 +24,12 @@ struct devres_node {
struct devres { struct devres_node node;
- /* -- 3 pointers */
- unsigned long long data[]; /* guarantee ull alignment */
- /*
* Depending on ABI "long long" type of a particular 32-bit CPU
* might be aligned by either word (32-bits) or double word (64-bits).
* Make sure "data" is really 64-bit aligned for any 32-bit CPU.
Just: /* data[] must be 64 bit aligned even on 32 bit architectures * because it might be accessed by instructions that require * aligned memory arguments.
*/
- unsigned long long data[] __aligned(sizeof(unsigned long long));
One day assuming that 'unsigned long long' is exactly 64 bits will bite. This probably ought to be u64 (or similar).
I agree. Initially I wanted to keep as few changes as possible but IMHO switching to more predictable data type makes sense.
-Alexey