Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
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

  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