aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/aarch64/dcpodp.c
blob: 2cf7df2e073b0e612bbb21fe979453151269815d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
 * Test execution of DC CVADP instruction.
 *
 * Copyright (c) 2023 Zhuojia Shen <chaosdefinition@hotmail.com>
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <asm/hwcap.h>
#include <sys/auxv.h>

#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef HWCAP2_DCPODP
#define HWCAP2_DCPODP (1 << 0)
#endif

bool should_fail = false;

static void signal_handler(int sig, siginfo_t *si, void *data)
{
    ucontext_t *uc = (ucontext_t *)data;

    if (should_fail) {
        uc->uc_mcontext.pc += 4;
    } else {
        exit(EXIT_FAILURE);
    }
}

static int do_dc_cvadp(void)
{
    struct sigaction sa = {
        .sa_flags = SA_SIGINFO,
        .sa_sigaction = signal_handler,
    };

    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGSEGV, &sa, NULL) < 0) {
        perror("sigaction");
        return EXIT_FAILURE;
    }

    asm volatile("dc cvadp, %0\n\t" :: "r"(&sa));

    should_fail = true;
    asm volatile("dc cvadp, %0\n\t" :: "r"(NULL));
    should_fail = false;

    return EXIT_SUCCESS;
}

int main(void)
{
    if (getauxval(AT_HWCAP2) & HWCAP2_DCPODP) {
        return do_dc_cvadp();
    } else {
        printf("SKIP: no HWCAP2_DCPODP on this system\n");
        return EXIT_SUCCESS;
    }
}