All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	"linux-ia64@vger.kernel.org" <linux-ia64@vger.kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Hanjun Guo <hanjun.guo@linaro.org>,
	Jiang Liu <jiang.liu@linux.intel.com>,
	Tony Luck <tony.luck@intel.com>, Tomasz Nowicki <tn@semihalf.com>,
	Mark Salter <msalter@redhat.com>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>
Subject: Re: [PATCH v2] PCI: ACPI: IA64: fix IO port generic range check
Date: Mon, 14 Mar 2016 14:27:08 -0500	[thread overview]
Message-ID: <20160314192708.GB16621@localhost> (raw)
In-Reply-To: <20160314145322.GE6629@red-moon>

On Mon, Mar 14, 2016 at 02:53:22PM +0000, Lorenzo Pieralisi wrote:
> On Thu, Mar 10, 2016 at 07:42:36AM +0000, Lorenzo Pieralisi wrote:
> 
> [...]
> 
> > > > We can't do that, it may work on IA64 but the ioport_resource is a
> > > > chunk of address space on IA64/ARM64 that has nothing to do with
> > > > the physical address at which the root bridges decode IO space (which
> > > > is what's contained in the resource).
> > > 
> > > I'm stumbling over "the physical address at which the root bridges
> > > decode IO space (which is what's contained in the resource)".
> > > 
> > > x86 host bridges typically just forward CPU-generated I/O port
> > > transactions to PCI with no address translation, so it sounds like
> > > you're talking about ia64/ARM64 bridges that decode CPU MMIO space and
> > > turn accesses into PCI I/O transactions.
> > > 
> > > If we start from a driver calling inb(), the driver supplies a Linux
> > > ioport number "X".  On ia64 (and I assume ARM64 as well), inb()
> > > performs an MMIO access to memory address "Y".  A host bridge consumes
> > > that MMIO access and generates a corresponding PCI I/O transaction to
> > > PCI ioport "Z".
> > > 
> > > It is indeed true that ioport_resource has nothing to do with memory
> > > addresses like "Y".  But the driver (and this part of the ACPI
> > > infrastructure) are dealing with ioport address "X", and that is
> > > definitely in an IORESOURCE_IO struct resource.  The IORESOURCE_MEM_
> > > struct resource that contains "Y" is internal to the host bridge
> > > driver and invisible to the device driver that's using inb().
> > 
> > The problem is, that's the address like "Y" that are checked in
> > acpi_dev_ioresource_flags() with current PCI initialization flow.
> > 
> > IO ports number "X" are created in (IA64) add_io_space() that is
> > executed after acpi_pci_probe_root_resources() is called (see
> > arch/ia64/pci/pci.c), that's the code that, IIUC, translates an
> > IO resource containing a CPU physical address (which is the address
> > that is ioremapped) to an IO resource containing a port number *and*
> > a corresponding MEM resource.
> > 
> > The check that causes failures (>=0x10003) is carried out
> > on the "raw" IO resource parsed from ACPI, not the one crafted
> > in add_io_space().
> > 
> > The resource checked in acpi_dev_ioresource_flags() is created from
> > ACPI IO descriptor and does contain CPU physical MMIO addresses,
> > comparing it to a port number is bound to fail, they do NOT represent
> > the same thing, happy be corrected.
> > 
> > That's the reason why currently IA64 IO space is not working, and
> > this patch fixes it, please correct me if I am wrong.
> > 
> > I will write back next week with the commits sequence and logic that
> > led to the current failure, sorry for not being able to respond
> > more promptly and in a comprehensive way I need sometime to write up
> > my understanding of the problem and commit logs, I will do that
> > next week.
> 
> I had a further look and went through commit history and I think
> my explanation above is correct, current code for IA64 PCI IO space
> is wrong IMO and the failures started with:
> 
> commit 3772aea7d6f3 ("ia64/PCI/ACPI: Use common ACPI resource parsing
> interface for host bridge")
> 
> because that's the commit that added IA64 PCI code to use
> acpi_dev_get_resources(), let me add to that.
> 
> For the records, and for the same reason, let's imagine we can fix the
> (>=0x10003) check in:
> 
> acpi_dev_ioresource_flags()
> 
> the code in acpi_pci_probe_root_resources() that checks the PCI IO
> resources (ie acpi_pci_root_validate_resources()) is wrong, in that it
> validates the PCI IO resources obtained from ACPI IO descriptors against
> ioport_resource, and that's not correct, they do not represent the
> same thing.
> 
> Code in acpi_dev_get_resources() walks the device (PCI host bridge in
> this case) resources (ie _CRS) with acpi_dev_process_resource().
> 
> On IA64 IO space is memory mapped, therefore the CPU physical address
> at which the PCI host bridge maps the IO space has to come from ACPI
> IO descriptors.
> 
> IIUC, those descriptors are parsed through:
> 
> acpi_dev_resource_address_space()
> acpi_dev_resource_ext_address_space()
> 
> which in turn call:
> 
> acpi_decode_space()
> 
> where the resource window is actually created, in particular the
> acpi_address64_attribute value contains (on IA64, I verified with
> ACPI spec working group through actual ACPI tables):
> 
> attr->minimum = PCI IO port min value
> attr->translation_offset = offset to add to attr->minimum to obtain the
>                            CPU physical address at which the PCI IO
> 			   bridge decodes IO space. Translation offset,
> 			   according to the ACPI specification has to
> 			   be used when resources on primary and
> 			   secondary sides of the PCI bridge are
> 			   different (IIUC secondary bus represents PCI
> 			   IO ports, primary bus CPU physical addresses
> 			   mapping IO ports in CPU physical address
> 			   space). This is the physical address that is
> 			   remapped in IA64 new_space(), to map the
> 			   bridge CPU physical address into the virtual
> 			   address space, and it has always been so, even
> 			   before 3772aea7d6f3.
> 
> Now, the resource window, in acpi_decode_space() is created as:
> 
> res->start = attr->minimum + attr->translation_offset;
> res->end = attr->maximum + attr->translation_offset;
> 
> and that's the resource we have in acpi_dev_ioresource_flags(), if we
> are comparing it against ioport_resource that's not correct since as I
> already mentioned, they represent *different* things.
> 
> There is something we can do, which is, checking translation_type
> in acpi_dev_ioresource_flags(), if it is == TypeTranslation (which
> basically means that the IO space is MMIO) the >=10003 can be skipped,
> but that's hackish (also because I am not sure IA64 platforms set
> translation_type consistently in ACPI tables).
> 
> Even if we do that, call to acpi_pci_root_validate_resources() for
> IO space is wrong on IA64, we are comparing an IO resource against
> ioport_resource there, but the Linux IO port space for the host
> bridge is created in IA64 pci_acpi_root_prepare_resources() with
> the call to add_io_space() which happens *after* the sequence above
> is executed.
> 
> On IA64:
> 
> pci_acpi_root_prepare_resources()
>  -> acpi_pci_probe_root_resources()
>     -> acpi_dev_get_resources()
>     -> acpi_pci_root_validate_resources()
>  -> add_io_space() # this is where the Linux IO port space for the bridge is
>                      created and that's when we can validate the IO
> 		     resource against ioport_resource
> 
> I have no experience/knowledge of IA64 systems so I may be totally wrong,
> I just want to understand.
> 
> Comments welcome, Hanjun proved my understanding by testing on IA64 and
> current mainline just does not work (see commit log for failure messages),
> feedback from IA64 people is really needed here, we have to get this fixed
> please (and through that fix, getting it to work on ARM64 too).

I/O port translations makes my head hurt, but I think you're right.

The raw I/O resources from ACPI _CRS are definitely different from the
Linux ioport spaces constructed by add_io_space(), so we shouldn't
compare the two.

If we need to validate the raw I/O ports from _CRS, I suppose in
theory we should be able to check that they're contained in the raw
I/O port range of an upstream window.

I think the problem is that 3772aea7d6f3 started applying the
x86-specific "[0-0xffff]" restriction to all arches, so if you want to 
back that out so it applies only on x86 (but to all devices, not just
PNP0A03), I think that would make sense.

Bjorn

WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Helgaas <helgaas@kernel.org>
To: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	"linux-ia64@vger.kernel.org" <linux-ia64@vger.kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Hanjun Guo <hanjun.guo@linaro.org>,
	Jiang Liu <jiang.liu@linux.intel.com>,
	Tony Luck <tony.luck@intel.com>, Tomasz Nowicki <tn@semihalf.com>,
	Mark Salter <msalter@redhat.com>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>
Subject: Re: [PATCH v2] PCI: ACPI: IA64: fix IO port generic range check
Date: Mon, 14 Mar 2016 19:27:08 +0000	[thread overview]
Message-ID: <20160314192708.GB16621@localhost> (raw)
In-Reply-To: <20160314145322.GE6629@red-moon>

On Mon, Mar 14, 2016 at 02:53:22PM +0000, Lorenzo Pieralisi wrote:
> On Thu, Mar 10, 2016 at 07:42:36AM +0000, Lorenzo Pieralisi wrote:
> 
> [...]
> 
> > > > We can't do that, it may work on IA64 but the ioport_resource is a
> > > > chunk of address space on IA64/ARM64 that has nothing to do with
> > > > the physical address at which the root bridges decode IO space (which
> > > > is what's contained in the resource).
> > > 
> > > I'm stumbling over "the physical address at which the root bridges
> > > decode IO space (which is what's contained in the resource)".
> > > 
> > > x86 host bridges typically just forward CPU-generated I/O port
> > > transactions to PCI with no address translation, so it sounds like
> > > you're talking about ia64/ARM64 bridges that decode CPU MMIO space and
> > > turn accesses into PCI I/O transactions.
> > > 
> > > If we start from a driver calling inb(), the driver supplies a Linux
> > > ioport number "X".  On ia64 (and I assume ARM64 as well), inb()
> > > performs an MMIO access to memory address "Y".  A host bridge consumes
> > > that MMIO access and generates a corresponding PCI I/O transaction to
> > > PCI ioport "Z".
> > > 
> > > It is indeed true that ioport_resource has nothing to do with memory
> > > addresses like "Y".  But the driver (and this part of the ACPI
> > > infrastructure) are dealing with ioport address "X", and that is
> > > definitely in an IORESOURCE_IO struct resource.  The IORESOURCE_MEM_
> > > struct resource that contains "Y" is internal to the host bridge
> > > driver and invisible to the device driver that's using inb().
> > 
> > The problem is, that's the address like "Y" that are checked in
> > acpi_dev_ioresource_flags() with current PCI initialization flow.
> > 
> > IO ports number "X" are created in (IA64) add_io_space() that is
> > executed after acpi_pci_probe_root_resources() is called (see
> > arch/ia64/pci/pci.c), that's the code that, IIUC, translates an
> > IO resource containing a CPU physical address (which is the address
> > that is ioremapped) to an IO resource containing a port number *and*
> > a corresponding MEM resource.
> > 
> > The check that causes failures (>=0x10003) is carried out
> > on the "raw" IO resource parsed from ACPI, not the one crafted
> > in add_io_space().
> > 
> > The resource checked in acpi_dev_ioresource_flags() is created from
> > ACPI IO descriptor and does contain CPU physical MMIO addresses,
> > comparing it to a port number is bound to fail, they do NOT represent
> > the same thing, happy be corrected.
> > 
> > That's the reason why currently IA64 IO space is not working, and
> > this patch fixes it, please correct me if I am wrong.
> > 
> > I will write back next week with the commits sequence and logic that
> > led to the current failure, sorry for not being able to respond
> > more promptly and in a comprehensive way I need sometime to write up
> > my understanding of the problem and commit logs, I will do that
> > next week.
> 
> I had a further look and went through commit history and I think
> my explanation above is correct, current code for IA64 PCI IO space
> is wrong IMO and the failures started with:
> 
> commit 3772aea7d6f3 ("ia64/PCI/ACPI: Use common ACPI resource parsing
> interface for host bridge")
> 
> because that's the commit that added IA64 PCI code to use
> acpi_dev_get_resources(), let me add to that.
> 
> For the records, and for the same reason, let's imagine we can fix the
> (>=0x10003) check in:
> 
> acpi_dev_ioresource_flags()
> 
> the code in acpi_pci_probe_root_resources() that checks the PCI IO
> resources (ie acpi_pci_root_validate_resources()) is wrong, in that it
> validates the PCI IO resources obtained from ACPI IO descriptors against
> ioport_resource, and that's not correct, they do not represent the
> same thing.
> 
> Code in acpi_dev_get_resources() walks the device (PCI host bridge in
> this case) resources (ie _CRS) with acpi_dev_process_resource().
> 
> On IA64 IO space is memory mapped, therefore the CPU physical address
> at which the PCI host bridge maps the IO space has to come from ACPI
> IO descriptors.
> 
> IIUC, those descriptors are parsed through:
> 
> acpi_dev_resource_address_space()
> acpi_dev_resource_ext_address_space()
> 
> which in turn call:
> 
> acpi_decode_space()
> 
> where the resource window is actually created, in particular the
> acpi_address64_attribute value contains (on IA64, I verified with
> ACPI spec working group through actual ACPI tables):
> 
> attr->minimum = PCI IO port min value
> attr->translation_offset = offset to add to attr->minimum to obtain the
>                            CPU physical address at which the PCI IO
> 			   bridge decodes IO space. Translation offset,
> 			   according to the ACPI specification has to
> 			   be used when resources on primary and
> 			   secondary sides of the PCI bridge are
> 			   different (IIUC secondary bus represents PCI
> 			   IO ports, primary bus CPU physical addresses
> 			   mapping IO ports in CPU physical address
> 			   space). This is the physical address that is
> 			   remapped in IA64 new_space(), to map the
> 			   bridge CPU physical address into the virtual
> 			   address space, and it has always been so, even
> 			   before 3772aea7d6f3.
> 
> Now, the resource window, in acpi_decode_space() is created as:
> 
> res->start = attr->minimum + attr->translation_offset;
> res->end = attr->maximum + attr->translation_offset;
> 
> and that's the resource we have in acpi_dev_ioresource_flags(), if we
> are comparing it against ioport_resource that's not correct since as I
> already mentioned, they represent *different* things.
> 
> There is something we can do, which is, checking translation_type
> in acpi_dev_ioresource_flags(), if it is = TypeTranslation (which
> basically means that the IO space is MMIO) the >\x10003 can be skipped,
> but that's hackish (also because I am not sure IA64 platforms set
> translation_type consistently in ACPI tables).
> 
> Even if we do that, call to acpi_pci_root_validate_resources() for
> IO space is wrong on IA64, we are comparing an IO resource against
> ioport_resource there, but the Linux IO port space for the host
> bridge is created in IA64 pci_acpi_root_prepare_resources() with
> the call to add_io_space() which happens *after* the sequence above
> is executed.
> 
> On IA64:
> 
> pci_acpi_root_prepare_resources()
>  -> acpi_pci_probe_root_resources()
>     -> acpi_dev_get_resources()
>     -> acpi_pci_root_validate_resources()
>  -> add_io_space() # this is where the Linux IO port space for the bridge is
>                      created and that's when we can validate the IO
> 		     resource against ioport_resource
> 
> I have no experience/knowledge of IA64 systems so I may be totally wrong,
> I just want to understand.
> 
> Comments welcome, Hanjun proved my understanding by testing on IA64 and
> current mainline just does not work (see commit log for failure messages),
> feedback from IA64 people is really needed here, we have to get this fixed
> please (and through that fix, getting it to work on ARM64 too).

I/O port translations makes my head hurt, but I think you're right.

The raw I/O resources from ACPI _CRS are definitely different from the
Linux ioport spaces constructed by add_io_space(), so we shouldn't
compare the two.

If we need to validate the raw I/O ports from _CRS, I suppose in
theory we should be able to check that they're contained in the raw
I/O port range of an upstream window.

I think the problem is that 3772aea7d6f3 started applying the
x86-specific "[0-0xffff]" restriction to all arches, so if you want to 
back that out so it applies only on x86 (but to all devices, not just
PNP0A03), I think that would make sense.

Bjorn

  reply	other threads:[~2016-03-14 19:27 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-11 17:47 [PATCH v2] PCI: ACPI: IA64: fix IO port generic range check Lorenzo Pieralisi
2016-02-11 17:47 ` Lorenzo Pieralisi
2016-02-14  8:33 ` Hanjun Guo
2016-02-14  8:33   ` Hanjun Guo
2016-03-08 22:21 ` Bjorn Helgaas
2016-03-08 22:21   ` Bjorn Helgaas
2016-03-08 22:27   ` Rafael J. Wysocki
2016-03-08 22:27     ` Rafael J. Wysocki
2016-03-08 23:11     ` Bjorn Helgaas
2016-03-08 23:11       ` Bjorn Helgaas
2016-03-09  5:33     ` Bjorn Helgaas
2016-03-09  5:33       ` Bjorn Helgaas
2016-03-09  7:14       ` Lorenzo Pieralisi
2016-03-09  7:14         ` Lorenzo Pieralisi
2016-03-09 14:20         ` Rafael J. Wysocki
2016-03-09 14:20           ` Rafael J. Wysocki
2016-03-09 15:35         ` Bjorn Helgaas
2016-03-09 15:35           ` Bjorn Helgaas
2016-03-10  7:42           ` Lorenzo Pieralisi
2016-03-14 14:53             ` Lorenzo Pieralisi
2016-03-14 14:53               ` Lorenzo Pieralisi
2016-03-14 19:27               ` Bjorn Helgaas [this message]
2016-03-14 19:27                 ` Bjorn Helgaas
2016-03-15 11:31                 ` Lorenzo Pieralisi
2016-03-15 11:31                   ` Lorenzo Pieralisi

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=20160314192708.GB16621@localhost \
    --to=helgaas@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=hanjun.guo@linaro.org \
    --cc=jiang.liu@linux.intel.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-ia64@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=msalter@redhat.com \
    --cc=rafael@kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=tn@semihalf.com \
    --cc=tony.luck@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.