| From b216342f2b771cefd53e325a93f1b5a05e54f554 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 28 May 2022 11:08:48 -0700 |
| Subject: drm: fix EDID struct for old ARM OABI format |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| [ Upstream commit 47f15561b69e226bfc034e94ff6dbec51a4662af ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/drm/drm_edid.h | 6 +++--- |
| 1 file changed, 3 insertions(+), 3 deletions(-) |
| |
| diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h |
| index c3a7d440bc11..514a02095983 100644 |
| --- a/include/drm/drm_edid.h |
| +++ b/include/drm/drm_edid.h |
| @@ -114,7 +114,7 @@ struct detailed_data_monitor_range { |
| u8 supported_scalings; |
| u8 preferred_refresh; |
| } __attribute__((packed)) cvt; |
| - } formula; |
| + } __attribute__((packed)) formula; |
| } __attribute__((packed)); |
| |
| struct detailed_data_wpindex { |
| @@ -147,7 +147,7 @@ struct detailed_non_pixel { |
| struct detailed_data_wpindex color; |
| struct std_timing timings[6]; |
| struct cvt_timing cvt[4]; |
| - } data; |
| + } __attribute__((packed)) data; |
| } __attribute__((packed)); |
| |
| #define EDID_DETAIL_EST_TIMINGS 0xf7 |
| @@ -165,7 +165,7 @@ struct detailed_timing { |
| union { |
| struct detailed_pixel_timing pixel_data; |
| struct detailed_non_pixel other_data; |
| - } data; |
| + } __attribute__((packed)) data; |
| } __attribute__((packed)); |
| |
| #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0) |
| -- |
| 2.35.1 |
| |