Hi, 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! Mark. _______________________________________________ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel