DEVICE_DEFINE(): properly align struct device instances
The DEVICE_DEFINE() macro creates instances of struct device that are gathered into a contiguous list by the linker. However, some assemblers pad sections to the next 16-byte boundary or so by default, screwing up the list walk in z_sys_device_do_config_level(). This is especially true for 64-bit compilation where sizeof(struct device) isn't a multiple of 16. Enforcing an alignment at the linker level would solve this issue when instances of struct device are gathered from different object files. However it doesn't solve it when multiple instances are created within the same object file where the first instance still has a gap with the next instance, as the assembler does add padding upon section switch even though the object file ends up with a single section with both instances. In that case the linker would get rid of the trailing padding only, leaving the inner gaps between instances in place. The actual fix is to provide an explicit alignment attribute to the section for every instances, using __alignof(struct device) which is the alignment expected by the compiler for that structure. This also means that the x86_64 workaround in the struct device definition may go as the "edge case" it refers to is now properly handled. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
6ecbe713b5
commit
7daa5451cf
1 changed files with 4 additions and 10 deletions
|
@ -108,7 +108,8 @@ extern "C" {
|
|||
.config_info = (cfg_info) \
|
||||
}; \
|
||||
static struct device _CONCAT(__device_, dev_name) __used \
|
||||
__attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
|
||||
__attribute__((__section__(".init_" #level STRINGIFY(prio)), \
|
||||
aligned(__alignof(struct device)))) = { \
|
||||
.config = &_CONCAT(__config_, dev_name), \
|
||||
.driver_api = api, \
|
||||
.driver_data = data \
|
||||
|
@ -165,7 +166,8 @@ extern "C" {
|
|||
.config_info = (cfg_info) \
|
||||
}; \
|
||||
static struct device _CONCAT(__device_, dev_name) __used \
|
||||
__attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
|
||||
__attribute__((__section__(".init_" #level STRINGIFY(prio)), \
|
||||
aligned(__alignof(struct device)))) = { \
|
||||
.config = &_CONCAT(__config_, dev_name), \
|
||||
.driver_api = api, \
|
||||
.driver_data = data, \
|
||||
|
@ -276,14 +278,6 @@ struct device {
|
|||
struct device_config *config;
|
||||
const void *driver_api;
|
||||
void *driver_data;
|
||||
#if defined(__x86_64) && __SIZEOF_POINTER__ == 4
|
||||
/* The x32 ABI hits an edge case. This is a 12 byte struct,
|
||||
* but the x86_64 linker will pack them only in units of 8
|
||||
* bytes, leading to alignment problems when iterating over
|
||||
* the link-time array.
|
||||
*/
|
||||
void *padding;
|
||||
#endif
|
||||
};
|
||||
|
||||
void z_sys_device_do_config_level(s32_t level);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue