Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unaligned access in networking code causes unaligned exception on Nucleo-F429ZI #6307

Closed
therealprof opened this issue Feb 21, 2018 · 39 comments
Assignees
Labels
area: Ethernet area: Networking bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug
Milestone

Comments

@therealprof
Copy link
Contributor

Trying to run some networking sample code (with the default configuration) on my new Nucleo-F429ZI board yields this interesting exception:

**** BOOTING ZEPHY***** USAGE FAULT *****
Executing thread ID (thread): 0x200038ac
Faulting instruction address: 0x80097e6
Unaligned memory access
Fatal fault in essential thread! Spinning...

Very much to my surprise it is somewhat obvious where that unaligned exception is coming from:

 80097e0:       689b            ldr     r3, [r3, #8]
        dst->s6_addr[0]   = 0xFF;
 80097e2:       f240 22ff       movw    r2, #767        ; 0x2ff
        UNALIGNED_PUT(0, &dst->s6_addr16[1]);
 80097e6:       e9c3 2506       strd    r2, r5, [r3, #24]
        UNALIGNED_PUT(0, &dst->s6_addr16[3]);

It's somewhat less obvious (to me at least) what to do about it...

@carlescufi carlescufi added this to the v1.12.0 milestone Mar 6, 2018
@carlescufi carlescufi added the bug The issue is a bug, or the PR is fixing a bug label Mar 6, 2018
@erwango
Copy link
Member

erwango commented Mar 19, 2018

Hi @therealprof,

Can you eleaborate a bit on this issue, so we can investigate and fix it?
What sample were you running ? Is that systematic?

@therealprof
Copy link
Contributor Author

therealprof commented Mar 19, 2018

@erwango I just built the default configuration for the Nucleo-F429ZI and ran it. The sample I was trying was the one in samples/net/lwm2m_client/ but I think I've seen it with other networking examples as well.

Meanwhile I've also been able to build a configuration that doesn't crash. I don't have the board here but I think the workaround was to change from
CONFIG_SIZE_OPTIMIZATIONS=y
to
CONFIG_DEBUG_OPTIMIZATIONS=y

Yes, it is systematic. And just looking at the exception and the executed code not at all surprising to the innocent bystander.

If you'd like me to test anything specific or provide more output, I can dig up the board later today and run some stuff.

@erwango
Copy link
Member

erwango commented Mar 21, 2018

Hi @therealprof
I think we can try, in net_ipv6_addr_create_solicited_node, to do something like :
dst->s6_addr[2] = 0x00;
dst->s6_addr[3] = 0x00;
UNALIGNED_PUT(0, &dst->s6_addr32[1]);
UNALIGNED_PUT(0, &dst->s6_addr16[4]);
instead of
UNALIGNED_PUT(0, &dst->s6_addr16[1]);
UNALIGNED_PUT(0, &dst->s6_addr16[2]);
UNALIGNED_PUT(0, &dst->s6_addr16[3]);
UNALIGNED_PUT(0, &dst->s6_addr16[4]);

@MaureenHelm MaureenHelm added the priority: medium Medium impact/importance bug label Mar 23, 2018
@erwango
Copy link
Member

erwango commented Apr 18, 2018

@therealprof , any update?

@jukkar
Copy link
Member

jukkar commented Apr 18, 2018

I am wondering about that net_ipv6_addr_create_solicited_node() function that looks like a culprit. It is missing UNALIGNED_PUT() in couple of places because those that are just u8_t (so one byte) assignments. I have not seen any issues in frdm_k64f or sam_e70_xplained board that use this code all the time, is there some more stricter alignment rules in stm32?

@erwango
Copy link
Member

erwango commented Apr 19, 2018

One thing is I'm not able to run the sample fully (lwm2m connection PC <> board), so will be hard for me to reproduce the exact issue.

Anyway, could this be linked with compiler ?
Looking to the code I generate, this comes a bit different (with CONFIG_SIZE_OPTIMIZATIONS=y ), and I guess using strh.w or strb instead of strd will avoid the issue:

UNALIGNED_PUT(0, &dst->s6_addr16[1]);
 800687c:	f8ad 3002 	strh.w	r3, [sp, #2]
UNALIGNED_PUT(0, &dst->s6_addr16[2]);
 8006880:	f8ad 3004 	strh.w	r3, [sp, #4]
UNALIGNED_PUT(0, &dst->s6_addr16[3]);
 8006884:	f8ad 3006 	strh.w	r3, [sp, #6]
UNALIGNED_PUT(0, &dst->s6_addr16[4]);
 8006888:	f8ad 3008 	strh.w	r3, [sp, #8]

or at other places:

UNALIGNED_PUT(0, &dst->s6_addr16[1]);
 800a6e2:	769d      	strb	r5, [r3, #26]
 800a6e4:	76dd      	strb	r5, [r3, #27]
UNALIGNED_PUT(0, &dst->s6_addr16[2]);
 800a6e6:	771d      	strb	r5, [r3, #28]
 800a6e8:	775d      	strb	r5, [r3, #29]
UNALIGNED_PUT(0, &dst->s6_addr16[3]);
 800a6ea:	779d      	strb	r5, [r3, #30]
 800a6ec:	77dd      	strb	r5, [r3, #31]
UNALIGNED_PUT(0, &dst->s6_addr16[4]);
 800a6ee:	f883 5020 	strb.w	r5, [r3, #32]
 800a6f2:	f883 5021 	strb.w	r5, [r3, #33]	; 0x21

Did we changed something that could have impacted this?

Btw, I've been able to run tests/net/mld (which calls net_ipv6_addr_create_solicited_node) successfully on nucleo_f429zi. This does not prove we're safe, since function is inline and hence I think generated assembly might depend on calling function. But at least this shows code could run without fault in some conditions.

@therealprof
Copy link
Contributor Author

@erwango I just tested the suggested change using

dst->s6_addr[2] = 0x00;
dst->s6_addr[3] = 0x00;
UNALIGNED_PUT(0, &dst->s6_addr32[1]);
UNALIGNED_PUT(0, &dst->s6_addr16[4]);

and that particular crash went away after making the change. I also checked that it still occurs without patch in the latest git version.

So that's good.

Unfortunately I still cannot fully test the lwm2m_client sample because I have a second (and seemingly unrelated) MPU fault now...

@erwango
Copy link
Member

erwango commented Apr 19, 2018

@therealprof , thanks for this feedback!

Can you confirm you meet the issue (w/o the patch) with tests/net/mld ?
Also, may I ask which compiler you're using?

@therealprof
Copy link
Contributor Author

@erwango

No, I don't see a crash in tests/net/mld, in fact the suggested patch breaks this testcase (cable not connected):

�***** Booting Zephyr OS v1.11.0-720-g28724732e *****
Running test suite net_mld_test
===================================================================
starting test - mld_setup
PASS - mld_setup.
===================================================================
starting test - join_group
PASS - join_group.
===================================================================
starting test - leave_group
PASS - leave_group.
===================================================================
starting test - catch_join_group
PASS - catch_join_group.
===================================================================
starting test - catch_leave_group
PASS - catch_leave_group.
===================================================================
starting test - verify_join_group
PASS - verify_join_group.
===================================================================
starting test - verify_leave_group
PASS - verify_leave_group.
===================================================================
starting test - catch_query
PASS - catch_query.
===================================================================
starting test - verify_send_report
PASS - verify_send_report.
===================================================================
starting test - test_allnodes
PASS - test_allnodes.
===================================================================
starting test - test_solicit_node

    Assertion failed at /Users/egger/oss/zephyr/tests/net/mld/src/main.c:460: test_solicit_node: (ifmaddr is NULL)
Interface does not contain solicit node multicast addressFAIL - test_solicit_node.
===================================================================
===================================================================
PROJECT EXECUTION FAILED
arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204]

@erwango
Copy link
Member

erwango commented May 4, 2018

@therealprof : I'm using version 6.2.0 which is coming from zephyr SDK.
Can you have a try with this one?

@therealprof
Copy link
Contributor Author

That seems to be only available for Linux.

@erwango
Copy link
Member

erwango commented May 15, 2018

@therealprof , I had a try with your toolchain variant and I end up generating the same code as you do.
And back to normal with the DEBUG option.

I'll check what can be done about that.

@erwango
Copy link
Member

erwango commented May 15, 2018

I am wondering about that net_ipv6_addr_create_solicited_node() function that looks like a culprit. It is missing UNALIGNED_PUT() in couple of places because those that are just u8_t (so one byte) assignments. I have not seen any issues in frdm_k64f or sam_e70_xplained board that use this code all the time, is there some more stricter alignment rules in stm32?

@jukkar : So according to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BABDJJGF.html,
"Unaligned LDM, STM, LDRD, and STRD instructions always fault irrespective of whether UNALIGN_TRP is set to 1."

Compiling frdm_k64f, I find same behavior strd are generated with GNU 7.2.1, while with GNU 6.2.0 (Zephyr SDK one), we get strh instructions.

So stm32 is not more strict, but @therealprof might be one of the few that run GNU 7.2.1 (Dec 2017), and hit the problem, whatever the SoC.

@erwango erwango removed the platform: STM32 ST Micro STM32 label May 15, 2018
@therealprof
Copy link
Contributor Author

@erwango And that's not going to change unless Zephyr provides SDKs for Mac. ;)

@mike-scott
Copy link
Contributor

@therealprof Not a real solution, but as a temporary work around you can download the GNU ARM Embedded Toolchain 6.3.1 for Mac OS X from here:
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
Slide below the initial offered 7.2.1 download and look for "GNU Arm Embedded Toolchain: 6-2017-q2-update June 28, 2017". Expand that section and a download link for Mac OS X 64-bit should be available.

I tested it on K64F and it seemed to work just fine (where the 7.2.1 compiler was breaking in the same way you described).

@therealprof
Copy link
Contributor Author

@mike-scott Yeah, I know more ways to work around that but frankly that's not something I'd want to spend my energy on.

@nashif
Copy link
Member

nashif commented May 29, 2018

@erwango ping, any solution in sight?

@erwango
Copy link
Member

erwango commented May 30, 2018

@jukkar, Now that root cause is identified, would you be able to have a look?
I'm not able to reproduce it on my end (LWM2M setup), which makes it difficult to investigate a solution.
Had a try with tests/net/mld, but which does not reproduce the exact same behavior according to therealprof.

@jukkar
Copy link
Member

jukkar commented May 30, 2018

Now that root cause is identified, would you be able to have a look?

I thought this was compiler issue, what is there in network code to fix?

@therealprof
Copy link
Contributor Author

It's most likely still a error in the code but only exploited by a newer compiler. Also note that this error may also cause troubles on other platforms but only cause real crashes if the MCU has hardware to fault on memory alignment issues.

I would imagine that the proper fix is to make sure that the addresses are properly aligned in memory.

@erwango
Copy link
Member

erwango commented May 30, 2018

I thought this was compiler issue, what is there in network code to fix?

Since it appeared on recent compiler version, this is something that more and more users will face.

@Nemo157
Copy link

Nemo157 commented Jun 1, 2018

I have just hit this same issue compiling with arm-none-eabi-gcc (Arch Repository) 8.1.0 targetting the nrf52840.

@mazhenke
Copy link

mazhenke commented Jun 5, 2018

I have hit this same issue.

r0: 0x2800bbc2
r1: 0x2800bbd6
r2: 0x2800bb96
r3: 0x2ff
ip: 0x1
lr: 0x2800bbc2
pc: 0x10a564
xpsr: 0x69000000
***** USAGE FAULT *****
  Executing thread ID (thread): 0x28008e28
  Faulting instruction address:  0x10a564
  Unaligned memory access
Fatal fault in essential thread! Spinning...
  10a55a:	f1ba 0f00 	cmp.w	sl, #0
  10a55e:	d168      	bne.n	10a632 <net_ipv6_send_ns+0x1b2>
	dst->s6_addr[0]   = 0xFF;
  10a560:	f240 23ff 	movw	r3, #767	; 0x2ff
	UNALIGNED_PUT(0, &dst->s6_addr16[1]);
  10a564:	e9c2 3a06 	strd	r3, sl, [r2, #24]
	UNALIGNED_PUT(0, &dst->s6_addr16[3]);
  10a568:	f04f 7380 	mov.w	r3, #16777216	; 0x1000000
  10a56c:	6213      	str	r3, [r2, #32]
	dst->s6_addr[11]  = 0x01;

And I think the real reason is lack memory_barrier.
I add some compiler_barrier() between the UNALIGNED_PUT,

	_dst->s6_addr[0]   = 0xFF;
    compiler_barrier();
	dst->s6_addr[1]   = 0x02;
    compiler_barrier();
	UNALIGNED_PUT(0, &dst->s6_addr16[1]);
    compiler_barrier();
	UNALIGNED_PUT(0, &dst->s6_addr16[2]);
    compiler_barrier();
	UNALIGNED_PUT(0, &dst->s6_addr16[3]);
    compiler_barrier();
	UNALIGNED_PUT(0, &dst->s6_addr16[4]);
    compiler_barrier();

	dst->s6_addr[10]  = 0;
    compiler_barrier();
	dst->s6_addr[11]  = 0x01;
    compiler_barrier();
	dst->s6_addr[12]  = 0xFF;
    compiler_barrier();
	dst->s6_addr[13]  = src->s6_addr[13];
    compiler_barrier();
	UNALIGNED_PUT(UNALIGNED_GET(&src->s6_addr16[7]), &dst->s6_addr16[7]);_

and the arm-none-eabi-gcc compiler generates different code:

	_dst->s6_addr[1]   = 0x02;
  1054da:	2202      	movs	r2, #2
  1054dc:	f88d 2019 	strb.w	r2, [sp, #25]
	UNALIGNED_PUT(0, &dst->s6_addr16[1]);
  1054e0:	2200      	movs	r2, #0
  1054e2:	f8ad 201a 	strh.w	r2, [sp, #26]
	UNALIGNED_PUT(0, &dst->s6_addr16[2]);
  1054e6:	f8ad 201c 	strh.w	r2, [sp, #28]
	UNALIGNED_PUT(0, &dst->s6_addr16[3]);
  1054ea:	f8ad 201e 	strh.w	r2, [sp, #30]
	UNALIGNED_PUT(0, &dst->s6_addr16[4]);
  1054ee:	f8ad 2020 	strh.w	r2, [sp, #32]
	dst->s6_addr[10]  = 0;
  1054f2:	f88d 2022 	strb.w	r2, [sp, #34]	; 0x22
	dst->s6_addr[11]  = 0x01;

@jukkar
Copy link
Member

jukkar commented Jun 5, 2018

Are there instructions somewhere how to use newer compiler version with zephyr? The zephyr-sdk is having gcc 6.x version and I am not able to reproduce this.

@erwango
Copy link
Member

erwango commented Jun 5, 2018

@jukkar : http://docs.zephyrproject.org/getting_started/getting_started.html#using-custom-and-3rd-party-cross-compilers
Make sure you don't have ZEPHYR_GCC_VARIANT set in your environment first, you'll save some time

jukkar added a commit to jukkar/zephyr that referenced this issue Jun 6, 2018
The gcc 7.x is generating code for ARM that is causing memory
alignment error when net_ipv6_addr_create_solicited_node() is
called by IP stack. Fix this by removing the offeding
UNALIGNED_PUT() calls and replacing them by simple memset().

Fixes zephyrproject-rtos#6307

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

Now that root cause is identified, would you be able to have a look?
I thought this was compiler issue

Yeah, I also don't see the root cause to be pronounced here clearly. And it is:

The compiler doesn't behave correctly.

The macro used in the code is UNALIGNED_PUT(), and it's named such for a reason - that it should work with unaligned memory addresses. And that works with gcc 6.x and below. But it started to break with 7.x+, and the reasons for that could be:

  1. Outright bug in those versions of GCC.
  2. Smartass-style bug, where they redefined something behind everyone's back, and code previously working started to break (like well-known drama of null-pointer dereference https://lists.zephyrproject.org/g/devel/message/305).

Our definition of UNALIGNED_PUT is defined as (include/toolchain/gcc.h):

#define UNALIGNED_PUT(v, p)                                             \
do {                                                                    \
	struct __attribute__((__packed__)) {                            \
		__typeof__(*p) __v;                                     \
	} *__p = (__typeof__(__p)) (p);                                 \
	__p->__v = (v);                                               \
} while (0)

So, how it's expected to work that compiler does the most conservative memory access when it deals with structures which has __attribute__((__packed__)). And gcc 7.x code looks as the compiler has just ignored that attribute. Let me theorize that the compiler dudes thought: "well, previously we worked with such a structure as if it was completely unaligned. Why don't we change that behind everyone's back to the following definition: individual members of this struct are packed, so members from 2nd can have unaligned addresses. But the structure itself, and thus its first member is treated as aligned still."

Again, that's just theorizing. The point is that we need to fix the definition of UNALIGNED_PUT and friends to work even with gcc 7.x, etc. (And as the current version works well with gcc 6.x, and it even it "optimizes" it (without breakage I hope) where possible, we'd rather have #ifdef for classical and new-too-smart versions).

@lpereira
Copy link
Collaborator

lpereira commented Jun 6, 2018

While this macro should work, I'd just yank everything in this macro and change it to a simple memset() call.

GCC will just generate the right thing (e.g. just move-reg-to-memory instructions) if the size is small (i.e. word-size) and known at runtime; if, in the worst case, it can't figure out a series of instructions to do the right thing, it'll just be a function call, but the important thing is that it'll always be correct, even if we're paying the price of a function call.

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

change it to a simple memset() call.

UNALIGNED_PUT() is not about memset(), it's about storing any-type value (uint8_t, uint16_t, uint32_t, add more if you like) into an unaligned memory address.

How I'd do it (and how I'll argue to do it later to drop gcc-specificness) is to have UNALIGNED_PUT8, UNALIGNED_PUT16, UNALIGNED_PUT32 with the expected implementations (storing everything by uint8_t*). But first need to figure out how to fix gcc7 with the current thing ;-).

@lpereira
Copy link
Collaborator

lpereira commented Jun 6, 2018

Sorry -- I meant memcpy().

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

I meant memcpy()

Well, I guess that's truly would be too inefficient, unless a compiler is truly very smart (but they usually smartass before that). @lpereira, we can race later to try to make it work ;-).

@lpereira
Copy link
Collaborator

lpereira commented Jun 6, 2018

GCC is already pretty smart about memcpy() for small sizes that are known at compile-time. At least on x86, it just generates a few mov instructions already if the arch is known to not have performance issues with unaligned access.

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

GCC is already pretty smart about memcpy() for small sizes that are known at compile-time.

That's GCC (we aren't fixed on one compiler, do we, at least we had a simple build system (ahem), and replaced with something else because there's Windows, surely, we won't stop there?), and it requires quite a good ability for coming from (constant) rvalues to storing them into (virtual) lvalues and dereferencing them back. I'll be pleasantly surprised if GCC can do such tricks, doing those borders on the level of prohibition in the C land. Do you have a ready macro? (I bet it'll have to be inline func tho.)

@lpereira
Copy link
Collaborator

lpereira commented Jun 6, 2018

The UNALIGNED_{PUT,GET}() macros are defined in the toolchain-specific headers (e.g. toolchain/gcc.h). So IMO it's fair game to use whatever works best with that particular compiler.

Something like this will most likely work (haven't tested, writing it directly as a comment):

#define UNALIGNED_PUT(v, p) \
({ \
    __typeof__(v) __tmp_value__ = (v); \
    memcpy((p), &__tmp_value__, sizeof(__tmp_value__)); \
})

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

Something like this will most likely work (haven't tested, writing it directly as a comment):

Here's how GNU 7.2.1 renders that for ARM:

        UNALIGNED_PUT(0, &dst->s6_addr16[1]);
    aa88:       f10d 0870       add.w   r8, sp, #112    ; 0x70
        dst->s6_addr[0]   = 0xFF;
    aa8c:       f240 23ff       movw    r3, #767        ; 0x2ff
    aa90:       8333            strh    r3, [r6, #24]
        UNALIGNED_PUT(0, &dst->s6_addr16[1]);
    aa92:       f848 5d24       str.w   r5, [r8, #-36]!
    aa96:       2204            movs    r2, #4
    aa98:       4641            mov     r1, r8
    aa9a:       f106 001a       add.w   r0, r6, #26
    aa9e:       f7f6 f961       bl      d64 <memcpy>

In full compliance with C semantics, it creates a variable in memory (on the stack) as requested, and passes its address to a function.

And as your macro has a bug - you type off the value, whereas it should off the pointer, it memcpy's an int (type of an integer value).

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

The UNALIGNED_{PUT,GET}() macros are defined in the toolchain-specific headers

So, the first problem we have is lack of the baseline neutral implementation. And that will require UNALIGNED_PUT8, UNALIGNED_PUT16, UNALIGNED_PUT32, as we can't rely on __typeof__.

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

I'm happy to report that gcc7 persists in its error. I'm making following change, to test hypothesis that being 1st structure member what causes the issue:

 #define UNALIGNED_PUT(v, p)                                             \
 do {                                                                    \
        struct __attribute__((__packed__)) {                            \
+               char _; \
                __typeof__(*p) __v;                                     \
-       } *__p = (__typeof__(__p)) (p);                                 \
+       } *__p = (__typeof__(__p)) ((char*)p - 1);                                 \
        __p->__v = (v);                                               \
 } while (0)

Buy nah, it's smart enough to compensate out that char in the beginning and decrement of pointer, and generates strd still.

I.e. it looks almost as peephole-style optimization, where it replaces 4 of strh with one strd, missing the alignment constraints on the pointer involved.

And it's very unstable opimization, e.g. making the following change:

 void net_ipv6_addr_create_solicited_node(const struct in6_addr *src,
                                         struct in6_addr *dst)
 {
-       dst->s6_addr[0]   = 0xFF;
-       dst->s6_addr[1]   = 0x02;
+//     dst->s6_addr[0]   = 0xFF;
+//     dst->s6_addr[1]   = 0x02;
        UNALIGNED_PUT(0, &dst->s6_addr16[1]);
        UNALIGNED_PUT(0, &dst->s6_addr16[2]);
        UNALIGNED_PUT(0, &dst->s6_addr16[3]);

It no longer uses strd, but is back to strh (and even strb in one case too). Again looks like not a well thought-out optimization, but some peephole one, going wrong.

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

@mazhenke:

I add some compiler_barrier() between the UNALIGNED_PUT,

Ah, ok, so it's defined by the very same include/toolchain/gcc.h. Looked strange, because we usually use uppercase for such macros.

And thanks for the hint, I guess that's a winning workaround for this issue. It's still a workaround, because it prohibits all coalescing and optimization of multiple UNALIGNED_PUT's. There's nothing wrong with it, e.g. in Cortex-M3/4, two strb can be optimized into one strh (but not on Cortex-M0). It's just there should be limits to it, e.g. strd should not be used if pointer can be unaligned.

I'll prepare patch for this.

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

P.S. I also wanted to test volatile, but I guess it can only have stronger effect than compiler_barrier().

@pfalcon
Copy link
Contributor

pfalcon commented Jun 6, 2018

Some info about compiler barrier: http://preshing.com/20120625/memory-ordering-at-compile-time/

@pfalcon pfalcon self-assigned this Jun 7, 2018
pfalcon added a commit to pfalcon/zephyr that referenced this issue Jun 8, 2018
compiler_barrier() is itself defined down in this file. Without
adding it, newer versions of GCC (7+) for ARM Cortex-M may mistakenly
coalesce multiple strb/strh/str (store byte/half-word/word)
instructions, which support unaligned access on some
sub-architectures (Cortex-M3 and higher, but not on Cortex-M0),
into strd (store double), which doesn't support unaligned access.

Fixes: zephyrproject-rtos#6307

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
MaureenHelm pushed a commit that referenced this issue Jun 8, 2018
compiler_barrier() is itself defined down in this file. Without
adding it, newer versions of GCC (7+) for ARM Cortex-M may mistakenly
coalesce multiple strb/strh/str (store byte/half-word/word)
instructions, which support unaligned access on some
sub-architectures (Cortex-M3 and higher, but not on Cortex-M0),
into strd (store double), which doesn't support unaligned access.

Fixes: #6307

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Ethernet area: Networking bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug
Projects
None yet
Development

No branches or pull requests