]> Git Repo - linux.git/commitdiff
x86/mce/amd: Remove shared threshold bank plumbing
authorYazen Ghannam <[email protected]>
Fri, 6 Dec 2024 16:11:54 +0000 (16:11 +0000)
committerBorislav Petkov (AMD) <[email protected]>
Fri, 3 Jan 2025 18:05:35 +0000 (19:05 +0100)
Legacy AMD systems include an integrated Northbridge that is represented
by MCA bank 4. This is the only non-core MCA bank in legacy systems. The
Northbridge is physically shared by all the CPUs within an AMD "Node".

However, in practice the "shared" MCA bank can only by managed by a
single CPU within that AMD Node. This is known as the "Node Base Core"
(NBC). For example, only the NBC will be able to read the MCA bank 4
registers; they will be Read-as-Zero for other CPUs. Also, the MCA
Thresholding interrupt will only signal the NBC; the other CPUs will not
receive it. This is enforced by hardware, and it should not be managed by
software.

The current AMD Thresholding code attempts to deal with the "shared" MCA
bank by micromanaging the bank's sysfs kobjects. However, this does not
follow the intended kobject use cases. It is also fragile, and it has
caused bugs in the past.

Modern AMD systems do not need this shared MCA bank support, and it
should not be needed on legacy systems either.

Remove the shared threshold bank code. Also, move the threshold struct
definitions to mce/amd.c, since they are no longer needed in amd_nb.c.

Signed-off-by: Yazen Ghannam <[email protected]>
Signed-off-by: Borislav Petkov (AMD) <[email protected]>
Reviewed-by: Borislav Petkov (AMD) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
arch/x86/Kconfig
arch/x86/include/asm/amd_nb.h
arch/x86/kernel/cpu/mce/amd.c

index 9d7bd0ae48c4260f4abb6dbedc696e3915c230ea..e4e27d44dc2b4c8f84af67bd02c78f0cf75a009e 100644 (file)
@@ -1189,7 +1189,7 @@ config X86_MCE_INTEL
 config X86_MCE_AMD
        def_bool y
        prompt "AMD MCE features"
-       depends on X86_MCE && X86_LOCAL_APIC && AMD_NB
+       depends on X86_MCE && X86_LOCAL_APIC
        help
          Additional support for AMD specific MCE features such as
          the DRAM Error Threshold.
