blob: 92ed4e5d35eb194e06e3309e553f4e627ebf0ca5 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017 Red Hat Inc
*
* Authors:
* Thomas Huth <thuth@redhat.com>
* David Hildenbrand <david@redhat.com>
*/
#include <libcflat.h>
#include <util.h>
#include <alloc.h>
#include <asm/interrupt.h>
#include <asm/barrier.h>
#include <asm/pgtable.h>
static void test_fp(void)
{
double a = 3.0;
double b = 2.0;
double c;
asm volatile(
" ddb %1, %2\n"
" std %1, %0\n"
: "=m" (c) : "f" (a), "m" (b));
report(c == 1.5, "3.0/2.0 == 1.5");
}
static void test_pgm_int(void)
{
expect_pgm_int();
asm volatile(" .insn e,0x0000"); /* used for SW breakpoints in QEMU */
check_pgm_int_code(PGM_INT_CODE_OPERATION);
expect_pgm_int();
asm volatile(" stg %0,0(%0)\n" : : "a"(-1L));
check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
}
static void test_malloc(void)
{
int *tmp, *tmp2;
report_prefix_push("malloc");
report_prefix_push("ptr_0");
tmp = malloc(sizeof(int));
report((uintptr_t)tmp & 0xf000000000000000ul, "allocated memory");
*tmp = 123456789;
mb();
report(*tmp == 123456789, "wrote allocated memory");
report_prefix_pop();
report_prefix_push("ptr_1");
tmp2 = malloc(sizeof(int));
report((uintptr_t)tmp2 & 0xf000000000000000ul,
"allocated memory");
*tmp2 = 123456789;
mb();
report((*tmp2 == 123456789), "wrote allocated memory");
report_prefix_pop();
report(tmp != tmp2, "allocated memory addresses differ");
expect_pgm_int();
disable_dat();
*tmp = 987654321;
enable_dat();
check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
free(tmp);
free(tmp2);
report_prefix_pop();
}
static void test_psw_mask(void)
{
uint64_t expected_key = 0xf;
struct psw test_psw = PSW(0, 0);
report_prefix_push("PSW mask");
test_psw.mask = PSW_MASK_DAT;
report(test_psw.dat, "DAT matches expected=0x%016lx actual=0x%016lx", PSW_MASK_DAT, test_psw.mask);
test_psw.mask = PSW_MASK_IO;
report(test_psw.io, "IO matches expected=0x%016lx actual=0x%016lx", PSW_MASK_IO, test_psw.mask);
test_psw.mask = PSW_MASK_EXT;
report(test_psw.ext, "EXT matches expected=0x%016lx actual=0x%016lx", PSW_MASK_EXT, test_psw.mask);
test_psw.mask = expected_key << (63 - 11);
report(test_psw.key == expected_key, "PSW Key matches expected=0x%lx actual=0x%x", expected_key, test_psw.key);
test_psw.mask = 1UL << (63 - 13);
report(test_psw.mchk, "MCHK matches");
test_psw.mask = PSW_MASK_WAIT;
report(test_psw.wait, "Wait matches expected=0x%016lx actual=0x%016lx", PSW_MASK_WAIT, test_psw.mask);
test_psw.mask = PSW_MASK_PSTATE;
report(test_psw.pstate, "Pstate matches expected=0x%016lx actual=0x%016lx", PSW_MASK_PSTATE, test_psw.mask);
test_psw.mask = PSW_MASK_64;
report(test_psw.ea && test_psw.ba, "BA/EA matches expected=0x%016lx actual=0x%016lx", PSW_MASK_64, test_psw.mask);
report_prefix_pop();
}
int main(int argc, char**argv)
{
report_prefix_push("selftest");
report_pass("true");
report(argc == 3, "argc == 3");
report(!strcmp(argv[0], "s390x/selftest.elf"), "argv[0] == PROGNAME");
report(!strcmp(argv[1], "test"), "argv[1] == test");
report(!strcmp(argv[2], "123"), "argv[2] == 123");
setup_vm();
test_fp();
test_pgm_int();
test_malloc();
test_psw_mask();
return report_summary();
}