All of lore.kernel.org
 help / color / mirror / Atom feed
From: Umang Jain <uajain@igalia.com>
To: Umang Jain via Kernel-dev <kernel-dev@igalia.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Lucas De Marchi <demarchi@kernel.org>,
	Mathias Nyman <mathias.nyman@linux.intel.com>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability
Date: Wed, 19 Aug 2026 05:09:14 +0000	[thread overview]
Message-ID: <c6334beb46fa154ecd031c4617618562@igalia.com> (raw)
In-Reply-To: <20260720191249.1272328-1-uajain@igalia.com>

Hello,

Gentle ping for review feedback.

On 2026-07-20 19:12, Umang Jain via Kernel-dev wrote:
> Currently, the early xhci-dbc assumes that the extended capability
> can be mapped within the fixed boot time mappings dictated by
> NR_FIX_BTMAPS.
> 
> This patch iterates over the PCI BAR address size to find and map
> xhci-xdbc capability which could be out-of-bounds otherwise,
> in xdbc_map_pci_mmio(). The iterations map the maximum allowed
> boot time mappings (fixmap size) at a time and search for xhci-xdbc
> capability offset, till the end of the bar address size.
> 
> This brings the need to track the early_ioremap() mapped size separately
> hence, introduce additional struct member xhci_base_length in
> struct xdbc_state.
> 
> Signed-off-by: Umang Jain <uajain@igalia.com>
> ---
> Link to earlier RFC:
> https://lore.kernel.org/all/20260604144122.962236-1-uajain@igalia.com/
> ---
>  drivers/usb/early/xhci-dbc.c | 94 +++++++++++++++++++++++++++++++++---
>  drivers/usb/early/xhci-dbc.h |  1 +
>  2 files changed, 87 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
> index 41118bba9197..5e540b6bf962 100644
> --- a/drivers/usb/early/xhci-dbc.c
> +++ b/drivers/usb/early/xhci-dbc.c
> @@ -35,10 +35,23 @@ static bool early_console_keep;
>  static inline void xdbc_trace(const char *fmt, ...) { }
>  #endif /* XDBC_TRACE */
>  
> +/* Size of xHCI debug capability structure */
> +#define XDBC_MAPPING_SIZE	56
> +
> +enum xdbc_capability_flags {
> +	XDBC_CAP_FLAG_NONE		= 0,
> +	XDBC_CAP_FLAG_LEGACY		= 1 << 0,
> +	XDBC_CAP_FLAG_PROTOCOL		= 1 << 1,
> +	XDBC_CAP_FLAG_DEBUG		= 1 << 2,
> +};
> +
>  static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
>  {
> -	u64 val64, sz64, mask64;
> +	u64 val64, sz64, mask64, fixmap_size, mapped_size;
> +	enum xdbc_capability_flags cap_flags = XDBC_CAP_FLAG_NONE;
> +	bool found_all_caps = false;
>  	void __iomem *base;
> +	int offset;
>  	u32 val, sz;
>  	u8 byte;
>  
> @@ -85,7 +98,72 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
>  
>  	xdbc.xhci_start = val64;
>  	xdbc.xhci_length = sz64;
> -	base = early_ioremap(val64, sz64);
> +
> +	fixmap_size = NR_FIX_BTMAPS << PAGE_SHIFT;
> +	if (sz64 < fixmap_size) {
> +		xdbc.xhci_base_length = sz64;
> +		return early_ioremap(val64, sz64);
> +	}
> +
> +	/*
> +	 * Base address size is greater than fixed size boot mappings,
> +	 * hence iterate over the region one fixmap_size at a time,
> +	 * starting with XHCI_EXP_CAPS_DEBUG capability.
> +	 */
> +	base = early_ioremap(val64, fixmap_size);
> +	offset = xhci_find_next_ext_cap(base, 0, 0);
> +	mapped_size = fixmap_size;
> +
> +	while (mapped_size <= sz64) {
> +		val = readl(base + offset);
> +		switch (XHCI_EXT_CAPS_ID(val)) {
> +		case XHCI_EXT_CAPS_DEBUG:
> +			if (offset + XDBC_MAPPING_SIZE > fixmap_size) {
> +				early_iounmap(base, fixmap_size);
> +				base = early_ioremap(val64 + offset, XDBC_MAPPING_SIZE);
> +
> +				mapped_size += offset;
> +				cap_flags = XDBC_CAP_FLAG_NONE;
> +			}
> +			cap_flags |= XDBC_CAP_FLAG_DEBUG;
> +			break;
> +		case XHCI_EXT_CAPS_PROTOCOL:
> +			cap_flags |= XDBC_CAP_FLAG_PROTOCOL;
> +			break;
> +		case XHCI_EXT_CAPS_LEGACY:
> +			cap_flags |= XDBC_CAP_FLAG_LEGACY;
> +			break;
> +		}
> +
> +		if ((cap_flags & XDBC_CAP_FLAG_DEBUG) &&
> +		    (cap_flags & XDBC_CAP_FLAG_PROTOCOL) &&
> +		    (cap_flags & XDBC_CAP_FLAG_LEGACY)) {
> +			found_all_caps = true;
> +			break;
> +		}
> +
> +		/*
> +		 * Find offset to next xhci-ext capability, remap if the offset
> +		 * is out of bounds of the already mapped region.
> +		 */
> +		offset = xhci_find_next_ext_cap(base, offset, 0);
> +		if (!offset) {
> +			early_iounmap(base, fixmap_size);
> +			base = early_ioremap(val64 + mapped_size, fixmap_size);
> +			mapped_size += fixmap_size;
> +
> +			offset = xhci_find_next_ext_cap(base, 0, 0);
> +			cap_flags = XDBC_CAP_FLAG_NONE;
> +
> +		}
> +	}
> +
> +	if (found_all_caps) {
> +		xdbc.xhci_base_length = fixmap_size;
> +	} else {
> +		xdbc.xhci_base_length = 0;
> +		base = NULL;
> +	}
>  
>  	return base;
>  }
> @@ -643,9 +721,9 @@ int __init early_xdbc_parse_parameter(char *s, int keep_early)
>  	offset = xhci_find_next_ext_cap(xdbc.xhci_base, 0, XHCI_EXT_CAPS_DEBUG);
>  	if (!offset) {
>  		pr_notice("xhci host doesn't support debug capability\n");
> -		early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
> +		early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
>  		xdbc.xhci_base = NULL;
> -		xdbc.xhci_length = 0;
> +		xdbc.xhci_base_length = 0;
>  
>  		return -ENODEV;
>  	}
> @@ -682,9 +760,9 @@ int __init early_xdbc_setup_hardware(void)
>  		xdbc.table_base = NULL;
>  		xdbc.out_buf = NULL;
>  
> -		early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
> +		early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
>  		xdbc.xhci_base = NULL;
> -		xdbc.xhci_length = 0;
> +		xdbc.xhci_base_length = 0;
>  	}
>  
>  	return ret;
> @@ -987,7 +1065,7 @@ static int __init xdbc_init(void)
>  	}
>  
>  	raw_spin_lock_irqsave(&xdbc.lock, flags);
> -	early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
> +	early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
>  	xdbc.xhci_base = base;
>  	offset = xhci_find_next_ext_cap(xdbc.xhci_base, 0, XHCI_EXT_CAPS_DEBUG);
>  	xdbc.xdbc_reg = (struct xdbc_regs __iomem *)(xdbc.xhci_base + offset);
> @@ -1004,7 +1082,7 @@ static int __init xdbc_init(void)
>  	memblock_phys_free(xdbc.table_dma, PAGE_SIZE);
>  	memblock_phys_free(xdbc.out_dma, PAGE_SIZE);
>  	writel(0, &xdbc.xdbc_reg->control);
> -	early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
> +	early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
>  
>  	return ret;
>  }
> diff --git a/drivers/usb/early/xhci-dbc.h b/drivers/usb/early/xhci-dbc.h
> index 8b4d71de45fc..e2aefb796084 100644
> --- a/drivers/usb/early/xhci-dbc.h
> +++ b/drivers/usb/early/xhci-dbc.h
> @@ -144,6 +144,7 @@ struct xdbc_state {
>  	u32			dev;
>  	u32			func;
>  	void __iomem		*xhci_base;
> +	size_t			xhci_base_length;
>  	u64			xhci_start;
>  	size_t			xhci_length;
>  	int			port_number;

  reply	other threads:[~2026-08-19  5:09 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 19:12 [PATCH] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability Umang Jain
2026-08-19  5:09 ` Umang Jain [this message]
2026-08-19 12:32 ` Mathias Nyman

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=c6334beb46fa154ecd031c4617618562@igalia.com \
    --to=uajain@igalia.com \
    --cc=demarchi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kernel-dev@igalia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@linux.intel.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.