diff mbox series

[1/2] irqchip/qcom-pdc: don't read version register if it is not available

Message ID 20230825213552.1646321-1-dmitry.baryshkov@linaro.org
State New
Headers show
Series [1/2] irqchip/qcom-pdc: don't read version register if it is not available | expand

Commit Message

Dmitry Baryshkov Aug. 25, 2023, 9:35 p.m. UTC
On Qualcomm SM8150 the PDC resource has size 0x400. When PDC driver
tries to read the version register (0x1000), it reads past the end of
this resource, causing kernel crash.

Check the size of PDC resource before reading the PDC_VERSION register.

Fixes: bc82cc42644b ("irqchip/qcom-pdc: Add support for v3.2 HW")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/irqchip/qcom-pdc.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

Comments

Maulik Shah Aug. 28, 2023, 9:36 a.m. UTC | #1
Hi Dmitry,

This patch may be useful if there was a case where some PDCs don't have 
version register populated/available,
In all PDC versions, version register is always available but due to reg 
size not good enough in device tree for SM8150 it failed to read.

reg size in device node must be expanded if its too small to access all 
registers and i think
additional check in driver to check if size is good enough would not be 
of much use.

Thanks,
Maulik

On 8/26/2023 3:05 AM, Dmitry Baryshkov wrote:

> On Qualcomm SM8150 the PDC resource has size 0x400. When PDC driver
> tries to read the version register (0x1000), it reads past the end of
> this resource, causing kernel crash.
>
> Check the size of PDC resource before reading the PDC_VERSION register.
>
> Fixes: bc82cc42644b ("irqchip/qcom-pdc: Add support for v3.2 HW")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
Konrad Dybcio Aug. 28, 2023, 9:45 a.m. UTC | #2
On 28.08.2023 11:36, Maulik Shah (mkshah) wrote:
> Hi Dmitry,
> 
> This patch may be useful if there was a case where some PDCs don't have version register populated/available,
> In all PDC versions, version register is always available but due to reg size not good enough in device tree for SM8150 it failed to read.
> 
> reg size in device node must be expanded if its too small to access all registers and i think
> additional check in driver to check if size is good enough would not be of much use.
The devicetree change has already been commited and not taking care
of this on the driver side would break backwards compatibility with
devicetrees without this change.


Konrad
Marc Zyngier Aug. 28, 2023, 10:04 a.m. UTC | #3
On Mon, 28 Aug 2023 10:46:10 +0100,
Dmitry Baryshkov <dmitry.baryshkov@linaro.org> wrote:
> 
> On Mon, 28 Aug 2023 at 12:36, Maulik Shah (mkshah)
> <quic_mkshah@quicinc.com> wrote:
> >
> > Hi Dmitry,
> >
> > This patch may be useful if there was a case where some PDCs don't have
> > version register populated/available,
> > In all PDC versions, version register is always available but due to reg
> > size not good enough in device tree for SM8150 it failed to read.
> >
> > reg size in device node must be expanded if its too small to access all
> > registers and i think
> > additional check in driver to check if size is good enough would not be
> > of much use.
> 
> Unfortunately, it doesn't work this way. DT files are ABI. Even if we
> change the DT, the kernel should continue working with the older
> version.
> Thus, we have to add such bandaid code, which will keep the kernel
> from crashing if old DT was used.

You're missing the point: all existing PDC HW have version register.
The fact that the DT is crap doesn't invalidate this simple fact. It
is thus perfectly possible for the driver to *ignore* the crap and do
the right thing by expanding the size of the mapping, rather than
falling back to the non-versioned code.

There is definitely precedents for this sort of behaviour, such as the
ARM GICv2 probe code.

	M.
