FreeBSD/sys/x86/x86/mca.c
/*
 * Update the interrupt threshold for a CMCI.  The strategy is to use
 * a low trigger that interrupts as soon as the first event occurs.
 * However, if a steady stream of events arrive, the threshold is
 * increased until the interrupts are throttled to once every
 * cmc_throttle seconds or the periodic scan.  If a periodic scan
 * finds that the threshold is too high, it is lowered.
 */
Update the interrupt threshold for a CMCI.  The strategy is to use
a low trigger that interrupts as soon as the first event occurs.
However, if a steady stream of events arrive, the threshold is
increased until the interrupts are throttled to once every
cmc_throttle seconds or the periodic scan.  If a periodic scan
finds that the threshold is too high, it is lowered.
Update the interrupt threshold for a CMCI . The strategy is to use a low trigger that interrupts as soon as the first event occurs . However if a steady stream of events arrive the threshold is increased until the interrupts are throttled to once every cmc_throttle seconds or the periodic scan . If a periodic scan finds that the threshold is too high it is lowered .
static void
cmci_update(enum scan_mode mode, int bank, int valid, struct mca_record *rec)
{
	struct cmc_state *cc;
	uint64_t ctl;
	u_int delta;
	int count, limit;
	cc = &cmc_state[PCPU_GET(cpuid)][bank];
	ctl = rdmsr(MSR_MC_CTL2(bank));
	count = (rec->mr_status & MC_STATUS_COR_COUNT) >> 38;
	delta = (u_int)(ticks - cc->last_intr);
	if (mode == CMCI && valid) {
		limit = ctl & MC_CTL2_THRESHOLD;
		if (delta < cmc_throttle && count >= limit &&
		    limit < cc->max_threshold) {
			limit = min(limit << 1, cc->max_threshold);
			ctl &= ~MC_CTL2_THRESHOLD;
			ctl |= limit;
			wrmsr(MSR_MC_CTL2(bank), limit);
		}
		cc->last_intr = ticks;
		return;
	}
	if (mode != POLLED)
		return;
	if (delta < cmc_throttle)
		return;
	if (valid) {
		count = (rec->mr_status & MC_STATUS_COR_COUNT) >> 38;
		limit = count * cmc_throttle / delta;
		if (limit <= 0)
			limit = 1;
		else if (limit > cc->max_threshold)
			limit = cc->max_threshold;
	} else
		limit = 1;
	if ((ctl & MC_CTL2_THRESHOLD) != limit) {
		ctl &= ~MC_CTL2_THRESHOLD;
		ctl |= limit;
		wrmsr(MSR_MC_CTL2(bank), limit);
	}
}
static void cmci_update ( enum scan_mode mode , int bank , int valid , struct mca_record * rec ) { struct cmc_state * cc ; uint64_t ctl ; u_int delta ; int count , limit ; cc = & cmc_state [ PCPU_GET ( cpuid ) ] [ bank ] ; ctl = rdmsr ( MSR_MC_CTL2 ( bank ) ) ; count = ( rec -> mr_status & MC_STATUS_COR_COUNT ) >> 38 ; delta = ( u_int ) ( ticks - cc -> last_intr ) ; if ( mode == CMCI && valid ) { limit = ctl & MC_CTL2_THRESHOLD ; if ( delta < cmc_throttle && count >= limit && limit < cc -> max_threshold ) { limit = min ( limit << 1 , cc -> max_threshold ) ; ctl &= ~ MC_CTL2_THRESHOLD ; ctl |= limit ; wrmsr ( MSR_MC_CTL2 ( bank ) , limit ) ; } cc -> last_intr = ticks ; return ; } if ( mode != POLLED ) return ; if ( delta < cmc_throttle ) return ; if ( valid ) { count = ( rec -> mr_status & MC_STATUS_COR_COUNT ) >> 38 ; limit = count * cmc_throttle / delta ; if ( limit <= 0 ) limit = 1 ; else if ( limit > cc -> max_threshold ) limit = cc -> max_threshold ; } else limit = 1 ; if ( ( ctl & MC_CTL2_THRESHOLD ) != limit ) { ctl &= ~ MC_CTL2_THRESHOLD ; ctl |= limit ; wrmsr ( MSR_MC_CTL2 ( bank ) , limit ) ; } }
Update the interrupt threshold for a CMCI.
Update the interrupt threshold for a CMCI .
/* Fetch the current limit for this bank. */ /*
	 * 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.
	 */ /*
	 * When the banks are polled, check to see if the threshold
	 * should be lowered.
	 */ /* If a CMCI occured recently, do nothing for now. */ /*
	 * Compute a new limit based on the average rate of events per
	 * cmc_throttle seconds since the last interrupt.
	 */