Skip to content

Conversation

@carlescufi
Copy link
Member

@carlescufi carlescufi commented Dec 4, 2021

This finally closes #16587 by removing all remaining pieces of code that can trigger the compiler warning after #39192 resolved all the ones in the networking code.

Additional analysis of the problem can be found here.

Comment on lines 2872 to 2878
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentionally misaligned as the field is inside a packed PDU struct. memcpy is used to fill this address ensuring there is no memfault.

Copy link
Member Author

@carlescufi carlescufi Dec 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is true too for line 3759, which is currently asserting?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3759 in this PR? None of the struct typecast use should assert, if they do, then its genuine misalignment/bug.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert in line 3759 in ull_conn.c hits, but it's not a struct, it's an int16_t @cvinayak \

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is true too for line 3759, which is currently asserting?

Yes.

@carlescufi carlescufi force-pushed the fix-16587 branch 2 times, most recently from 0ab22b5 to a2f5da6 Compare December 4, 2021 16:26
@cvinayak
Copy link
Contributor

cvinayak commented Dec 5, 2021

@carlescufi added commits to address required changes related to Broadcast ISO and Connected ISO implementations.

@carlescufi carlescufi force-pushed the fix-16587 branch 2 times, most recently from db3c954 to dd54411 Compare December 5, 2021 23:00
@carlescufi carlescufi requested a review from cvinayak December 6, 2021 10:29
kernel/mmu.c Outdated
Copy link
Member Author

@carlescufi carlescufi Dec 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcpleung @andyross @peter-mitsis any idea why we are hitting this assert if I uncomment it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not the expert on paging, but per the comment at the top of the struct in kernel/include/mmu.h it's intentionally misaligned for size optimization. z_page_frame is a 5- or 9-byte struct (one pointer and a flags byte) and the intent seems to be to pack them all together, alignment be damned.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I will leave out the assertion then. Thanks!

Copy link
Member Author

@carlescufi carlescufi Dec 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcpleung @andyross @peter-mitsis any idea why we are hitting this assert if I uncomment it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to be checking IS_PTR_ALIGNED(dyn, struct dyn_obj), no? It would be pathological, but you could imagine a kernel object aligned on N*8 + 4, with a (8-byte-aligned) dyn_obj field offset 4 or 12 bytes in, and that would be legal.

Beyond that possibility, the question is why this particular kernel object got misaligned. And as this is a dynamic object, that points to a glitch in the allocator? Someone should definitely look at this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be that the object is not allocated using the aligned alloc function?

Copy link
Member Author

@carlescufi carlescufi Dec 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to be checking IS_PTR_ALIGNED(dyn, struct dyn_obj),

@andyross
It really is the same, because the struct z_object is the first member of struct dyn_obj. But sure, let me fix that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be that the object is not allocated using the aligned alloc function?

@dcpleung I have no idea, could you check?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

z_impl_k_object_alloc() is using obj_align_get() to feed alignment to memory allocation, where it should align to sizeof(void *).

Does IS_PTR_ALIGNED(dyn, struct dyn_obj) work?

@carlescufi
Copy link
Member Author

@carlescufi added commits to address required changes related to Broadcast ISO and Connected ISO implementations.

Thank you @cvinayak, added that in the Bluetooth commit.

Copy link
Contributor

@cvinayak cvinayak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller changes look good.

kernel/mmu.c Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the explicit typecast is needed. Isn't one of the main feature of void pointers that you don't need to do explicit casts to/from them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, will check and remove. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be done now @jhedberg, thanks for catching this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also removed them from the inverse assignment (void to a data type) since those are not necessary either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here regarding unnecessary explicit typecast

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here. I guess it doesn't make sense to to go pointing out every single place in this PR, but if you agree it be good to remove these explicit casts.

After having resolved all of the instances of packed member access,
re-enable the warning.

Fixes zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Add a new macro, IS_PTR_ALIGNED() that verifies if a pointer is aligned
sufficiently for a particular data type provided as an argument.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Fix all instances in the controller of -Waddress-of-packed-member by
casting through an intermediate variable and verifying the alignment
with an assertion.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
@nashif nashif added the DNM This PR should not be merged (Do Not Merge) label Dec 8, 2021
Copy link
Contributor

@rlubos rlubos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

The following warning is triggered by GCC when
-Waddress-of-packed-member is enabled:

/home/carles/src/zephyr/zephyr/kernel/mmu.c: In function
'free_page_frame_list_put':
/home/carles/src/zephyr/zephyr/kernel/mmu.c:383:42: warning: taking
address of packed member of 'struct z_page_frame' may result in an
unaligned pointer value [-Waddress-of-packed-member]
  383 |  sys_slist_append(&free_page_frame_list, &pf->node);

This is due to the fact that sys_snode_t node is an unpacked structure
inside a packed z_page_frame structure, so that the alignment of the
former cannot be ensured if placed inside the latter.

