git: 996a832d2e01 - main - mca: Allow for passing ECC error record to memory controller driver
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 18 Sep 2024 14:37:24 UTC
The branch main has been updated by stevek: URL: https://cgit.FreeBSD.org/src/commit/?id=996a832d2e01fceb5a3bbfd33df585bd778e6288 commit 996a832d2e01fceb5a3bbfd33df585bd778e6288 Author: Stephen J. Kiernan <stevek@FreeBSD.org> AuthorDate: 2024-09-18 14:37:14 +0000 Commit: Stephen J. Kiernan <stevek@FreeBSD.org> CommitDate: 2024-09-18 14:37:14 +0000 mca: Allow for passing ECC error record to memory controller driver Added (de)registration functions for memory controller driver to be notified when ECC errors occur. This allows for decoding of the specific error by the driver. Submitted by: Lakshman Likith Nudurupati <lnlakshman@juniper.net> Sponsored by: Juniper Networks, Inc. Obtained from: Semihalf --- sys/x86/include/mca.h | 5 +++++ sys/x86/x86/mca.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/sys/x86/include/mca.h b/sys/x86/include/mca.h index 183480625f6d..d8b8da86523d 100644 --- a/sys/x86/include/mca.h +++ b/sys/x86/include/mca.h @@ -46,6 +46,11 @@ struct mca_record { #ifdef _KERNEL +typedef void (*mca_decode_func)(void *, const struct mca_record *); + +int mca_register_decode_func(mca_decode_func func, void *aux); +int mca_deregister_decode_func(mca_decode_func func); + void cmc_intr(void); void mca_init(void); void mca_intr(void); diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index b293fcedbd84..89ab59639882 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -99,6 +99,8 @@ static MALLOC_DEFINE(M_MCA, "MCA", "Machine Check Architecture"); static volatile int mca_count; /* Number of records stored. */ static int mca_banks; /* Number of per-CPU register banks. */ static int mca_maxcount = -1; /* Limit on records stored. (-1 = unlimited) */ +static mca_decode_func mca_func; +static void *mca_decode_arg; static SYSCTL_NODE(_hw, OID_AUTO, mca, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Machine Check Architecture"); @@ -421,6 +423,50 @@ mca_mute(const struct mca_record *rec) return (0); } +/* + * Pass mca_record to a memory controller driver so that it can decode + * the address and possibly do some more work. + */ +static void +mca_decode_record(const struct mca_record *rec) +{ + + if (mca_func != NULL) + mca_func(mca_decode_arg, rec); +} + +int +mca_register_decode_func(mca_decode_func func, void *aux) +{ + int error; + + if (func == NULL) + return (EINVAL); + + error = 0; + mtx_lock_spin(&mca_lock); + if (mca_func != NULL) + error = EEXIST; + + if (error == 0) { + mca_func = func; + mca_decode_arg = aux; + } + + mtx_unlock_spin(&mca_lock); + return (error); +} + +int +mca_deregister_decode_func(mca_decode_func func) +{ + if (func == NULL || func != mca_func) + return (EINVAL); + + mca_func = NULL; + return (0); +} + /* Dump details about a single machine check. */ static void mca_log(const struct mca_record *rec) @@ -613,6 +659,8 @@ mca_log(const struct mca_record *rec) } if (rec->mr_status & MC_STATUS_MISCV) printf("MCA: Misc 0x%llx\n", (long long)rec->mr_misc); + + mca_decode_record(rec); } static bool