cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rdma_dim.c (2627B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/*
      3 * Copyright (c) 2019, Mellanox Technologies inc.  All rights reserved.
      4 */
      5
      6#include <linux/dim.h>
      7
      8static int rdma_dim_step(struct dim *dim)
      9{
     10	if (dim->tune_state == DIM_GOING_RIGHT) {
     11		if (dim->profile_ix == (RDMA_DIM_PARAMS_NUM_PROFILES - 1))
     12			return DIM_ON_EDGE;
     13		dim->profile_ix++;
     14		dim->steps_right++;
     15	}
     16	if (dim->tune_state == DIM_GOING_LEFT) {
     17		if (dim->profile_ix == 0)
     18			return DIM_ON_EDGE;
     19		dim->profile_ix--;
     20		dim->steps_left++;
     21	}
     22
     23	return DIM_STEPPED;
     24}
     25
     26static int rdma_dim_stats_compare(struct dim_stats *curr,
     27				  struct dim_stats *prev)
     28{
     29	/* first stat */
     30	if (!prev->cpms)
     31		return DIM_STATS_SAME;
     32
     33	if (IS_SIGNIFICANT_DIFF(curr->cpms, prev->cpms))
     34		return (curr->cpms > prev->cpms) ? DIM_STATS_BETTER :
     35						DIM_STATS_WORSE;
     36
     37	if (IS_SIGNIFICANT_DIFF(curr->cpe_ratio, prev->cpe_ratio))
     38		return (curr->cpe_ratio > prev->cpe_ratio) ? DIM_STATS_BETTER :
     39						DIM_STATS_WORSE;
     40
     41	return DIM_STATS_SAME;
     42}
     43
     44static bool rdma_dim_decision(struct dim_stats *curr_stats, struct dim *dim)
     45{
     46	int prev_ix = dim->profile_ix;
     47	u8 state = dim->tune_state;
     48	int stats_res;
     49	int step_res;
     50
     51	if (state != DIM_PARKING_ON_TOP && state != DIM_PARKING_TIRED) {
     52		stats_res = rdma_dim_stats_compare(curr_stats,
     53						   &dim->prev_stats);
     54
     55		switch (stats_res) {
     56		case DIM_STATS_SAME:
     57			if (curr_stats->cpe_ratio <= 50 * prev_ix)
     58				dim->profile_ix = 0;
     59			break;
     60		case DIM_STATS_WORSE:
     61			dim_turn(dim);
     62			fallthrough;
     63		case DIM_STATS_BETTER:
     64			step_res = rdma_dim_step(dim);
     65			if (step_res == DIM_ON_EDGE)
     66				dim_turn(dim);
     67			break;
     68		}
     69	}
     70
     71	dim->prev_stats = *curr_stats;
     72
     73	return dim->profile_ix != prev_ix;
     74}
     75
     76void rdma_dim(struct dim *dim, u64 completions)
     77{
     78	struct dim_sample *curr_sample = &dim->measuring_sample;
     79	struct dim_stats curr_stats;
     80	u32 nevents;
     81
     82	dim_update_sample_with_comps(curr_sample->event_ctr + 1, 0, 0,
     83				     curr_sample->comp_ctr + completions,
     84				     &dim->measuring_sample);
     85
     86	switch (dim->state) {
     87	case DIM_MEASURE_IN_PROGRESS:
     88		nevents = curr_sample->event_ctr - dim->start_sample.event_ctr;
     89		if (nevents < DIM_NEVENTS)
     90			break;
     91		dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats);
     92		if (rdma_dim_decision(&curr_stats, dim)) {
     93			dim->state = DIM_APPLY_NEW_PROFILE;
     94			schedule_work(&dim->work);
     95			break;
     96		}
     97		fallthrough;
     98	case DIM_START_MEASURE:
     99		dim->state = DIM_MEASURE_IN_PROGRESS;
    100		dim_update_sample_with_comps(curr_sample->event_ctr, 0, 0,
    101					     curr_sample->comp_ctr,
    102					     &dim->start_sample);
    103		break;
    104	case DIM_APPLY_NEW_PROFILE:
    105		break;
    106	}
    107}
    108EXPORT_SYMBOL(rdma_dim);