[ipxe-devel] [PATCH 1/1] [arm] add -mno-unaligned-access compiler flag

Mark Rutland mark.rutland at arm.com
Thu Apr 19 15:00:48 UTC 2018


On Thu, Apr 19, 2018 at 12:33:10AM +0100, Michael Brown wrote:
> On 18/04/18 20:21, Heinrich Schuchardt wrote:
> > the unaligned access problem with iPXE is still haunting me. Even with
> > SCTLR.A = 0 not all forms of unaligned access are allowable. When trying
> > to run iPXE on another board I experienced the following data abort:
> > 
> > static int tcp_rx ( struct io_buffer *iobuf,
> >                      struct net_device *netdev __unused,
> >                      struct sockaddr_tcpip *st_src,
> >                      struct sockaddr_tcpip *st_dest __unused,
> >                      uint16_t pshdr_csum ) {
> > 
> > ldr     r5, [r0, #12] /* Here a value from iobuf is copied */

So that's the load of iobuf->data, since we have:

struct_iobuf {
	struct list_head list;	// offset 0, 8 bytes
	void *head;		// offset 8, 4 bytes
	void *data;		// offset 12, 4 bytes


> > ...
> > ldrd    r6, r3, [r5, #4] /* Here the data abort occurs */

This is a combined load of tcphdr->ack and tcphdr->seq, since we have:

struct tcp_header { 
	uint16_t src; 		// offset 0, 2 bytes
	uint16_t dest; 		// offset 2, 2 bytes
	uint32_t seq;		// offset 4, 4 bytes
	uint32_t ack;		// offset 4, 4 bytes

Per the ARM PCS, a uint32_t should have a minimum 4-byte alignment, and
hence the compiler can assume that any struct tcp_header must have a
minimum alignment of 4 bytes...

> > r5 : 7ceba822 /* This value is only halfword aligned */

... but evidently this is not the case, presumably because we have no
control over the alignment of iobuf->data.

> > All forms of LDM and STM, LDRD, RFE, SRS, STRD, SWP must be word aligned
> > even if bit SCTLR.A = 0.
> > See ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition
> The fact that gcc is generating these instructions suggests that gcc
> believes that the instructions should be legal despite the lack of alignment
> guarantees.  This suggests that there should be some CPU/MMU configuration
> in which the instructions would work.

To the best of my knowledge, there is no such mode. The instructions
listed above always require word alignment, regardless of SCTLR.A or any
other configuration bit.

As above, I think that GCC is assuming the alignment required by the
PCS, and the problem is that we create a misaligned pointer contrary to
this requirement, without telling GCC we're doing something special.

> Mark: any suggestions?

Assuming data streams can be arbitrarily misaligned, we can tell GCC so
by making tcphdr __attribute__ ((aligned(1))).

As I understand it, within Linux, we have {get,put}_unaligned_*()
helpers to cater for cases like this.

For better or worse, I don't think that it is sufficient to pass the
compiler -mno-unaligned-accesses, even if it happens to mask the problem
in this specific case. The compiler can validly assume structures have
their usual alignment, and hence the LDRD should not be misaligned.

Sorry to be the bearer of bad news!


More information about the ipxe-devel mailing list