root/tools/testing/selftests/arm64/signal/testcases/poe_missing_poe_context.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2026 Arm Ltd
 *
 * Verify that the POR_EL0 register is left untouched on sigreturn if the
 * POE frame record is missing.
 */

#include <asm/sigcontext.h>

#include "test_signals_utils.h"
#include "testcases.h"

#define POR_EL0_INIT    0x07ul
#define POR_EL0_CUSTOM  0x77ul

static bool failed_check;

static bool modify_por_el0(struct tdescr *td)
{
        set_por_el0(POR_EL0_CUSTOM);

        return true;
}

static int signal_remove_poe_context(struct tdescr *td, siginfo_t *si,
                                      ucontext_t *uc)
{
        struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uc);
        size_t resv_size = GET_UCP_RESV_SIZE(uc);
        struct _aarch64_ctx *poe_ctx_head;

        poe_ctx_head = get_header(ctx, POE_MAGIC, resv_size, NULL);
        if (!poe_ctx_head) {
                fprintf(stderr, "Missing poe_context record\n");
                failed_check = true;
                return 0;
        }

        /*
         * Actually removing the record would require moving down the next
         * records. An easier option is to turn it into an ESR record, which is
         * ignored by sigreturn().
         */
        poe_ctx_head->magic = ESR_MAGIC;

        return 0;
}

static void check_por_el0_preserved(struct tdescr *td)
{
        uint64_t por_el0 = get_por_el0();

        if (por_el0 == POR_EL0_INIT) {
                fprintf(stderr, "POR_EL0 preserved\n");
        } else {
                fprintf(stderr, "POR_EL0 unexpectedly set to %lx\n", por_el0);
                failed_check = true;
        }

        td->pass = !failed_check;
}

struct tdescr tde = {
        .name = "POR_EL0 missing poe_context",
        .descr = "Remove poe_context record and check POR_EL0 is preserved",
        .feats_required = FEAT_POE,
        .timeout = 3,
        .sig_trig = SIGUSR1,
        .init = modify_por_el0,
        .run = signal_remove_poe_context,
        .check_result = check_por_el0_preserved,
};