Files
linux-net/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c
Jack Miller 16c19a2e98 selftests/powerpc: Load Monitor Register Tests
Adds two tests. One is a simple test to ensure that the new registers
LMRR and LMSER are properly maintained. The other actually uses the
existing EBB test infrastructure to test that LMRR and LMSER behave as
documented.

Signed-off-by: Jack Miller <jack@codezen.org>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2016-06-21 15:30:50 +10:00

144 lines
2.7 KiB
C

/*
* Copyright 2016, Jack Miller, IBM Corp.
* Licensed under GPLv2.
*/
#include <stdlib.h>
#include <stdio.h>
#include "ebb.h"
#include "ebb_lmr.h"
#define SIZE (32 * 1024 * 1024) /* 32M */
#define LM_SIZE 0 /* Smallest encoding, 32M */
#define SECTIONS 64 /* 1 per bit in LMSER */
#define SECTION_SIZE (SIZE / SECTIONS)
#define SECTION_LONGS (SECTION_SIZE / sizeof(long))
static unsigned long *test_mem;
static int lmr_count = 0;
void ebb_lmr_handler(void)
{
lmr_count++;
}
void ldmx_full_section(unsigned long *mem, int section)
{
unsigned long *ptr;
int i;
for (i = 0; i < SECTION_LONGS; i++) {
ptr = &mem[(SECTION_LONGS * section) + i];
ldmx((unsigned long) &ptr);
ebb_lmr_reset();
}
}
unsigned long section_masks[] = {
0x8000000000000000,
0xFF00000000000000,
0x0000000F70000000,
0x8000000000000001,
0xF0F0F0F0F0F0F0F0,
0x0F0F0F0F0F0F0F0F,
0x0
};
int ebb_lmr_section_test(unsigned long *mem)
{
unsigned long *mask = section_masks;
int i;
for (; *mask; mask++) {
mtspr(SPRN_LMSER, *mask);
printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER));
for (i = 0; i < 64; i++) {
lmr_count = 0;
ldmx_full_section(mem, i);
if (*mask & (1UL << (63 - i)))
FAIL_IF(lmr_count != SECTION_LONGS);
else
FAIL_IF(lmr_count);
}
}
return 0;
}
int ebb_lmr(void)
{
int i;
SKIP_IF(!lmr_is_supported());
setup_ebb_handler(ebb_lmr_handler);
ebb_global_enable();
FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0);
mtspr(SPRN_LMSER, 0);
FAIL_IF(mfspr(SPRN_LMSER) != 0);
mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE));
FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE));
/* Read every single byte to ensure we get no false positives */
for (i = 0; i < SECTIONS; i++)
ldmx_full_section(test_mem, i);
FAIL_IF(lmr_count != 0);
/* Turn on the first section */
mtspr(SPRN_LMSER, (1UL << 63));
FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63));
/* Enable LM (BESCR) */
mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME);
FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME));
ldmx((unsigned long)&test_mem);
FAIL_IF(lmr_count != 1); // exactly one exception
FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled
FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set
printf("Simple LMR EBB OK\n");
/* This shouldn't cause an EBB since it's been disabled */
ldmx((unsigned long)&test_mem);
FAIL_IF(lmr_count != 1);
printf("LMR disable on EBB OK\n");
ebb_lmr_reset();
/* This should cause an EBB or reset is broken */
ldmx((unsigned long)&test_mem);
FAIL_IF(lmr_count != 2);
printf("LMR reset EBB OK\n");
ebb_lmr_reset();
return ebb_lmr_section_test(test_mem);
}
int main(void)
{
int ret = test_harness(ebb_lmr, "ebb_lmr");
if (test_mem)
free(test_mem);
return ret;
}