From: Ferruh Yigit <ferruh.yigit@amd.com>
To: "Morten Brørup" <mb@smartsharesystems.com>,
fengchengwen <fengchengwen@huawei.com>,
dev@dpdk.org, "Dengdui Huang" <huangdengdui@huawei.com>
Subject: Re: Strict aliasing problem with rte_eth_linkstatus_set()
Date: Wed, 10 Apr 2024 16:57:19 +0100 [thread overview]
Message-ID: <af2d7b96-3b81-4748-a0cf-6a1b3fef27be@amd.com> (raw)
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35E9F388@smartserver.smartshare.dk>
On 4/10/2024 11:30 AM, Morten Brørup wrote:
>> From: fengchengwen [mailto:fengchengwen@huawei.com]
>> Sent: Wednesday, 10 April 2024 11.34
>>
>> Hi All,
>>
>> We have a problem introduced by a compiler upgrade (from gcc10 to gcc12.3),
>> we've done some
>> research but haven't been able to figure out why. We'd like the community's
>> help.
>>
>> Environment:
>> 1. Source: DPDK 23.11
>> 2. GCC: 12.3.1 [1]
>> 3. Compiled with target kunpeng SoC (ARM64)
>> 4. Run on kunpeng SoC
>>
>>
>> Problem & Debug:
>> 1. We found the hns3 driver fails to update the link status. The corresponding
>> function is
>> hns3_update_linkstatus_and_event [2], and we found the rte_eth_linkstatus_set
>> [3] always return zero.
>> 2. After disassembly the hns3_update_linkstatus_and_event, and found
>> rte_eth_linkstatus_set's
>> rte_atomic_exchange_explicit return to xzr register (which is zero register):
>> 1239fec: 3900f3e0 strb w0, [sp, #60]
>> 1239ff0: 9101a041 add x1, x2, #0x68 ---x2 seem not the
>> variable new_link
>> 1239ff4: f8ff8022 swpal xzr, x2, [x1] ---this instr
>> corresponding rte_atomic_exchange_explicit,
>> it will place
>> the resut in xzr which always zero,
>> and this will
>> lead to rte_eth_linkstatus_set return 0.
>> 1239ff8: 3940f3e0 ldrb w0, [sp, #60]
>> 1239ffc: d3609c41 ubfx x1, x2, #32, #8
>> 123a000: 4a010000 eor w0, w0, w1
>> 123a004: 36100080 tbz w0, #2, 123a014
>> <hns3_update_linkstatus_and_event+0xd4>
>> 3. We checked other "ret = rte_eth_linkstatus_set" calls, and can't find
>> similar problem.
>> 4. After reading a lot of documents, we preliminarily think that the problem
>> is caused by -fstrict-aliasing
>> (which was enabled default with O2 or O3), if compiled with -fno-strict-
>> aliasing, then this problem don't
>> exist. We guest this maybe strict-aliasing's bug which only happened in our
>> function.
>> 5. We also try to use union to avoid such aliasing in rte_eth_linkstatus_set,
>> we changed the struct
>> rte_eth_link define, and it works:
>> -__extension__
>> -struct __rte_aligned(8) rte_eth_link { /**< aligned for atomic64 read/write
>> */
>> - uint32_t link_speed; /**< RTE_ETH_SPEED_NUM_ */
>> - uint16_t link_duplex : 1; /**< RTE_ETH_LINK_[HALF/FULL]_DUPLEX */
>> - uint16_t link_autoneg : 1; /**< RTE_ETH_LINK_[AUTONEG/FIXED] */
>> - uint16_t link_status : 1; /**< RTE_ETH_LINK_[DOWN/UP] */
>> +struct rte_eth_link { /**< aligned for atomic64 read/write */
>> + union {
>> + uint64_t val64;
>> + struct {
>> + uint32_t link_speed; /**< RTE_ETH_SPEED_NUM_
>> */
>> + uint16_t link_duplex : 1; /**<
>> RTE_ETH_LINK_[HALF/FULL]_DUPLEX */
>> + uint16_t link_autoneg : 1; /**<
>> RTE_ETH_LINK_[AUTONEG/FIXED] */
>> + uint16_t link_status : 1; /**<
>> RTE_ETH_LINK_[DOWN/UP] */
>> + };
>> + };
>> };
>> the corresponding rte_eth_linkstatus_set:
>> @@ -1674,18 +1674,13 @@ static inline int
>> rte_eth_linkstatus_set(struct rte_eth_dev *dev,
>> const struct rte_eth_link *new_link)
>> {
>> - RTE_ATOMIC(uint64_t) *dev_link = (uint64_t __rte_atomic *)&(dev-
>>> data->dev_link);
>> - union {
>> - uint64_t val64;
>> - struct rte_eth_link link;
>> - } orig;
>> -
>> - RTE_BUILD_BUG_ON(sizeof(*new_link) != sizeof(uint64_t));
>> + struct rte_eth_link old_link;
>>
>> - orig.val64 = rte_atomic_exchange_explicit(dev_link, *(const uint64_t
>> *)new_link,
>> + old_link.val64 = rte_atomic_exchange_explicit(&dev->data-
>>> dev_link.val64,
>> + new_link->val64,
>> rte_memory_order_seq_cst);
>>
>> - return (orig.link.link_status == new_link->link_status) ? -1 : 0;
>> + return (old_link.link_status == new_link->link_status) ? -1 : 0;
>> }
>> 6. BTW: the linux kernel enabled "-fno-strict-aliasing" default, please see
>> [4] for more.
>>
>
> Thank you for the detailed analysis.
> Looking at the GCC documentation for -fstrict-aliasing supports your conclusion.
>
Agree that issue looks like strict aliasing violation.
> Just out of curiosity:
> Does building with -Wstrict-aliasing=3 or -Wstrict-aliasing=1 provide any useful information?
> And are the any differences in the strict-aliasing warnings without/with your fix?
>
>>
>> Last: We think there are two ways to solve this problem.
>> 1. Add the compilation option '-fno-strict-aliasing' for hold DPDK project.
>> 2. Use union to avoid such aliasing in rte_eth_linkstatus_set (please see
>> above).
>> PS: We prefer first way.
>>
>> Hope for more discuess.
>>
>> Thanks
>
> Unfortunately, DPDK uses a lot of type casting where other methods would be formally more correct.
> I fear that you only found one of potentially many more bugs like this.
> Fixing this generally would be great, but probably not realistic.
>
> I prefer correctness over performance, and thus am in favor of adding -fno-strict-aliasing project wide.
>
strict aliasing violation is undefined behavior, instead of ignoring it
why not fix it, and option 2 is a way to fix it.
> Performance can be improved by adding more hints and attributes to functions and parameters, e.g. rte_memcpy() could be:
> __attribute__((access(write_only, 1, 3), access(read_only, 2, 3)))
> static void *
> rte_memcpy(void * restrict dst, const void * restrict src, size_t n);
>
> Instead of just:
> static void *
> rte_memcpy(void * dst, const void * src, size_t n);
>
>
>>
>>
>> [1] https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads/12-3-
>> rel1
>> [2] void
>> hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query)
>> {
>> struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
>> struct rte_eth_link new_link;
>> int ret;
>>
>> if (query)
>> hns3_update_port_link_info(dev);
>>
>> memset(&new_link, 0, sizeof(new_link));
>> hns3_setup_linkstatus(dev, &new_link);
>>
>> ret = rte_eth_linkstatus_set(dev, &new_link);
>> if (ret == 0 && dev->data->dev_conf.intr_conf.lsc != 0)
>> hns3_start_report_lse(dev);
>> }
>> [3] static inline int
>> rte_eth_linkstatus_set(struct rte_eth_dev *dev,
>> const struct rte_eth_link *new_link)
>> {
>> RTE_ATOMIC(uint64_t) *dev_link = (uint64_t __rte_atomic *)&(dev->data-
>>> dev_link);
>> union {
>> uint64_t val64;
>> struct rte_eth_link link;
>> } orig;
>>
>> RTE_BUILD_BUG_ON(sizeof(*new_link) != sizeof(uint64_t));
>>
>> orig.val64 = rte_atomic_exchange_explicit(dev_link, *(const uint64_t
>> *)new_link,
>> rte_memory_order_seq_cst);
>>
>> return (orig.link.link_status == new_link->link_status) ? -1 : 0;
>> }
>> [4] https://lore.kernel.org/all/b3itcd$2bi$1@penguin.transmeta.com/
next prev parent reply other threads:[~2024-04-10 15:57 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-10 9:33 Strict aliasing problem with rte_eth_linkstatus_set() fengchengwen
2024-04-10 10:30 ` Morten Brørup
2024-04-10 15:57 ` Ferruh Yigit [this message]
2024-04-11 2:03 ` fengchengwen
2024-04-10 15:27 ` Stephen Hemminger
2024-04-10 15:58 ` Ferruh Yigit
2024-04-10 17:54 ` Morten Brørup
2024-04-10 19:58 ` Tyler Retzlaff
2024-04-11 3:20 ` fengchengwen
2024-04-10 21:18 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=af2d7b96-3b81-4748-a0cf-6a1b3fef27be@amd.com \
--to=ferruh.yigit@amd.com \
--cc=dev@dpdk.org \
--cc=fengchengwen@huawei.com \
--cc=huangdengdui@huawei.com \
--cc=mb@smartsharesystems.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.