index d0caac26533f22e78c4776b4921102df5edd423b..4f586fc699fdd1a5ee0046cbdddeec19da1255ee 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/refcount.h>
 
 struct amd_nb_bus_dev_range {
        u8 bus;
@@ -29,41 +28,11 @@ struct amd_l3_cache {
        u8       subcaches[4];
 };
 
-struct threshold_block {
-       unsigned int     block;                 /* Number within bank */
-       unsigned int     bank;                  /* MCA bank the block belongs to */
-       unsigned int     cpu;                   /* CPU which controls MCA bank */
-       u32              address;               /* MSR address for the block */
-       u16              interrupt_enable;      /* Enable/Disable APIC interrupt */
-       bool             interrupt_capable;     /* Bank can generate an interrupt. */
-
-       u16              threshold_limit;       /*
-                                                * Value upon which threshold
-                                                * interrupt is generated.
-                                                */
-
-       struct kobject   kobj;                  /* sysfs object */
-       struct list_head miscj;                 /*
-                                                * List of threshold blocks
-                                                * within a bank.
-                                                */
-};
-
-struct threshold_bank {
-       struct kobject          *kobj;
-       struct threshold_block  *blocks;
-
-       /* initialized to the number of CPUs on the node sharing this bank */
-       refcount_t              cpus;
-       unsigned int            shared;
-};
-
 struct amd_northbridge {
        struct pci_dev *root;
        struct pci_dev *misc;
        struct pci_dev *link;
        struct amd_l3_cache l3_cache;
-       struct threshold_bank *bank4;
 };
 
 struct amd_northbridge_info {
index 018874b554cbfa8c4cac9b9e99e32c701243b17e..1075a90141daedc3d259882678c8cbe0ebb66e04 100644 (file)
@@ -4,8 +4,6 @@
  *
  *  Written by Jacob Shin - AMD, Inc.
  *  Maintained by: Borislav Petkov <[email protected]>
- *
- *  All MC4_MISCi registers are shared between cores on a node.
  */
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
@@ -20,7 +18,6 @@
 #include <linux/smp.h>
 #include <linux/string.h>
 
-#include <asm/amd_nb.h>
 #include <asm/traps.h>
 #include <asm/apic.h>
 #include <asm/mce.h>
@@ -221,6 +218,32 @@ static const struct smca_hwid smca_hwid_mcatypes[] = {
 #define MAX_MCATYPE_NAME_LEN   30
 static char buf_mcatype[MAX_MCATYPE_NAME_LEN];
 
+struct threshold_block {
+       /* This block's number within its bank. */
+       unsigned int            block;
+       /* MCA bank number that contains this block. */
+       unsigned int            bank;
+       /* CPU which controls this block's MCA bank. */
+       unsigned int            cpu;
+       /* MCA_MISC MSR address for this block. */
+       u32                     address;
+       /* Enable/Disable APIC interrupt. */
+       bool                    interrupt_enable;
+       /* Bank can generate an interrupt. */
+       bool                    interrupt_capable;
+       /* Value upon which threshold interrupt is generated. */
+       u16                     threshold_limit;
+       /* sysfs object */
+       struct kobject          kobj;
+       /* List of threshold blocks within this block's MCA bank. */
+       struct list_head        miscj;
+};
+
+struct threshold_bank {
+       struct kobject          *kobj;
+       struct threshold_block  *blocks;
+};
+
 static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
 
 /*
@@ -333,19 +356,6 @@ struct thresh_restart {
        u16                     old_limit;
 };
 
-static inline bool is_shared_bank(int bank)
-{
-       /*
-        * Scalable MCA provides for only one core to have access to the MSRs of
-        * a shared bank.
-        */
-       if (mce_flags.smca)
-               return false;
-
-       /* Bank 4 is for northbridge reporting and is thus shared */
-       return (bank == 4);
-}
-
 static const char *bank4_names(const struct threshold_block *b)
 {
        switch (b->address) {
@@ -1198,35 +1208,10 @@ out_free:
        return err;
 }
 
-static int __threshold_add_blocks(struct threshold_bank *b)
-{
-       struct list_head *head = &b->blocks->miscj;
-       struct threshold_block *pos = NULL;
-       struct threshold_block *tmp = NULL;
-       int err = 0;
-
-       err = kobject_add(&b->blocks->kobj, b->kobj, b->blocks->kobj.name);
-       if (err)
-               return err;
-
-       list_for_each_entry_safe(pos, tmp, head, miscj) {
-
-               err = kobject_add(&pos->kobj, b->kobj, pos->kobj.name);
-               if (err) {
-                       list_for_each_entry_safe_reverse(pos, tmp, head, miscj)
-                               kobject_del(&pos->kobj);
-
-                       return err;
-               }
-       }
-       return err;
-}
-
 static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu,
                                 unsigned int bank)
 {
        struct device *dev = this_cpu_read(mce_device);
-       struct amd_northbridge *nb = NULL;
        struct threshold_bank *b = NULL;
        const char *name = get_name(cpu, bank, NULL);
        int err = 0;
@@ -1234,26 +1219,6 @@ static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu,
        if (!dev)
                return -ENODEV;
 
-       if (is_shared_bank(bank)) {
-               nb = node_to_amd_nb(topology_amd_node_id(cpu));
-
-               /* threshold descriptor already initialized on this node? */
-               if (nb && nb->bank4) {
-                       /* yes, use it */
-                       b = nb->bank4;
-                       err = kobject_add(b->kobj, &dev->kobj, name);
-                       if (err)
-                               goto out;
-
-                       bp[bank] = b;
-                       refcount_inc(&b->cpus);
-
-                       err = __threshold_add_blocks(b);
-
-                       goto out;
-               }
-       }
-
        b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
        if (!b) {
                err = -ENOMEM;
@@ -1267,17 +1232,6 @@ static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu,
                goto out_free;
        }
 
-       if (is_shared_bank(bank)) {
-               b->shared = 1;
-               refcount_set(&b->cpus, 1);
-
-               /* nb is already initialized, see above */
-               if (nb) {
-                       WARN_ON(nb->bank4);
-                       nb->bank4 = b;
-               }
-       }
-
        err = allocate_threshold_blocks(cpu, b, bank, 0, mca_msr_reg(bank, MCA_MISC));
        if (err)
                goto out_kobj;
@@ -1310,40 +1264,11 @@ static void deallocate_threshold_blocks(struct threshold_bank *bank)
        kobject_put(&bank->blocks->kobj);
 }
 
-static void __threshold_remove_blocks(struct threshold_bank *b)
-{
-       struct threshold_block *pos = NULL;
-       struct threshold_block *tmp = NULL;
-
-       kobject_put(b->kobj);
-
-       list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj)
-               kobject_put(b->kobj);
-}
-
 static void threshold_remove_bank(struct threshold_bank *bank)
 {
-       struct amd_northbridge *nb;
-
        if (!bank->blocks)
                goto out_free;
 
-       if (!bank->shared)
-               goto out_dealloc;
-
-       if (!refcount_dec_and_test(&bank->cpus)) {
-               __threshold_remove_blocks(bank);
-               return;
-       } else {
-               /*
-                * The last CPU on this node using the shared bank is going
-                * away, remove that bank now.
-                */
-               nb = node_to_amd_nb(topology_amd_node_id(smp_processor_id()));
-               nb->bank4 = NULL;
-       }
-
-out_dealloc:
        deallocate_threshold_blocks(bank);
 
 out_free:
This page took 0.08131 seconds and 4 git commands to generate.