blob: dff4961876021c04cdb658695e6be4fc406a3086 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Perform Set Clock tests
*
* Copyright IBM Corp. 2022
*
* Authors:
* Nico Boehr <nrb@linux.ibm.com>
*/
#include <libcflat.h>
#include <uv.h>
#include <asm/interrupt.h>
#include <asm/time.h>
static void test_priv(void)
{
uint64_t time_to_set_privileged = 0xfacef00dcafe0000,
time_to_set_nonprivileged = 0xcafe0000,
time_verify;
int cc;
report_prefix_push("privileged");
cc = sck(&time_to_set_privileged);
report(!cc, "set clock cc=%d", cc);
cc = stck(&time_verify);
report(!cc, "store clock cc=%d", cc);
report(time_verify > time_to_set_privileged,
"privileged set affected the clock");
report_prefix_pop();
report_prefix_push("unprivileged");
expect_pgm_int();
enter_pstate();
sck(&time_to_set_nonprivileged);
leave_pstate();
check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
cc = stck(&time_verify);
report(!cc, "store clock cc=%d", cc);
report(time_verify > time_to_set_privileged,
"unprivileged set did not affect the clock");
report_prefix_pop();
}
static void test_align(void)
{
const int align_to = 8;
char unalign[sizeof(uint64_t) + align_to] __attribute__((aligned(8)));
report_prefix_push("Unaligned operand");
for (int i = 1; i < align_to; i *= 2) {
report_prefix_pushf("%d", i);
expect_pgm_int();
sck((uint64_t *)(unalign + i));
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
}
report_prefix_pop();
}
static void test_set(void)
{
uint64_t start = 0, end = 0, time = 0xcafef00dbeef;
const uint64_t ticks_per_ms = 1000 << 12, ms_to_wait = 5;
int cc;
report_prefix_push("set");
cc = sck(&time);
report(!cc, "set clock cc=%d", cc);
cc = stck(&start);
report(!cc, "store start clock cc=%d", cc);
report(start >= time, "start >= set value");
mdelay(ms_to_wait);
cc = stck(&end);
report(!cc, "store end clock cc=%d", cc);
report(end > time, "end > set value");
report(end - start > (ticks_per_ms * ms_to_wait), "Advances");
report_prefix_pop();
}
int main(void)
{
report_prefix_push("sck");
if (uv_os_is_guest()) {
report_skip("Test unsupported under PV");
goto out;
}
test_align();
test_set();
test_priv();
out:
report_prefix_pop();
return report_summary();
}