Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm: fix EDID struct for old ARM OABI format

When building the kernel for arm with the "-mabi=apcs-gnu" option, gcc
will force alignment of all structures and unions to a word boundary
(see also STRUCTURE_SIZE_BOUNDARY and the "-mstructure-size-boundary=XX"
option if you're a gcc person), even when the members of said structures
do not want or need said alignment.

This completely messes up the structure alignment of 'struct edid' on
those targets, because even though all the embedded structures are
marked with "__attribute__((packed))", the unions that contain them are
not.

This was exposed by commit f1e4c916f97f ("drm/edid: add EDID block count
and size helpers"), but the bug is pre-existing. That commit just made
the structure layout problem cause a build failure due to the addition
of the

BUILD_BUG_ON(sizeof(*edid) != EDID_LENGTH);

sanity check in drivers/gpu/drm/drm_edid.c:edid_block_data().

This legacy union alignment should probably not be used in the first
place, but we can fix the layout by adding the packed attribute to the
union entries even when each member is already packed and it shouldn't
matter in a sane build environment.

You can see this issue with a trivial test program:

union {
struct {
char c[5];
};
struct {
char d;
unsigned e;
} __attribute__((packed));
} a = { "1234" };

where building this with a normal "gcc -S" will result in the expected
5-byte size of said union:

.type a, @object
.size a, 5

but with an ARM compiler and the old ABI:

arm-linux-gnu-gcc -mabi=apcs-gnu -mfloat-abi=soft -S t.c

you get

.type a, %object
.size a, 8

instead, because even though each member of the union is packed, the
union itself still gets aligned.

This was reported by Sudip for the spear3xx_defconfig target.

Link: https://lore.kernel.org/lkml/YpCUzStDnSgQLNFN@debian/
Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+3 -3
+3 -3
include/drm/drm_edid.h
··· 121 121 u8 supported_scalings; 122 122 u8 preferred_refresh; 123 123 } __attribute__((packed)) cvt; 124 - } formula; 124 + } __attribute__((packed)) formula; 125 125 } __attribute__((packed)); 126 126 127 127 struct detailed_data_wpindex { ··· 154 154 struct detailed_data_wpindex color; 155 155 struct std_timing timings[6]; 156 156 struct cvt_timing cvt[4]; 157 - } data; 157 + } __attribute__((packed)) data; 158 158 } __attribute__((packed)); 159 159 160 160 #define EDID_DETAIL_EST_TIMINGS 0xf7 ··· 172 172 union { 173 173 struct detailed_pixel_timing pixel_data; 174 174 struct detailed_non_pixel other_data; 175 - } data; 175 + } __attribute__((packed)) data; 176 176 } __attribute__((packed)); 177 177 178 178 #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)