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

cycles_with_freeze_test.c (2427B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2014, Michael Ellerman, IBM Corp.
      4 */
      5
      6#include <stdio.h>
      7#include <stdlib.h>
      8#include <stdbool.h>
      9
     10#include "ebb.h"
     11
     12
     13/*
     14 * Test of counting cycles while using MMCR0_FC (freeze counters) to only count
     15 * parts of the code. This is complicated by the fact that FC is set by the
     16 * hardware when the event overflows. We may take the EBB after we have set FC,
     17 * so we have to be careful about whether we clear FC at the end of the EBB
     18 * handler or not.
     19 */
     20
     21static bool counters_frozen = false;
     22static int ebbs_while_frozen = 0;
     23
     24static void ebb_callee(void)
     25{
     26	uint64_t mask, val;
     27
     28	mask = MMCR0_PMAO | MMCR0_FC;
     29
     30	val = mfspr(SPRN_BESCR);
     31	if (!(val & BESCR_PMEO)) {
     32		ebb_state.stats.spurious++;
     33		goto out;
     34	}
     35
     36	ebb_state.stats.ebb_count++;
     37	trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count);
     38
     39	val = mfspr(SPRN_MMCR0);
     40	trace_log_reg(ebb_state.trace, SPRN_MMCR0, val);
     41
     42	if (counters_frozen) {
     43		trace_log_string(ebb_state.trace, "frozen");
     44		ebbs_while_frozen++;
     45		mask &= ~MMCR0_FC;
     46	}
     47
     48	count_pmc(1, sample_period);
     49out:
     50	reset_ebb_with_clear_mask(mask);
     51}
     52
     53int cycles_with_freeze(void)
     54{
     55	struct event event;
     56	uint64_t val;
     57	bool fc_cleared;
     58
     59	SKIP_IF(!ebb_is_supported());
     60
     61	event_init_named(&event, 0x1001e, "cycles");
     62	event_leader_ebb_init(&event);
     63
     64	event.attr.exclude_kernel = 1;
     65	event.attr.exclude_hv = 1;
     66	event.attr.exclude_idle = 1;
     67
     68	FAIL_IF(event_open(&event));
     69
     70	setup_ebb_handler(ebb_callee);
     71	ebb_global_enable();
     72	FAIL_IF(ebb_event_enable(&event));
     73
     74	mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
     75
     76	fc_cleared = false;
     77
     78	/* Make sure we loop until we take at least one EBB */
     79	while ((ebb_state.stats.ebb_count < 20 && !fc_cleared) ||
     80		ebb_state.stats.ebb_count < 1)
     81	{
     82		counters_frozen = false;
     83		mb();
     84		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC);
     85
     86		FAIL_IF(core_busy_loop());
     87
     88		counters_frozen = true;
     89		mb();
     90		mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) |  MMCR0_FC);
     91
     92		val = mfspr(SPRN_MMCR0);
     93		if (! (val & MMCR0_FC)) {
     94			printf("Outside of loop, FC NOT set MMCR0 0x%lx\n", val);
     95			fc_cleared = true;
     96		}
     97	}
     98
     99	ebb_global_disable();
    100	ebb_freeze_pmcs();
    101
    102	dump_ebb_state();
    103
    104	printf("EBBs while frozen %d\n", ebbs_while_frozen);
    105
    106	event_close(&event);
    107
    108	FAIL_IF(ebb_state.stats.ebb_count == 0);
    109	FAIL_IF(fc_cleared);
    110
    111	return 0;
    112}
    113
    114int main(void)
    115{
    116	return test_harness(cycles_with_freeze, "cycles_with_freeze");
    117}