/*
 * Check emulated system register access for linux-user mode.
 *
 * See: https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt
 *
 * Copyright (c) 2019 Linaro
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>

#ifndef HWCAP_CPUID
#define HWCAP_CPUID (1 << 11)
#endif

/*
 * Older assemblers don't recognize newer system register names,
 * but we can still access them by the Sn_n_Cn_Cn_n syntax.
 */
#define SYS_ID_AA64ISAR2_EL1 S3_0_C0_C6_2
#define SYS_ID_AA64MMFR2_EL1 S3_0_C0_C7_2

int failed_bit_count;

/* Read and print system register `id' value */
#define get_cpu_reg(id) ({                                      \
            unsigned long __val = 0xdeadbeef;                   \
            asm("mrs %0, "#id : "=r" (__val));                  \
            printf("%-20s: 0x%016lx\n", #id, __val);            \
            __val;                                               \
        })

/* As above but also check no bits outside of `mask' are set*/
#define get_cpu_reg_check_mask(id, mask) ({                     \
            unsigned long __cval = get_cpu_reg(id);             \
            unsigned long __extra = __cval & ~mask;             \
            if (__extra) {                                      \
                printf("%-20s: 0x%016lx\n", "  !!extra bits!!", __extra);   \
                failed_bit_count++;                            \
            }                                                   \
})

/* As above but check RAZ */
#define get_cpu_reg_check_zero(id) ({                           \
            unsigned long __val = 0xdeadbeef;                   \
            asm("mrs %0, "#id : "=r" (__val));                  \
            if (__val) {                                        \
                printf("%-20s: 0x%016lx (not RAZ!)\n", #id, __val);        \
                failed_bit_count++;                            \
            }                                                   \
})

/* Chunk up mask into 63:48, 47:32, 31:16, 15:0 to ease counting */
#define _m(a, b, c, d) (0x ## a ## b ## c ## d ##ULL)

bool should_fail;
int should_fail_count;
int should_not_fail_count;
uintptr_t failed_pc[10];

void sigill_handler(int signo, siginfo_t *si, void *data)
{
    ucontext_t *uc = (ucontext_t *)data;

    if (should_fail) {
        should_fail_count++;
    } else {
        uintptr_t pc = (uintptr_t) uc->uc_mcontext.pc;
        failed_pc[should_not_fail_count++] =  pc;
    }
    uc->uc_mcontext.pc += 4;
}

int main(void)
{
    struct sigaction sa;

    /* Hook in a SIGILL handler */
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = &sigill_handler;
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIGILL, &sa, 0) != 0) {
        perror("sigaction");
        return 1;
    }

    /* Counter values have been exposed since Linux 4.12 */
    printf("Checking Counter registers\n");

    get_cpu_reg(ctr_el0);
    get_cpu_reg(cntvct_el0);
    get_cpu_reg(cntfrq_el0);

    /* HWCAP_CPUID indicates we can read feature registers, since Linux 4.11 */
    if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
        printf("CPUID registers unavailable\n");
        return 1;
    } else {
        printf("Checking CPUID registers\n");
    }

    /*
     * Some registers only expose some bits to user-space. Anything
     * that is IMPDEF is exported as 0 to user-space. The _mask checks
     * assert no extra bits are set.
     *
     * This check is *not* comprehensive as some fields are set to
     * minimum valid fields - for the purposes of this check allowed
     * to have non-zero values.
     */
    get_cpu_reg_check_mask(id_aa64isar0_el1, _m(f0ff,ffff,f0ff,fff0));
    get_cpu_reg_check_mask(id_aa64isar1_el1, _m(00ff,f0ff,ffff,ffff));
    get_cpu_reg_check_mask(SYS_ID_AA64ISAR2_EL1, _m(0000,0000,0000,ffff));
    /* TGran4 & TGran64 as pegged to -1 */
    get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(f000,0000,ff00,0000));
    get_cpu_reg_check_mask(id_aa64mmfr1_el1, _m(0000,f000,0000,0000));
    get_cpu_reg_check_mask(SYS_ID_AA64MMFR2_EL1, _m(0000,000f,0000,0000));
    /* EL1/EL0 reported as AA64 only */
    get_cpu_reg_check_mask(id_aa64pfr0_el1,  _m(000f,000f,00ff,0011));
    get_cpu_reg_check_mask(id_aa64pfr1_el1,  _m(0000,0000,0f00,0fff));
    /* all hidden, DebugVer fixed to 0x6 (ARMv8 debug architecture) */
    get_cpu_reg_check_mask(id_aa64dfr0_el1,  _m(0000,0000,0000,0006));
    get_cpu_reg_check_zero(id_aa64dfr1_el1);
    get_cpu_reg_check_mask(id_aa64zfr0_el1,  _m(0ff0,ff0f,00ff,00ff));
#ifdef HAS_ARMV9_SME
    get_cpu_reg_check_mask(id_aa64smfr0_el1, _m(80f1,00fd,0000,0000));
#endif

    get_cpu_reg_check_zero(id_aa64afr0_el1);
    get_cpu_reg_check_zero(id_aa64afr1_el1);

    get_cpu_reg_check_mask(midr_el1,         _m(0000,0000,ffff,ffff));
    /* mpidr sets bit 31, everything else hidden */
    get_cpu_reg_check_mask(mpidr_el1,        _m(0000,0000,8000,0000));
    /* REVIDR is all IMPDEF so should be all zeros to user-space */
    get_cpu_reg_check_zero(revidr_el1);

    /*
     * There are a block of more registers that are RAZ in the rest of
     * the Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7 space. However for
     * brevity we don't check stuff that is currently un-allocated
     * here. Feel free to add them ;-)
     */

    printf("Remaining registers should fail\n");
    should_fail = true;

    /* Unexposed register access causes SIGILL */
    get_cpu_reg(id_mmfr0_el1);
    get_cpu_reg(id_mmfr1_el1);
    get_cpu_reg(id_mmfr2_el1);
    get_cpu_reg(id_mmfr3_el1);

    get_cpu_reg(mvfr0_el1);
    get_cpu_reg(mvfr1_el1);

    if (should_not_fail_count > 0) {
        int i;
        for (i = 0; i < should_not_fail_count; i++) {
            uintptr_t pc = failed_pc[i];
            uint32_t insn = *(uint32_t *) pc;
            printf("insn %#x @ %#lx unexpected FAIL\n", insn, pc);
        }
        return 1;
    }

    if (failed_bit_count > 0) {
        printf("Extra information leaked to user-space!\n");
        return 1;
    }

    return should_fail_count == 6 ? 0 : 1;
}