Dmitry Baryshkov Aug. 28, 2023, 10:18 a.m. UTC | #4
On Mon, 28 Aug 2023 at 13:04, Marc Zyngier <maz@kernel.org> wrote:
>
> On Mon, 28 Aug 2023 10:46:10 +0100,
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org> wrote:
> >
> > On Mon, 28 Aug 2023 at 12:36, Maulik Shah (mkshah)
> > <quic_mkshah@quicinc.com> wrote:
> > >
> > > Hi Dmitry,
> > >
> > > This patch may be useful if there was a case where some PDCs don't have
> > > version register populated/available,
> > > In all PDC versions, version register is always available but due to reg
> > > size not good enough in device tree for SM8150 it failed to read.
> > >
> > > reg size in device node must be expanded if its too small to access all
> > > registers and i think
> > > additional check in driver to check if size is good enough would not be
> > > of much use.
> >
> > Unfortunately, it doesn't work this way. DT files are ABI. Even if we
> > change the DT, the kernel should continue working with the older
> > version.
> > Thus, we have to add such bandaid code, which will keep the kernel
> > from crashing if old DT was used.
>
> You're missing the point: all existing PDC HW have version register.
> The fact that the DT is crap doesn't invalidate this simple fact. It
> is thus perfectly possible for the driver to *ignore* the crap and do
> the right thing by expanding the size of the mapping, rather than
> falling back to the non-versioned code.

Ah. Interesting idea. If that's the overall consensus I can send v2
doing this. Not sure what is better though.

>
> There is definitely precedents for this sort of behaviour, such as the
> ARM GICv2 probe code.
Maulik Shah Aug. 29, 2023, 4:25 a.m. UTC | #5
Hi,

On 8/28/2023 3:48 PM, Dmitry Baryshkov wrote:
> On Mon, 28 Aug 2023 at 13:04, Marc Zyngier <maz@kernel.org> wrote:
>> On Mon, 28 Aug 2023 10:46:10 +0100,
>> Dmitry Baryshkov <dmitry.baryshkov@linaro.org> wrote:
>>> On Mon, 28 Aug 2023 at 12:36, Maulik Shah (mkshah)
>>> <quic_mkshah@quicinc.com> wrote:
>>>> Hi Dmitry,
>>>>
>>>> This patch may be useful if there was a case where some PDCs don't have
>>>> version register populated/available,
>>>> In all PDC versions, version register is always available but due to reg
>>>> size not good enough in device tree for SM8150 it failed to read.
>>>>
>>>> reg size in device node must be expanded if its too small to access all
>>>> registers and i think
>>>> additional check in driver to check if size is good enough would not be
>>>> of much use.
>>> Unfortunately, it doesn't work this way. DT files are ABI. Even if we
>>> change the DT, the kernel should continue working with the older
>>> version.
>>> Thus, we have to add such bandaid code, which will keep the kernel
>>> from crashing if old DT was used.
>> You're missing the point: all existing PDC HW have version register.
>> The fact that the DT is crap doesn't invalidate this simple fact. It
>> is thus perfectly possible for the driver to *ignore* the crap and do
>> the right thing by expanding the size of the mapping, rather than
>> falling back to the non-versioned code.
> Ah. Interesting idea. If that's the overall consensus I can send v2
> doing this. Not sure what is better though.
if expanding register size and reading version register looks too hacky 
the other way is to have "qcom,pdc-v3.2" compatible for newer targets 
post which don't need to read version register to figure out as the 
compatible string is enough to tell if v3.2 HW behavior needs to apply.

I am ok with either approach but biased towards using version register 
rather than compatibles.

Thanks,
Maulik
>> There is definitely precedents for this sort of behaviour, such as the
>> ARM GICv2 probe code.
diff mbox series

Patch

diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 9bb6951257c2..431b213b5abb 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -324,6 +324,7 @@  static int pdc_setup_pin_mapping(struct device_node *np)
 static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 {
 	struct irq_domain *parent_domain, *pdc_domain;
+	struct resource res;
 	int ret;
 
 	pdc_base = of_iomap(node, 0);
@@ -332,7 +333,14 @@  static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 		return -ENXIO;
 	}
 
-	pdc_version = pdc_reg_read(PDC_VERSION, 0);
+	if (of_address_to_resource(node, 0, &res))
+		return -EINVAL;
+
+	/* compat with old sm8150 DT which had very small region for PDC */
+	if (resource_size(&res) > PDC_VERSION)
+		pdc_version = pdc_reg_read(PDC_VERSION, 0);
+	else
+		pdc_version = 0;
 
 	parent_domain = irq_find_host(parent);
 	if (!parent_domain) {