Given that alignment of z_page_frame is ensured by the code, silence the
compiler by going through an intermediate variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/home/carles/src/zephyr/zephyr/kernel/userspace.c: In function
'unref_check':
/home/carles/src/zephyr/zephyr/kernel/userspace.c:471:28: warning:
converting a packed 'struct z_object' pointer (alignment 4) to a 'struct
dyn_obj' pointer (alignment 16) may result in an unaligned pointer value
[-Waddress-of-packed-mem
ber]
  471 |    CONTAINER_OF(ko, struct dyn_obj, kobj);

To avoid the warning, use an intermediate void * variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/home/carles/src/zephyr/zephyr/arch/x86/core/acpi.c: In function
'z_acpi_find_table':
/home/carles/src/zephyr/zephyr/arch/x86/core/acpi.c:190:24: warning:
taking address of packed member of 'struct acpi_xsdt' may result in an
unaligned pointer value [-Waddress-of-packed-member]
  190 |    for (uint64_t *tp = &xsdt->table_ptrs[0]; tp < end; tp++) {

To avoid the warning, use an intermediate void * variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/__w/zephyr/zephyr/drivers/gpio/gpio_sx1509b.c: In function
'port_write':
/__w/zephyr/zephyr/drivers/gpio/gpio_sx1509b.c:456:19: error: taking
address of packed member of 'struct sx1509b_pin_state' may result in an
unaligned pointer value [-Werror=address-of-packed-member]
  456 |  uint16_t *outp = &drv_data->pin_state.data;

To avoid the warning, use an intermediate void * variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/__w/zephyr/zephyr/tests/kernel/mem_protect/userspace/src/main.c: In
function 'test_main':
/__w/zephyr/zephyr/tests/kernel/mem_protect/userspace/src/main.c:1024:17:
error: converting a packed 'k_thread_stack_t' {aka 'struct
z_thread_stack_element'} pointer (alignment 1) to a 'struct
z_x86_thread_stack_header' pointer (alignment 4096) may result in an
unaligned pointer value [-Werror=address-of-packed-member]
 1024 |  hdr = ((struct z_x86_thread_stack_header *)ztest_thread_stack);

To avoid the warning, use an intermediate void * variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/__w/zephyr/zephyr/tests/lib/mpsc_pbuf/src/main.c: In function
'item_put_data_overwrite':
/__w/zephyr/zephyr/tests/lib/mpsc_pbuf/src/main.c:497:3: error:
converting a packed 'struct test_data_ext' pointer (alignment 1) to a
'uint32_t' {aka 'const unsigned int'} pointer (alignment 4) may result
in an unaligned pointer value [-Werror=address-of-packed-member]
  497 |   mpsc_pbuf_put_data(&buffer, (uint32_t *)&item, len);

To avoid the warning, as well as several others related to the same
problem, use an intermediate void * variable.

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
The warning below appears once -Waddress-of-packed-mem is enabled:

/__w/zephyr/zephyr/drivers/sensor/bmi160/bmi160.c: In function
bmi160_gyr_channel_get:
/__w/zephyr/zephyr/drivers/sensor/bmi160/bmi160.c:795:23: error: taking
address of packed member of struct <anonymous> may result in an
unaligned pointer value [-Werror=address-of-packed-member]
  795 |           data->sample.gyr, val);
      |           ~~~~~~~~~~~~^~~~
/__w/zephyr/zephyr/drivers/sensor/bmi160/bmi160.c: In function
bmi160_acc_channel_get:
/__w/zephyr/zephyr/drivers/sensor/bmi160/bmi160.c:807:23: error: taking
address of packed member of struct <anonymous> may result in an
unaligned pointer value [-Werror=address-of-packed-member]
  807 |           data->sample.acc, val);
      |           ~~~~~~~~~~~~^~~~

To avoid the warning, make the struct non-packed, since it is not
necessary in this case given that a union already guarantees that the
pointer to the union points to each member of the union equally..

More info in zephyrproject-rtos#16587.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>

struct dyn_obj *dyn = CONTAINER_OF(vko, struct dyn_obj, kobj);
/* TODO: check why this assert hits */
/*__ASSERT(IS_PTR_ALIGNED(dyn, struct dyn_obj), "unaligned z_object");*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to repeat my comment from elsewhere: this points to some suspicious behavior in the kernel dynamic object allocator. We should probably open a bug to make sure it gets looked at. Given the architecture, it's not illegal to misalign structs, but we shouldn't be doing it without a good reason.

(If I had to make a wild guess, it was written for i386 and 4-byte-aligns everything, so misses half the time for structs with 64 bit pointers.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, see here: #41062

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: API Changes to public APIs area: Bluetooth Controller area: Bluetooth area: Build System area: GPIO area: Kernel area: Sensors Sensors area: Tests Issues related to a particular existing or missing test area: Userspace Userspace area: X86 x86 Architecture (32-bit) DNM This PR should not be merged (Do Not Merge)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build failures with gcc 9.x

8 participants