Index: FreeBSD/sys/x86/x86/mca.c =================================================================== --- FreeBSD/sys/x86/x86/mca.c +++ FreeBSD/sys/x86/x86/mca.c @@ -127,6 +127,7 @@ static struct cmc_state **cmc_state; /* Indexed by cpuid, bank. */ static struct amd_et_state *amd_et_state; /* Indexed by cpuid. */ static int cmc_throttle = 60; /* Time in seconds to throttle CMCI. */ +static int cmc_backoff = 1; /* Throttling exponential backoff factor. */ static int amd_elvt = -1; @@ -579,12 +580,16 @@ * If an interrupt was received less than cmc_throttle seconds * since the previous interrupt and the count from the current * event is greater than or equal to the current threshold, - * double the threshold up to the max. + * exponentially increase the threshold up to the max. */ if (mode == CMCI && valid) { if (delta < cmc_throttle && count >= limit && limit < max_threshold) { - limit = min(limit << 1, max_threshold); + limit <<= cmc_backoff; + if (limit < cur_threshold) + limit = max_threshold; + else + limit = min(limit, max_threshold); } return (limit); } @@ -835,6 +840,10 @@ "cmc_throttle", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &cmc_throttle, 0, sysctl_positive_int, "I", "Interval in seconds to throttle corrected MC interrupts"); + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, + "cmc_backoff", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + &cmc_backoff, 0, sysctl_positive_int, "I", + "Backoff factor while throttling (2 ** value)"); } static void @@ -847,6 +856,10 @@ "cmc_throttle", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &cmc_throttle, 0, sysctl_positive_int, "I", "Interval in seconds to throttle corrected MC interrupts"); + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, + "cmc_backoff", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + &cmc_backoff, 0, sysctl_positive_int, "I", + "Backoff factor while throttling (2 ** value)"); } #endif