Re: [PATCH] x86-64: make enabling of MMCFG on AMD Fam10 CPUs actually work

From: Yinghai Lu
Date: Tue Jul 19 2011 - 12:38:25 EST


On Tue, Jul 19, 2011 at 4:43 AM, Jan Beulich <JBeulich@xxxxxxxxxx> wrote:
> Forcibly enabling the MMCFG space on AMD Fam10 CPUs cannot be expected
> to work, since with the firmware not being aware of the address range
> used, it cannot possibly reserve the space in E820 or ACPI resources.
> Hence we need to manually insert the range into the E820 table, and
> enable the range only when the insertion actually works without
> conflict.
>
> Adding the calls to the respective E820 handling functions additionally
> requires to deal with modpost's mismatch checking: The function doing
> those calls needs to be __init, and it is being made sure that it gets
> called (from its __cpuinit caller) only on the BSP, and through a stub
> (silencing the warning).
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
> Cc: Yinghai Lu <yinghai@xxxxxxxxxx>
>
> ---
>  arch/x86/kernel/mmconf-fam10h_64.c |   22 +++++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
>
> --- 3.0-rc7/arch/x86/kernel/mmconf-fam10h_64.c
> +++ 3.0-rc7-x86_64-mmcfg-fam10/arch/x86/kernel/mmconf-fam10h_64.c
> @@ -14,6 +14,7 @@
>  #include <asm/io.h>
>  #include <asm/msr.h>
>  #include <asm/acpi.h>
> +#include <asm/e820.h>
>  #include <asm/mmconfig.h>
>  #include <asm/pci_x86.h>
>
> @@ -49,7 +50,7 @@ static int __cpuinit cmp_range(const voi
>  /* need to avoid (0xfd<<32), (0xfe<<32), and (0xff<<32), ht used space */
>  #define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
>  #define BASE_VALID(b) ((b) + MMCONF_SIZE <= (0xfdULL<<32) || (b) >= (1ULL<<40))
> -static void __cpuinit get_fam10h_pci_mmconf_base(void)
> +static void __init _get_fam10h_pci_mmconf_base(void)
>  {
>        int i;
>        unsigned bus;
> @@ -163,7 +164,21 @@ static void __cpuinit get_fam10h_pci_mmc
>        return;
>
>  out:
> -       fam10h_pci_mmconf_base = base;
> +       if(!e820_any_mapped(base, base + MMCONF_SIZE, 0)) {
> +               e820_add_region(base, MMCONF_SIZE, E820_RESERVED);
> +               update_e820();
> +               fam10h_pci_mmconf_base = base;
> +       }
> +}
> +
> +/*
> + * Section-mismatch warning avoidance: This gets called from a ___cpuinit
> + * function (below), but only on the BSP, and needs to call the __init
> + * functions e820_add_region() and update_e820() (above).
> + */
> +static void __ref get_fam10h_pci_mmconf_base(void)
> +{
> +       _get_fam10h_pci_mmconf_base();
>  }
>
>  void __cpuinit fam10h_check_enable_mmcfg(void)
> @@ -199,7 +214,8 @@ void __cpuinit fam10h_check_enable_mmcfg
>         * if it is not enabled, try to enable it and assume only one segment
>         * with 256 buses
>         */
> -       get_fam10h_pci_mmconf_base();
> +       if (!fam10h_pci_mmconf_base)
> +               get_fam10h_pci_mmconf_base();
>        if (!fam10h_pci_mmconf_base) {
>                pci_probe &= ~PCI_CHECK_ENABLE_AMD_MMCONF;
>                return;
>
>
>

sent out some time ago...please check attached patch.

Maybe you can combine them together.

Thanks

Yinghai
Subject: [PATCH -v2] x86/pci: Add mmconf range into e820 for when it is from MSR with amd faml0h

for AMD Fam10h, it we read mmconf from MSR early, we should just trust it
because we check it and correct it already.

so add it to e820

Also correct the base calulating to make it work below 4g case.

-v2: remove unrelated sort_range changes.
also make FAM10H_MMIO_CONF_BASE_MASK to be ULL pointed by Jan.

Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxxxx>

---
arch/x86/kernel/mmconf-fam10h_64.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

Index: linux-2.6/arch/x86/kernel/mmconf-fam10h_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mmconf-fam10h_64.c
+++ linux-2.6/arch/x86/kernel/mmconf-fam10h_64.c
@@ -16,6 +16,7 @@
#include <asm/acpi.h>
#include <asm/mmconfig.h>
#include <asm/pci_x86.h>
+#include <asm/e820.h>

struct pci_hostbridge_probe {
u32 bus;
@@ -26,6 +27,21 @@ struct pci_hostbridge_probe {

static u64 __cpuinitdata fam10h_pci_mmconf_base;

+/* only on BSP */
+static void __init_refok e820_add_mmconf_range(int busnbits)
+{
+ u64 end;
+
+ end = fam10h_pci_mmconf_base + (1ULL<<(busnbits + 20)) - 1;
+ if (!e820_all_mapped(fam10h_pci_mmconf_base, end+1, E820_RESERVED)) {
+ printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n",
+ fam10h_pci_mmconf_base, end);
+ e820_add_region(fam10h_pci_mmconf_base, 1ULL<<(busnbits + 20),
+ E820_RESERVED);
+ sanitize_e820_map();
+ }
+}
+
static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
{ 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
@@ -164,6 +180,7 @@ static void __cpuinit get_fam10h_pci_mmc

out:
fam10h_pci_mmconf_base = base;
+ e820_add_mmconf_range(8);
}

void __cpuinit fam10h_check_enable_mmcfg(void)
@@ -189,6 +206,7 @@ void __cpuinit fam10h_check_enable_mmcfg

if (!fam10h_pci_mmconf_base) {
fam10h_pci_mmconf_base = base;
+ e820_add_mmconf_range(busnbits);
return;
} else if (fam10h_pci_mmconf_base == base)
return;