* Strict aliasing problem with rte_eth_linkstatus_set() @ 2024-04-10 9:33 fengchengwen 2024-04-10 10:30 ` Morten Brørup 2024-04-10 15:27 ` Stephen Hemminger 0 siblings, 2 replies; 10+ messages in thread From: fengchengwen @ 2024-04-10 9:33 UTC (permalink / raw) To: dev, Dengdui Huang 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. 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 [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/ ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: Strict aliasing problem with rte_eth_linkstatus_set() 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 2024-04-11 2:03 ` fengchengwen 2024-04-10 15:27 ` Stephen Hemminger 1 sibling, 2 replies; 10+ messages in thread From: Morten Brørup @ 2024-04-10 10:30 UTC (permalink / raw) To: fengchengwen, dev, Dengdui Huang > 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. 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. 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/ ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 2024-04-10 10:30 ` Morten Brørup @ 2024-04-10 15:57 ` Ferruh Yigit 2024-04-11 2:03 ` fengchengwen 1 sibling, 0 replies; 10+ messages in thread From: Ferruh Yigit @ 2024-04-10 15:57 UTC (permalink / raw) To: Morten Brørup, fengchengwen, dev, Dengdui Huang 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/ ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 2024-04-10 10:30 ` Morten Brørup 2024-04-10 15:57 ` Ferruh Yigit @ 2024-04-11 2:03 ` fengchengwen 1 sibling, 0 replies; 10+ messages in thread From: fengchengwen @ 2024-04-11 2:03 UTC (permalink / raw) To: Morten Brørup, dev, Dengdui Huang Cc: Stephen Hemminger, Ferruh Yigit, Tyler Retzlaff Hi Morten, On 2024/4/10 18:30, 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. > > Just out of curiosity: > Does building with -Wstrict-aliasing=3 or -Wstrict-aliasing=1 provide any useful information? There are no any useful information with -Wstrict-aliasing=3 But for -Wstrict-aliasing=1, there are plenty of warnings, below is rte_eth_linkstatus_set: In file included from ../../dpdk/lib/ethdev/rte_ethdev.c:32: ../../dpdk/lib/ethdev/ethdev_driver.h: In function ‘rte_eth_linkstatus_set’: ../../dpdk/lib/ethdev/ethdev_driver.h:1677:67: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing] 1677 | RTE_ATOMIC(uint64_t) *dev_link = (uint64_t __rte_atomic *)&(dev->data->dev_link); | ^~~~~~~~~~~~~~~~~~~~~~ ../../dpdk/lib/ethdev/ethdev_driver.h:1685:9: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing] 1685 | orig.val64 = rte_atomic_exchange_explicit(dev_link, *(const uint64_t *)new_link, | ^~~~ Note: above without apply my fix (use union). > And are the any differences in the strict-aliasing warnings without/with your fix? After apply my fix (use union), with enabled -Wstrict-aliasing=1, there are no strict-aliasing warnings related to rte_eth_linkstatus_set. Thanks > >> >> 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. > > 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/ ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 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:27 ` Stephen Hemminger 2024-04-10 15:58 ` Ferruh Yigit 2024-04-10 17:54 ` Morten Brørup 1 sibling, 2 replies; 10+ messages in thread From: Stephen Hemminger @ 2024-04-10 15:27 UTC (permalink / raw) To: fengchengwen; +Cc: dev, Dengdui Huang On Wed, 10 Apr 2024 17:33:53 +0800 fengchengwen <fengchengwen@huawei.com> wrote: > 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. > Please send a patch to replace alias with union. PS: you can also override aliasing for a few lines of code with either pragma's or lots of casting. Both are messy and hard to maintain. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 2024-04-10 15:27 ` Stephen Hemminger @ 2024-04-10 15:58 ` Ferruh Yigit 2024-04-10 17:54 ` Morten Brørup 1 sibling, 0 replies; 10+ messages in thread From: Ferruh Yigit @ 2024-04-10 15:58 UTC (permalink / raw) To: Stephen Hemminger, fengchengwen; +Cc: dev, Dengdui Huang On 4/10/2024 4:27 PM, Stephen Hemminger wrote: > On Wed, 10 Apr 2024 17:33:53 +0800 > fengchengwen <fengchengwen@huawei.com> wrote: > >> 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. >> > > Please send a patch to replace alias with union. > +1 I am not sure about ABI implications, as size is not changing I expect it won't be an issue but may be good to verify with libabigail. > PS: you can also override aliasing for a few lines of code with either pragma's > or lots of casting. Both are messy and hard to maintain. ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: Strict aliasing problem with rte_eth_linkstatus_set() 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-10 21:18 ` Stephen Hemminger 1 sibling, 2 replies; 10+ messages in thread From: Morten Brørup @ 2024-04-10 17:54 UTC (permalink / raw) To: Stephen Hemminger, fengchengwen, Ferruh Yigit; +Cc: dev, Dengdui Huang > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Wednesday, 10 April 2024 17.27 > > On Wed, 10 Apr 2024 17:33:53 +0800 > fengchengwen <fengchengwen@huawei.com> wrote: > > > 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. > > > > Please send a patch to replace alias with union. +1 Fixing this specific bug would be good. Instinctively, I think we should build with -fno-strict-aliasing, so the compiler doesn't make the same mistake with similar code elsewhere in DPDK. I fear there is more than this instance. I also wonder if -Wstrict-aliasing could help us instead, if we don't want -fno-strict-aliasing. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 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 1 sibling, 1 reply; 10+ messages in thread From: Tyler Retzlaff @ 2024-04-10 19:58 UTC (permalink / raw) To: Morten Brørup Cc: Stephen Hemminger, fengchengwen, Ferruh Yigit, dev, Dengdui Huang On Wed, Apr 10, 2024 at 07:54:27PM +0200, Morten Brørup wrote: > > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > > Sent: Wednesday, 10 April 2024 17.27 > > > > On Wed, 10 Apr 2024 17:33:53 +0800 > > fengchengwen <fengchengwen@huawei.com> wrote: > > > > > 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. > > > > > > > Please send a patch to replace alias with union. > > +1 > > Fixing this specific bug would be good. > > Instinctively, I think we should build with -fno-strict-aliasing, so the compiler doesn't make the same mistake with similar code elsewhere in DPDK. I fear there is more than this instance. > I also wonder if -Wstrict-aliasing could help us instead, if we don't want -fno-strict-aliasing. agree, union is the correct way to get defined behavior. there are valuable optimizatons that the compiler can make with strict aliasing enabled so -Wstrict-aliasing is a good suggestion as opposed to disabling it. also the union won't break the abi if introduced correctly. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 2024-04-10 19:58 ` Tyler Retzlaff @ 2024-04-11 3:20 ` fengchengwen 0 siblings, 0 replies; 10+ messages in thread From: fengchengwen @ 2024-04-11 3:20 UTC (permalink / raw) To: Tyler Retzlaff, Morten Brørup Cc: Stephen Hemminger, Ferruh Yigit, dev, Dengdui Huang Hi All, On 2024/4/11 3:58, Tyler Retzlaff wrote: > On Wed, Apr 10, 2024 at 07:54:27PM +0200, Morten Brørup wrote: >>> From: Stephen Hemminger [mailto:stephen@networkplumber.org] >>> Sent: Wednesday, 10 April 2024 17.27 >>> >>> On Wed, 10 Apr 2024 17:33:53 +0800 >>> fengchengwen <fengchengwen@huawei.com> wrote: >>> >>>> 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. >>>> >>> >>> Please send a patch to replace alias with union. >> >> +1 >> >> Fixing this specific bug would be good. OK for this, and I already send a bugfix which use union. Thanks >> >> Instinctively, I think we should build with -fno-strict-aliasing, so the compiler doesn't make the same mistake with similar code elsewhere in DPDK. I fear there is more than this instance. >> I also wonder if -Wstrict-aliasing could help us instead, if we don't want -fno-strict-aliasing. > > agree, union is the correct way to get defined behavior. there are > valuable optimizatons that the compiler can make with strict aliasing > enabled so -Wstrict-aliasing is a good suggestion as opposed to > disabling it. > > also the union won't break the abi if introduced correctly. > . > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Strict aliasing problem with rte_eth_linkstatus_set() 2024-04-10 17:54 ` Morten Brørup 2024-04-10 19:58 ` Tyler Retzlaff @ 2024-04-10 21:18 ` Stephen Hemminger 1 sibling, 0 replies; 10+ messages in thread From: Stephen Hemminger @ 2024-04-10 21:18 UTC (permalink / raw) To: Morten Brørup; +Cc: fengchengwen, Ferruh Yigit, dev, Dengdui Huang On Wed, 10 Apr 2024 19:54:27 +0200 Morten Brørup <mb@smartsharesystems.com> wrote: > > Please send a patch to replace alias with union. > > +1 > > Fixing this specific bug would be good. > > Instinctively, I think we should build with -fno-strict-aliasing, so the compiler doesn't make the same mistake with similar code elsewhere in DPDK. I fear there is more than this instance. > I also wonder if -Wstrict-aliasing could help us instead, if we don't want -fno-strict-aliasing. Strict aliasing checks should be enabled already if you use warning_level 2 and default (debugoptimized) or release build types. Unless some part of DPDK meson config is not overriding that. https://mesonbuild.com/Builtin-options.html Warning level 2 sets -Wall and -Wextra From gcc man page -Wstrict-aliasing This option is only active when -fstrict-aliasing is active. It warns about code that might break the strict aliasing rules that the compiler is using for optimization. The warning does not catch all cases, but does attempt to catch the more common pitfalls. It is included in -Wall. It is equivalent to -Wstrict-aliasing=3 and The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-04-11 3:20 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 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 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).