Here's another stab at this writeup. I'd appreciate any comments!
Changes from v1 to v2:
- Consumer/Producer is defined for Extended Address Space descriptors;
should be ignored for QWord/DWord/Word Address Space descriptors
- New arches may use Extended Address Space descriptors in PNP0A03 for
bridge registers, including ECAM (if the arch adds support for this)
- Add more details about MCFG and _CBA (Lv's suggestion)
- Incorporate Rafael's suggestions
---
Bjorn Helgaas (1):
PCI: Add information about describing PCI in ACPI
Documentation/PCI/00-INDEX | 2
Documentation/PCI/acpi-info.txt | 180 +++++++++++++++++++++++++++++++++++++++
2 files changed, 182 insertions(+)
create mode 100644 Documentation/PCI/acpi-info.txt
These patches were part of https://lkml.org/lkml/2016/9/9/666 series,
however, only core part (first two patches) was approved. ThunderX quirk
example had some comments which are address in this series (resetting version
numbering).
Add ACPI PCI host controler support for ThunderX SoCs pass1.x & pass2.x using
ACPI quirk mechanism [1]. Patches rework ThunderX ECAM and PEM driver to work
with ACPI & DT boot method.
Patch set can be found here:
git@github.com:semihalf-nowicki-tomasz/linux.git (pci-quirks-thunderx-v1)
It is based on branch pci/ecam-v6 which can be found here:
[1] https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git (pci/ecam-v6)
Tomasz Nowicki (2):
PCI: thunder: Enable ACPI PCI controller for ThunderX pass2.x silicon
version
PCI: thunder: Enable ACPI PCI controller for ThunderX pass1.x silicon
version
drivers/acpi/pci_mcfg.c | 35 ++++++++++++
drivers/pci/host/pci-thunder-ecam.c | 2 +-
drivers/pci/host/pci-thunder-pem.c | 107 +++++++++++++++++++++++++++++++-----
include/linux/pci-ecam.h | 7 +++
4 files changed, 136 insertions(+), 15 deletions(-)
--
2.7.4
Hi ,
On 25 November 2016 at 22:32, kbuild test robot <lkp(a)intel.com> wrote:
> Hi Fu,
>
> [auto build test ERROR on pm/linux-next]
> [also build test ERROR on v4.9-rc6]
> [cannot apply to tip/timers/core next-20161125]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/fu-wei-linaro-org/acpi-clocksource…
> base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
> config: arm64-defconfig (attached as .config)
> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
> reproduce:
> wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/m… -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=arm64
>
> Note: the linux-review/fu-wei-linaro-org/acpi-clocksource-add-GTDT-driver-and-GTDT-support-in-arm_arch_timer/20161125-171111 HEAD 498f1f2503da21841b0e7679ddbdb86a40451bdb builds fine.
> It only hurts bisectibility.
>
> All errors (new ones prefixed by >>):
>
> drivers/clocksource/arm_arch_timer.c: In function 'arch_timer_acpi_init':
Sorry, again,
a "+ int ret;" should be move from [12/15] to here, I have fix the
problem in my repo, it would happen in next patchset
https://git.linaro.org/people/fu.wei/linux.git/log/?h=topic-gtdt-wakeup-tim…
>>> drivers/clocksource/arm_arch_timer.c:1071:2: error: 'ret' undeclared (first use in this function)
> ret = arch_timer_register();
> ^~~
> drivers/clocksource/arm_arch_timer.c:1071:2: note: each undeclared identifier is reported only once for each function it appears in
>
> vim +/ret +1071 drivers/clocksource/arm_arch_timer.c
>
> 1065 return -EINVAL;
> 1066 }
> 1067
> 1068 /* Always-on capability */
> 1069 arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
> 1070
>> 1071 ret = arch_timer_register();
> 1072 if (ret)
> 1073 return ret;
> 1074
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
--
Best regards,
Fu Wei
Software Engineer
Red Hat
Hi all,
We've been working through the details of getting ACPI to work on
arm64, and there have been lots of questions about what this means for
PCI. I've outlined this for several people individually, but I'm
going to send this separately, apart from a specific patch series, to
make sure we're all on the same page. Please correct my errors and
misunderstandings.
Bjorn
The basic requirement is that the ACPI namespace should describe
*everything* that consumes address space unless there's another
standard way for the OS to find it [1, 2]. For example, windows that
are forwarded to PCI by a PCI host bridge should be described via ACPI
devices, since the OS can't locate the host bridge by itself. PCI
devices *below* the host bridge do not need to be described via ACPI,
because the resources they consume are inside the host bridge windows,
and the OS can discover them via the standard PCI enumeration
mechanism (using config accesses to read and size the BARs).
This ACPI resource description is done via _CRS methods of devices in
the ACPI namespace [2]. _CRS methods are like generalized PCI BARs:
the OS can read _CRS and figure out what resource is being consumed
even if it doesn't have a driver for the device [3]. That's important
because it means an old OS can work correctly even on a system with
new devices unknown to the OS. The new devices won't do anything, but
the OS can at least make sure no resources conflict with them.
Static tables like MCFG, HPET, ECDT, etc., are *not* mechanisms for
reserving address space! The static tables are for things the OS
needs to know early in boot, before it can parse the ACPI namespace.
If a new table is defined, an old OS needs to operate correctly even
though it ignores the table. _CRS allows that because it is generic
and understood by the old OS; a static table does not.
If the OS is expected to manage an ACPI device, that device will have
a specific _HID/_CID that tells the OS what driver to bind to it, and
the _CRS tells the OS and the driver where the device's registers are.
PNP0C02 "motherboard" devices are basically a catch-all. There's no
programming model for them other than "don't use these resources for
anything else." So any address space that is (1) not claimed by some
other ACPI device and (2) should not be assigned by the OS to
something else, should be claimed by a PNP0C02 _CRS method.
PCI host bridges are PNP0A03 or PNP0A08 devices. Their _CRS should
describe all the address space they consume. In principle, this would
be all the windows they forward down to the PCI bus, as well as the
bridge registers themselves. The bridge registers include things like
secondary/subordinate bus registers that determine the bus range below
the bridge, window registers that describe the apertures, etc. These
are all device-specific, non-architected things, so the only way a
PNP0A03/PNP0A08 driver can manage them is via _PRS/_CRS/_SRS, which
contain the device-specific details. These bridge registers also
include ECAM space, since it is consumed by the bridge.
ACPI defined a Producer/Consumer bit that was intended to distinguish
the bridge apertures from the bridge registers [4, 5]. However,
BIOSes didn't use that bit correctly, and the result is that OSes have
to assume that everything in a PCI host bridge _CRS is a window. That
leaves no way to describe the bridge registers in the PNP0A03/PNP0A08
device itself.
The workaround is to describe the bridge registers (including ECAM
space) in PNP0C02 catch-all devices [6]. With the exception of ECAM,
the bridge register space is device-specific anyway, so the generic
PNP0A03/PNP0A08 driver (pci_root.c) has no need to know about it. For
ECAM, pci_root.c learns about the space from either MCFG or the _CBA
method.
Note that the PCIe spec actually does require ECAM unless there's a
standard firmware interface for config access, e.g., the ia64 SAL
interface [7]. One reason is that we want a generic host bridge
driver (pci_root.c), and a generic driver requires a generic way to
access config space.
[1] ACPI 6.0, sec 6.1:
For any device that is on a non-enumerable type of bus (for
example, an ISA bus), OSPM enumerates the devices' identifier(s)
and the ACPI system firmware must supply an _HID object ... for
each device to enable OSPM to do that.
[2] ACPI 6.0, sec 3.7:
The OS enumerates motherboard devices simply by reading through
the ACPI Namespace looking for devices with hardware IDs.
Each device enumerated by ACPI includes ACPI-defined objects in
the ACPI Namespace that report the hardware resources the device
could occupy [_PRS], an object that reports the resources that are
currently used by the device [_CRS], and objects for configuring
those resources [_SRS]. The information is used by the Plug and
Play OS (OSPM) to configure the devices.
[3] ACPI 6.0, sec 6.2:
OSPM uses device configuration objects to configure hardware
resources for devices enumerated via ACPI. Device configuration
objects provide information about current and possible resource
requirements, the relationship between shared resources, and
methods for configuring hardware resources.
When OSPM enumerates a device, it calls _PRS to determine the
resource requirements of the device. It may also call _CRS to
find the current resource settings for the device. Using this
information, the Plug and Play system determines what resources
the device should consume and sets those resources by calling the
device’s _SRS control method.
In ACPI, devices can consume resources (for example, legacy
keyboards), provide resources (for example, a proprietary PCI
bridge), or do both. Unless otherwise specified, resources for a
device are assumed to be taken from the nearest matching resource
above the device in the device hierarchy.
[4] ACPI 6.0, sec 6.4.3.5.4:
Extended Address Space Descriptor
General Flags: Bit [0] Consumer/Producer:
1–This device consumes this resource
0–This device produces and consumes this resource
[5] ACPI 6.0, sec 19.6.43:
ResourceUsage specifies whether the Memory range is consumed by
this device (ResourceConsumer) or passed on to child devices
(ResourceProducer). If nothing is specified, then
ResourceConsumer is assumed.
[6] PCI Firmware 3.0, sec 4.1.2:
If the operating system does not natively comprehend reserving the
MMCFG region, the MMCFG region must be reserved by firmware. The
address range reported in the MCFG table or by _CBA method (see
Section 4.1.3) must be reserved by declaring a motherboard
resource. For most systems, the motherboard resource would appear
at the root of the ACPI namespace (under \_SB) in a node with a
_HID of EISAID (PNP0C02), and the resources in this case should
not be claimed in the root PCI bus’s _CRS. The resources can
optionally be returned in Int15 E820 or EFIGetMemoryMap as
reserved memory but must always be reported through ACPI as a
motherboard resource.
[7] PCI Express 3.0, sec 7.2.2:
For systems that are PC-compatible, or that do not implement a
processor-architecture-specific firmware interface standard that
allows access to the Configuration Space, the ECAM is required as
defined in this section.
Quirk handling relies on an idea of simple static array which contains
quirk enties. Each entry consists of identification information (IDs from
standard header of MCFG table) along with custom pci_ecam_ops structure and
configuration space resource structure. This way it is possible find
corresponding quirk entries and override pci_ecam_ops and PCI configuration
space regions.
As an example, the last 3 patches present quirk handling mechanism usage for
ThunderX.
v5 -> v6
- rebase against v4.8-rc5
- drop patch 1 form previous series
- keep pci_acpi_setup_ecam_mapping() in ARM64 arch directory
- move quirk code to pci_mcfg.c
- restrict quirk to override pci_ecam_ops and CFG resource structure
only, no init call any more
- split ThunderX quirks into the smaller chunks
- add ThunderX pass1.x silicon revision support
v4 -> v5
- rebase against v4.8-rc1
- rework to exact MCFG OEM ID, TABLE ID, rev match
- use memcmp instead of strncmp
- no substring match
- fix typos and dmesg message
Tomasz Nowicki (5):
PCI/ACPI: Extend pci_mcfg_lookup() responsibilities
PCI/ACPI: Check platform specific ECAM quirks
PCI: thunder-pem: Allow to probe PEM-specific register range for ACPI
case
PCI: thunder: Enable ACPI PCI controller for ThunderX pass2.x silicon
version
PCI: thunder: Enable ACPI PCI controller for ThunderX pass1.x silicon
version
arch/arm64/kernel/pci.c | 17 ++--
drivers/acpi/pci_mcfg.c | 168 +++++++++++++++++++++++++++++++++++-
drivers/pci/host/pci-thunder-ecam.c | 2 +-
drivers/pci/host/pci-thunder-pem.c | 63 +++++++++++---
include/linux/pci-acpi.h | 4 +-
include/linux/pci-ecam.h | 7 ++
6 files changed, 230 insertions(+), 31 deletions(-)
--
1.9.1
From: Tomasz Nowicki <tomasz.nowicki(a)linaro.org>
This patch provides APEI arch-specific bits for aarch64
Meanwhile,
(1)move HEST type (ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) checking to
a generic place.
(2)select HAVE_ACPI_APEI when EFI and ACPI is set on ARM64,
because arch_apei_get_mem_attribute is using efi_mem_attributes on ARM64.
[Fu Wei: improve && upstream]
Signed-off-by: Tomasz Nowicki <tomasz.nowicki(a)linaro.org>
Tested-by: Jonathan (Zhixiong) Zhang <zjzhang(a)codeaurora.org>
Signed-off-by: Fu Wei <fu.wei(a)linaro.org>
Acked-by: Hanjun Guo <hanjun.guo(a)linaro.org>
Tested-by: Tyler Baicar <tbaicar(a)codeaurora.org>
Acked-by: Will Deacon <will.deacon(a)arm.com>
---
This patchset has been tested on the following platforms:
(1)ARM Foundation v8 model
Changelog:
v14:https://lkml.org/lkml/2016/8/10/
Delete hest_ia32_init().
Fix a comment typo for acpi_disable_cmcff.
Rebase to 4.8.0-rc1-ge6c4d92
v13:https://lkml.org/lkml/2016/8/10/
Fix a comment problem(add a "end").
Add a comment for the definition of acpi_disable_cmcff.
Rebase to 4.8.0-rc1-g372734a
v12:https://lkml.org/lkml/2016/7/29/97
Fix a comment problem(redundant "with").
Rebase to 4.7.0-g680eee2.
v11:https://lkml.org/lkml/2016/7/27/427
Rebase to v4.7-0e06f5c0.
v10:https://lkml.org/lkml/2016/4/14
Fix the Alphabetical order problem in arch/arm64/Kconfig.
v9: https://lkml.org/lkml/2016/4/5/522
Improve the comment for arch_apei_flush_tlb_one.
Using select "HAVE_ACPI_APEI if (ACPI && EFI)" to fix the EFI dependence
problem.
v8: https://lkml.org/lkml/2016/3/29/132
Fix a "undefined reference" bug by selecting EFI when ACPI_APEI is set
on ARM64.
v7: https://lkml.org/lkml/2016/3/17/183
Add comment for arch_apei_flush_tlb_one in arch/arm64/include/asm/acpi.h.
v6: https://lists.linaro.org/pipermail/linaro-acpi/2016-March/006644.html
Move HEST type (ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) checking to
a generic place.
Delete HAVE_ACPI_APEI_HEST_IA32.
v5: https://lkml.org/lkml/2015/12/10/131
Add "HAVE_ACPI_APEI_HEST_IA32" instead of
"#if defined(__i386__) || defined(__x86_64__)".
v4: https://lkml.org/lkml/2015/12/8/188
Rebase to latest kernel version(4.4-rc4).
Move arch_apei_flush_tlb_one into header file as a inline function
Add a new subfunction "hest_ia_init" for "acpi_disable_cmcff".
v3: https://lkml.org/lkml/2015/12/3/521
Remove "acpi_disable_cmcff" from arm64 code,
and wrap it in hest.c by "#if defined(__i386__) || defined(__x86_64__)"
v2: https://lkml.org/lkml/2015/12/2/432
Rebase to latest kernel version(4.4-rc3).
Move arch_apei_flush_tlb_one() to arch/arm64/kernel/acpi.c
v1: https://lkml.org/lkml/2015/8/14/199
Move arch_apei_flush_tlb_one() to arch/arm64/include/asm/apci.h.
Delete arch/arm64/kernel/apei.c.
Add "#ifdef CONFIG_ACPI_APEI" for "acpi_disable_cmcff".
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/acpi.h | 22 +++++++++++++++++++++-
arch/x86/kernel/acpi/apei.c | 3 ---
drivers/acpi/apei/hest.c | 13 ++++++++++---
4 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index bc3f00f..385cf13 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -51,6 +51,7 @@ config ARM64
select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
+ select HAVE_ACPI_APEI if (ACPI && EFI)
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 5420cb0..f435967 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -17,6 +17,7 @@
#include <asm/cputype.h>
#include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
/* Macros for consistency checks of the GICC subtable of MADT */
#define ACPI_MADT_GICC_LENGTH \
@@ -110,8 +111,27 @@ static inline const char *acpi_get_enable_method(int cpu)
}
#ifdef CONFIG_ACPI_APEI
+/*
+ * acpi_disable_cmcff is used in drivers/acpi/apei/hest.c for disabling
+ * IA-32 Architecture Corrected Machine Check (CMC) Firmware-First mode by
+ * boot parameter(acpi=nocmcff). But we don't have this IA-32 specific
+ * feature on ARM64, this definition is only for compatibility.
+ */
+#define acpi_disable_cmcff 1
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
-#endif
+
+/*
+ * Despite its name, this function must still broadcast the TLB
+ * invalidation in order to ensure other CPUs don't end up with junk
+ * entries as a result of speculation. Unusually, its also called in
+ * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for
+ * TLB broadcasting, then we're in trouble here.
+ */
+static inline void arch_apei_flush_tlb_one(unsigned long addr)
+{
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+}
+#endif /* CONFIG_ACPI_APEI */
#ifdef CONFIG_ACPI_NUMA
int arm64_acpi_numa_init(void);
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
index c280df6..ea3046e 100644
--- a/arch/x86/kernel/acpi/apei.c
+++ b/arch/x86/kernel/acpi/apei.c
@@ -24,9 +24,6 @@ int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data)
struct acpi_hest_ia_corrected *cmc;
struct acpi_hest_ia_error_bank *mc_bank;
- if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
- return 0;
-
cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
if (!cmc->enabled)
return 0;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 20b3fcf..8f2a98e 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -123,7 +123,13 @@ EXPORT_SYMBOL_GPL(apei_hest_parse);
*/
static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
{
- return arch_apei_enable_cmcff(hest_hdr, data);
+ if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
+ return 0;
+
+ if (!acpi_disable_cmcff)
+ return !arch_apei_enable_cmcff(hest_hdr, data);
+
+ return 0;
}
struct ghes_arr {
@@ -232,8 +238,9 @@ void __init acpi_hest_init(void)
goto err;
}
- if (!acpi_disable_cmcff)
- apei_hest_parse(hest_parse_cmc, NULL);
+ rc = apei_hest_parse(hest_parse_cmc, NULL);
+ if (rc)
+ goto err;
if (!ghes_disable) {
rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
--
2.5.5
Per spec, the Consumer/Producer bit is defined only for Extended
Address Space descriptors and should be ignored for QWord/DWord/Word
Address Space descriptors. My understanding is that this is because
x86 BIOSes didn't use the bit consistently, so it couldn't be relied
upon. The Extended descriptors were added later and are presumably
more reliable.
Linux currently looks at Consumer/Producer for all Address Space
descriptors, although we don't use the result very much. The x86 and
ia64 host bridge driver code doesn't use Consumer/Producer to identify
windows; it assumes all descriptors are windows.
We do currently use Consumer/Producer to decide whether to apply _TRA.
The change in these patches is to ignore Consumer/Producer for
QWord/DWord/Word, so we'll apply _TRA from Consumer descriptors where
we didn't before. Per spec, that should be safe because _TRA is
required to be zero for Consumer resources.
If we want to describe host bridge register space and ECAM space
directly in the PNP0A03 device on ARM64 (and I guess potentially even
on x86 & ia64), I think we need changes like this so the arch code can
use IORESOURCE_WINDOW to tell which descriptors are windows and which
are registers.
This is a subtle area, so please take a look and let me know what you
think.
These patches are based on v4.9-rc1. It's getting pretty late in the
cycle, but I think we'd really like to get the ARM64 ACPI PCI story
sorted out for the v4.10 merge window.
---
Bjorn Helgaas (2):
ACPI: Combine acpi_dev_resource_address_space() and acpi_dev_resource_ext_address_space()
ACPI: Ignore Consumer/Producer for QWord/DWord/Word Address Space
drivers/acpi/ioapic.c | 3 -
drivers/acpi/resource.c | 130 ++++++++++++++++++----------------------
drivers/pnp/pnpacpi/rsparser.c | 3 -
include/linux/acpi.h | 2 -
4 files changed, 59 insertions(+), 79 deletions(-)
Add a writeup about how PCI host bridges should be described in ACPI
using PNP0A03/PNP0A08 devices, PNP0C02 devices, and the MCFG table.
Signed-off-by: Bjorn Helgaas <bhelgaas(a)google.com>
---
Documentation/PCI/00-INDEX | 2 +
Documentation/PCI/acpi-info.txt | 136 +++++++++++++++++++++++++++++++++++++++
2 files changed, 138 insertions(+)
create mode 100644 Documentation/PCI/acpi-info.txt
diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index 147231f..0780280 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- this file
+acpi-info.txt
+ - info on how PCI host bridges are represented in ACPI
MSI-HOWTO.txt
- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
PCIEBUS-HOWTO.txt
diff --git a/Documentation/PCI/acpi-info.txt b/Documentation/PCI/acpi-info.txt
new file mode 100644
index 0000000..ccbcfda
--- /dev/null
+++ b/Documentation/PCI/acpi-info.txt
@@ -0,0 +1,136 @@
+ ACPI considerations for PCI host bridges
+
+The basic requirement is that the ACPI namespace should describe
+*everything* that consumes address space unless there's another
+standard way for the OS to find it [1, 2]. For example, windows that
+are forwarded to PCI by a PCI host bridge should be described via ACPI
+devices, since the OS can't locate the host bridge by itself. PCI
+devices *below* the host bridge do not need to be described via ACPI,
+because the resources they consume are inside the host bridge windows,
+and the OS can discover them via the standard PCI enumeration
+mechanism (using config accesses to read and size the BARs).
+
+This ACPI resource description is done via _CRS methods of devices in
+the ACPI namespace [2]. _CRS methods are like generalized PCI BARs:
+the OS can read _CRS and figure out what resource is being consumed
+even if it doesn't have a driver for the device [3]. That's important
+because it means an old OS can work correctly even on a system with
+new devices unknown to the OS. The new devices won't do anything, but
+the OS can at least make sure no resources conflict with them.
+
+Static tables like MCFG, HPET, ECDT, etc., are *not* mechanisms for
+reserving address space! The static tables are for things the OS
+needs to know early in boot, before it can parse the ACPI namespace.
+If a new table is defined, an old OS needs to operate correctly even
+though it ignores the table. _CRS allows that because it is generic
+and understood by the old OS; a static table does not.
+
+If the OS is expected to manage an ACPI device, that device will have
+a specific _HID/_CID that tells the OS what driver to bind to it, and
+the _CRS tells the OS and the driver where the device's registers are.
+
+PNP0C02 "motherboard" devices are basically a catch-all. There's no
+programming model for them other than "don't use these resources for
+anything else." So any address space that is (1) not claimed by some
+other ACPI device and (2) should not be assigned by the OS to
+something else, should be claimed by a PNP0C02 _CRS method.
+
+PCI host bridges are PNP0A03 or PNP0A08 devices. Their _CRS should
+describe all the address space they consume. In principle, this would
+be all the windows they forward down to the PCI bus, as well as the
+bridge registers themselves. The bridge registers include things like
+secondary/subordinate bus registers that determine the bus range below
+the bridge, window registers that describe the apertures, etc. These
+are all device-specific, non-architected things, so the only way a
+PNP0A03/PNP0A08 driver can manage them is via _PRS/_CRS/_SRS, which
+contain the device-specific details. These bridge registers also
+include ECAM space, since it is consumed by the bridge.
+
+ACPI defined a Producer/Consumer bit that was intended to distinguish
+the bridge apertures from the bridge registers [4, 5]. However,
+BIOSes didn't use that bit correctly, and the result is that OSes have
+to assume that everything in a PCI host bridge _CRS is a window. That
+leaves no way to describe the bridge registers in the PNP0A03/PNP0A08
+device itself.
+
+The workaround is to describe the bridge registers (including ECAM
+space) in PNP0C02 catch-all devices [6]. With the exception of ECAM,
+the bridge register space is device-specific anyway, so the generic
+PNP0A03/PNP0A08 driver (pci_root.c) has no need to know about it. For
+ECAM, pci_root.c learns about the space from either MCFG or the _CBA
+method.
+
+Note that the PCIe spec actually does require ECAM unless there's a
+standard firmware interface for config access, e.g., the ia64 SAL
+interface [7]. One reason is that we want a generic host bridge
+driver (pci_root.c), and a generic driver requires a generic way to
+access config space.
+
+
+[1] ACPI 6.0, sec 6.1:
+ For any device that is on a non-enumerable type of bus (for
+ example, an ISA bus), OSPM enumerates the devices' identifier(s)
+ and the ACPI system firmware must supply an _HID object ... for
+ each device to enable OSPM to do that.
+
+[2] ACPI 6.0, sec 3.7:
+ The OS enumerates motherboard devices simply by reading through
+ the ACPI Namespace looking for devices with hardware IDs.
+
+ Each device enumerated by ACPI includes ACPI-defined objects in
+ the ACPI Namespace that report the hardware resources the device
+ could occupy [_PRS], an object that reports the resources that are
+ currently used by the device [_CRS], and objects for configuring
+ those resources [_SRS]. The information is used by the Plug and
+ Play OS (OSPM) to configure the devices.
+
+[3] ACPI 6.0, sec 6.2:
+ OSPM uses device configuration objects to configure hardware
+ resources for devices enumerated via ACPI. Device configuration
+ objects provide information about current and possible resource
+ requirements, the relationship between shared resources, and
+ methods for configuring hardware resources.
+
+ When OSPM enumerates a device, it calls _PRS to determine the
+ resource requirements of the device. It may also call _CRS to
+ find the current resource settings for the device. Using this
+ information, the Plug and Play system determines what resources
+ the device should consume and sets those resources by calling the
+ device’s _SRS control method.
+
+ In ACPI, devices can consume resources (for example, legacy
+ keyboards), provide resources (for example, a proprietary PCI
+ bridge), or do both. Unless otherwise specified, resources for a
+ device are assumed to be taken from the nearest matching resource
+ above the device in the device hierarchy.
+
+[4] ACPI 6.0, sec 6.4.3.5.4:
+ Extended Address Space Descriptor
+ General Flags: Bit [0] Consumer/Producer:
+ 1–This device consumes this resource
+ 0–This device produces and consumes this resource
+
+[5] ACPI 6.0, sec 19.6.43:
+ ResourceUsage specifies whether the Memory range is consumed by
+ this device (ResourceConsumer) or passed on to child devices
+ (ResourceProducer). If nothing is specified, then
+ ResourceConsumer is assumed.
+
+[6] PCI Firmware 3.0, sec 4.1.2:
+ If the operating system does not natively comprehend reserving the
+ MMCFG region, the MMCFG region must be reserved by firmware. The
+ address range reported in the MCFG table or by _CBA method (see
+ Section 4.1.3) must be reserved by declaring a motherboard
+ resource. For most systems, the motherboard resource would appear
+ at the root of the ACPI namespace (under \_SB) in a node with a
+ _HID of EISAID (PNP0C02), and the resources in this case should
+ not be claimed in the root PCI bus’s _CRS. The resources can
+ optionally be returned in Int15 E820 or EFIGetMemoryMap as
+ reserved memory but must always be reported through ACPI as a
+ motherboard resource.
+
+[7] PCI Express 3.0, sec 7.2.2:
+ For systems that are PC-compatible, or that do not implement a
+ processor-architecture-specific firmware interface standard that
+ allows access to the Configuration Space, the ECAM is required as
+ defined in this section.