// 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 #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, };