From: sashiko-bot@kernel.org
To: "Xin Tian" <tianx@yunsilicon.com>
Cc: linux-rdma@vger.kernel.org
Subject: Re: [PATCH 02/15] yunsilicon: add the register HAL
Date: Tue, 13 Oct 2026 11:46:13 +0000 [thread overview]
Message-ID: <sashiko-outbox-169650@kernel.org> (raw)
In-Reply-To: <20261012114354.2471317-3-tianx@yunsilicon.com>
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [Critical] net: xsc_get_db_addr returns hardcoded physical address instead of PCI BAR
- [High] net: global state corruption via shared static xsc_hw_reg structures
- [High] net: endianness breakage from C bitfields mapped to hardware descriptors
- [High] net: hardcoded 0xf clear of W1C interrupt register causes interrupt storm
- [High] net: silent fallback to 1GB page size for unhandled page shifts
- [Medium] net: uninitialized stack padding leaked to hardware doorbell MMIO registers
- [Medium] net: stale in_line bit retained in recycled DMA data segments
- [Medium] net: integer overflow in xsc_get_max_mr_size on 32-bit architectures
--
commit ab5e7ef7c47a715df12f926749f1e49fe112c55d
Author: Xin Tian <tianx@yunsilicon.com>
yunsilicon: add the register HAL
This commit adds the register access layer and per-device register map for
doorbells, interrupts, and command queues. The implementation provides
register offsets and configurations for the Andes device.
diff --git a/drivers/net/ethernet/yunsilicon/xsc/pci/hal/andes_impl.c b/drivers/net/ethernet/yunsilicon/xsc/pci/hal/andes_impl.c
new file mode 100644
index 0000000000000..46fc045f92c02
--- /dev/null
+++ b/drivers/net/ethernet/yunsilicon/xsc/pci/hal/andes_impl.c
@@ -0,0 +1,708 @@
[ ... ]
> +static void andes_ring_rx_doorbell(struct xsc_hw_reg *regs,
> + void __iomem *bar, u32 rqn, u32 next_pid)
> +{
> + union xsc_recv_doorbell {
> + struct{
> + u32 next_pid : 13;
> + u32 qp_id : 15;
> + };
> + u32 raw;
> + } db;
> +
> + db.next_pid = next_pid;
> + db.qp_id = rqn;
> +
> + /* Make sure that descriptors are written before
> + * updating doorbell record and ringing the doorbell
> + */
> + wmb();
> +
> + writel(db.raw, REG_ADDR(bar, regs->rx_db));
[Severity: Medium]
Does this leak uninitialized kernel stack memory to the hardware? The union
instantiated on the stack is not fully zero-initialized before its raw 32-bit
value is written to MMIO, leaving padding bits uninitialized.
[ ... ]
> +static void andes_set_eq_ci(struct xsc_hw_reg *regs,
> + void __iomem *bar, u32 eqn, u32 next_cid,
> + u8 arm)
> +{
> + union andes_eq_doorbell {
> + struct{
> + u32 eq_next_cid : 11;
> + u32 eq_id : 11;
> + u32 arm : 1;
> + };
> + u32 val;
> + } db;
> +
> + db.eq_next_cid = next_cid;
> + db.eq_id = eqn;
> + db.arm = !!arm;
> +
> + /* make sure val write to memory done */
> + wmb();
> + writel(db.val, REG_ADDR(bar, regs->event_db));
[Severity: Medium]
Could this leak uninitialized stack memory to the event doorbell register,
similar to the rx doorbell above?
[ ... ]
> +static u8 andes_get_mr_page_mode(u8 page_shift)
> +{
> +enum {
> + XSC_PAGE_SHIFT_4K = 12,
> + XSC_PAGE_SHIFT_64K = 16,
> + XSC_PAGE_SHIFT_2M = 21,
> + XSC_PAGE_SHIFT_1G = 30,
> +};
> +
> +enum {
> + XSC_PAGE_MODE_4K = 0,
> + XSC_PAGE_MODE_64K = 1,
> + XSC_PAGE_MODE_2M = 2,
> + XSC_PAGE_MODE_1G = 3,
> +};
> +
> + return (page_shift == XSC_PAGE_SHIFT_4K ? XSC_PAGE_MODE_4K :
> + (page_shift == XSC_PAGE_SHIFT_64K ? XSC_PAGE_MODE_64K :
> + (page_shift == XSC_PAGE_SHIFT_2M ? XSC_PAGE_MODE_2M : XSC_PAGE_MODE_1G)));
[Severity: High]
Does this silently fall back to XSC_PAGE_MODE_1G for unhandled page shifts
(such as 8K or 16K)? Could this cause out-of-bounds DMA accesses if the
hardware incorrectly maps 8K/16K buffers as 1GB pages?
[ ... ]
> +struct andes_cqe {
> + union {
> + u8 msg_opcode;
> + struct {
> + u8 error_code:7;
> + u8 is_error:1;
> + };
> + };
> + __le32 qp_id:15;
> + u8 rsv1:1;
> + u8 se:1;
> + u8 has_pph:1;
> + u8 type:1;
> + u8 with_immdt:1;
> + u8 csum_err:4;
> + __le32 imm_data;
> + __le32 msg_len;
> + __le32 vni;
> + __le64 ts:48;
> + __le16 wqe_id;
> + __le16 rsv[3];
> + __le16 rsv2:15;
> + u8 owner:1;
> +};
> +
> +static int andes_get_cqe_wqe_id(void *cqe)
> +{
> + return ((struct andes_cqe *)cqe)->wqe_id;
[Severity: High]
Does mapping C bitfields directly to hardware descriptors break on big-endian
systems? The compiler layout of bitfields is implementation-defined, which
frequently results in reversed bit packing.
Also, shouldn't le16_to_cpu() be used here when returning the __le16 wqe_id
as a native integer to avoid returning out-of-bounds indices on big-endian
architectures?
[ ... ]
> +static void andes_set_data_seg(void *data_seg, u32 length, u32 key, u64 addr)
> +{
> + struct andes_data_seg *seg = data_seg;
> +
> + seg->length = length;
> + seg->key = key;
> + seg->addr = addr;
[Severity: Medium]
If a data segment descriptor is recycled from a ring buffer, does failing to
explicitly clear the in_line bitfield here cause the hardware to misinterpret
the address and key as inline data?
[ ... ]
> +struct andes_send_wqe_ctrl_seg {
> + __le32 msg_opcode:8;
> + __le32 with_immdt:1;
> + __le32 csum_en:2;
> + __le32 ds_data_num:5;
> + __le32 wqe_id:16;
> + __le32 msg_len;
[ ... ]
> +static void andes_set_wqe_id(void *cseg, u32 wqe_id)
> +{
> + u16 _wqe_id = wqe_id;
> +
> + ((struct andes_send_wqe_ctrl_seg *)cseg)->wqe_id = cpu_to_le16(_wqe_id);
[Severity: High]
Is it safe to assign an explicitly byte-swapped value directly to a bitfield?
This could doubly corrupt the data on big-endian systems.
[ ... ]
> +static struct xsc_hw_reg andes_pf_regs = {
> + .req_pid_addr = HIF_CMDQM_HOST_REQ_PID_MEM_ADDR - 0xa0000000,
> + .req_cid_addr = HIF_CMDQM_HOST_REQ_CID_MEM_ADDR - 0xa0000000,
[ ... ]
> +static struct xsc_hw_reg andes_compressed_regs = {
> + .tx_db = TX_DB_FUNC_MEM_ADDR,
> + .rx_db = RX_DB_FUNC_MEM_ADDR,
[ ... ]
> +void xsc_init_hal(struct xsc_core_device *xdev, u32 device_id)
> +{
> + switch (device_id) {
> + case XSC_MC_VF_DEV_ID:
> + case XSC_MF_HOST_VF_DEV_ID:
> + case XSC_MS_VF_DEV_ID:
> + case XSC_MV_HOST_VF_DEV_ID:
> + /* VFs expose the same BAR-relative window as a bar-compressed PF */
> + xdev->hal_regs = &andes_compressed_regs;
> + break;
> + default:
> + if (is_pf_bar_compressed(xdev))
> + xdev->hal_regs = &andes_compressed_regs;
> + else
> + xdev->hal_regs = &andes_pf_regs;
[Severity: High]
Could multiple devices probed at the same time overwrite each other's hardware
capability offsets? It appears xdev->hal_regs is assigned to a globally shared
static structure rather than allocating a separate configuration per-device.
[ ... ]
> +void xsc_set_mtt_info(struct xsc_core_device *xdev)
> +{
> + struct xsc_hw_reg *regs = xdev->hal_regs;
> +
> + regs->mpt_tbl_addr = xdev->caps.mpt_tbl_addr - 0xa0000000;
> + regs->mpt_tbl_depth = xdev->caps.mpt_tbl_depth;
> + regs->mpt_tbl_width = xdev->caps.mpt_tbl_width;
> + regs->mtt_inst_base_addr = xdev->caps.mtt_inst_base_addr - 0xa0000000;
[Severity: High]
Does this mutate the global shared static structure assigned during
xsc_init_hal() with device-specific values?
[ ... ]
> +void xsc_get_db_addr(struct xsc_core_device *xdev,
> + u64 *tx_db, u64 *rx_db, u64 *cq_db, u64 *cq_reg, u64 *eq_db)
> +{
> + struct xsc_hw_reg *regs = xdev->hal_regs;
> +
> + if (!xsc_core_is_pf(xdev) || is_pf_bar_compressed(xdev)) {
[ ... ]
> + } else {
> + if (tx_db)
> + *tx_db = regs->tx_db + 0xa0000000;
> + if (rx_db)
> + *rx_db = regs->rx_db + 0xa0000000;
> + if (cq_db)
> + *cq_db = regs->complete_db + 0xa0000000;
> + if (cq_reg)
> + *cq_reg = regs->complete_reg + 0xa0000000;
> + if (eq_db)
> + *eq_db = regs->event_db + 0xa0000000;
> + }
[Severity: Critical]
Does adding a hardcoded offset of 0xa0000000 to the doorbell register offsets
yield a valid physical address? PCI device BAR physical addresses are typically
dynamically assigned and should be retrieved via pci_resource_start().
Returning a hardcoded physical address to upper layers could map arbitrary
physical memory.
[ ... ]
> +int xsc_handle_cmdq_interrupt(struct xsc_core_device *xdev)
> +{
> + union interrupt_stat {
> + struct {
> + u32 hw_read_req_err:1;
> + u32 hw_write_req_err:1;
> + u32 req_pid_err:1;
> + u32 rsp_cid_err:1;
> + };
> + u32 raw;
> + } stat;
> +
> + int err = 0;
> + int retry = 0;
> +
> + xsc_read32(xdev->bar, xdev->hal_regs->interrupt_stat_addr, &stat.raw,
> + sizeof(stat.raw));
> + while (stat.raw != 0) {
> + err++;
> + if (stat.hw_read_req_err) {
[ ... ]
> + } else {
> + stat.raw = 0;
> + pci_err(xdev->pdev, "ignore unknown interrupt!\n");
> + }
> + }
> +
> + if (retry) {
> + if (xdev->cmd.retry_cnt >= XSC_CMD_MAX_RETRY_CNT) {
> + pci_warn(xdev->pdev, "err handler have retried for %d times, stop retry\n",
> + xdev->cmd.retry_cnt);
> + goto clear_err_int;
> + }
> + xsc_write32(xdev->bar, xdev->hal_regs->req_pid_addr,
> + &xdev->cmd.cmd_pid);
> + xdev->cmd.retry_cnt++;
> + }
> +
> +clear_err_int:
> + if (err) {
> + stat.raw = 0xf;
> + xsc_write32(xdev->bar, xdev->hal_regs->interrupt_stat_addr, &stat.raw);
[Severity: High]
Will writing a hardcoded 0xf back to the hardware W1C register cause an
interrupt storm if a higher-order bit (e.g., bit 4) was asserted, since the
unknown bit would never be cleared?
Also, could unconditionally writing 1s to bits 0-3 clear new legitimate
interrupts that arrived after the initial read?
[ ... ]
> +u64 xsc_get_max_mr_size(struct xsc_core_device *xdev)
> +{
> + u64 max_mpt_mr_size = xdev->caps.max_mr_size;
> + u64 max_mtt_mr_size = xdev->caps.max_mtt * PAGE_SIZE;
[Severity: Medium]
Can this calculation overflow on 32-bit architectures where PAGE_SIZE is an
unsigned long? Both operands to the multiplication are 32-bit integers before
the assignment to the 64-bit result, which could truncate the capacity before
the type conversion happens.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012114352.2471317-1-tianx@yunsilicon.com?part=2
next prev parent reply other threads:[~2026-10-13 11:46 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 11:44 [PATCH 00/15] Yunsilicon ethernet and RDMA drivers Xin Tian
2026-10-12 11:43 ` [PATCH 01/15] yunsilicon: add PCI core driver skeleton Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:43 ` [PATCH 02/15] yunsilicon: add the register HAL Xin Tian
2026-10-12 15:21 ` Andrew Lunn
2026-10-13 11:46 ` sashiko-bot [this message]
2026-10-12 11:43 ` [PATCH 03/15] yunsilicon: add the command queue Xin Tian
2026-10-13 3:11 ` Junxian Huang
2026-10-13 14:31 ` Leon Romanovsky
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 04/15] yunsilicon: add event queues, interrupts and the Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 05/15] yunsilicon: add the CQ and QP resource pools Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 06/15] yunsilicon: add ethernet netdev registration Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 07/15] yunsilicon: add ethernet TX path Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 08/15] yunsilicon: add ethernet RX path and statistics Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 09/15] yunsilicon: add RDMA device support Xin Tian
2026-10-13 6:17 ` Junxian Huang
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 10/15] yunsilicon: add RDMA PD/MR Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 11/15] yunsilicon: add RDMA CQ/SRQ/AH Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 12/15] yunsilicon: add RDMA QP verbs Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 13/15] yunsilicon: add the RDMA send path Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 14/15] yunsilicon: add RDMA counters and sysfs Xin Tian
2026-10-13 11:46 ` sashiko-bot
2026-10-12 11:44 ` [PATCH 15/15] MAINTAINERS: add the Yunsilicon XSC drivers Xin Tian
2026-10-13 14:34 ` [PATCH 00/15] Yunsilicon ethernet and RDMA drivers Leon Romanovsky
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=sashiko-outbox-169650@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tianx@yunsilicon.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox