// SPDX-License-Identifier: GPL-2.0+
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "dexcr.h"
#include "reg.h"
#include "utils.h"
static jmp_buf generic_signal_jump_buf;
static void generic_signal_handler(int signum, siginfo_t *info, void *context)
{
longjmp(generic_signal_jump_buf, 0 );
}
bool dexcr_exists(void )
{
struct sigaction old;
volatile bool exists;
old = push_signal_handler(SIGILL, generic_signal_handler);
if (setjmp(generic_signal_jump_buf))
goto out;
/*
* If the SPR is not recognised by the hardware it triggers
* a hypervisor emulation interrupt . If the kernel does not
* recognise / try to emulate it , we receive a SIGILL signal .
*
* If we do not receive a signal , assume we have the SPR or the
* kernel is trying to emulate it correctly .
*/
exists = false ;
mfspr(SPRN_DEXCR_RO);
exists = true ;
out:
pop_signal_handler(SIGILL, old);
return exists;
}
unsigned int pr_which_to_aspect(unsigned long which)
{
switch (which) {
case PR_PPC_DEXCR_SBHE:
return DEXCR_PR_SBHE;
case PR_PPC_DEXCR_IBRTPD:
return DEXCR_PR_IBRTPD;
case PR_PPC_DEXCR_SRAPD:
return DEXCR_PR_SRAPD;
case PR_PPC_DEXCR_NPHIE:
return DEXCR_PR_NPHIE;
default :
FAIL_IF_EXIT_MSG(true , "unknown PR aspect" );
}
}
int pr_get_dexcr(unsigned long which)
{
return prctl(PR_PPC_GET_DEXCR, which, 0 UL, 0 UL, 0 UL);
}
int pr_set_dexcr(unsigned long which, unsigned long ctrl)
{
return prctl(PR_PPC_SET_DEXCR, which, ctrl, 0 UL, 0 UL);
}
bool pr_dexcr_aspect_supported(unsigned long which)
{
if (pr_get_dexcr(which) == -1 )
return errno == ENODEV;
return true ;
}
bool pr_dexcr_aspect_editable(unsigned long which)
{
return pr_get_dexcr(which) & PR_PPC_DEXCR_CTRL_EDITABLE;
}
/*
* Just test if a bad hashchk triggers a signal , without checking
* for support or if the NPHIE aspect is enabled .
*/
bool hashchk_triggers(void )
{
struct sigaction old;
volatile bool triggers;
old = push_signal_handler(SIGILL, generic_signal_handler);
if (setjmp(generic_signal_jump_buf))
goto out;
triggers = true ;
do_bad_hashchk();
triggers = false ;
out:
pop_signal_handler(SIGILL, old);
return triggers;
}
unsigned int get_dexcr(enum dexcr_source source)
{
switch (source) {
case DEXCR:
return mfspr(SPRN_DEXCR_RO);
case HDEXCR:
return mfspr(SPRN_HDEXCR_RO);
case EFFECTIVE:
return mfspr(SPRN_DEXCR_RO) | mfspr(SPRN_HDEXCR_RO);
default :
FAIL_IF_EXIT_MSG(true , "bad enum dexcr_source" );
}
}
void await_child_success(pid_t pid)
{
int wstatus;
FAIL_IF_EXIT_MSG(pid == -1 , "fork failed" );
FAIL_IF_EXIT_MSG(waitpid(pid, &wstatus, 0 ) == -1 , "wait failed" );
FAIL_IF_EXIT_MSG(!WIFEXITED(wstatus), "child did not exit cleanly" );
FAIL_IF_EXIT_MSG(WEXITSTATUS(wstatus) != 0 , "child exit error" );
}
/*
* Perform a hashst instruction . The following components determine the result
*
* 1 . The LR value ( any register technically )
* 2 . The SP value ( also any register , but it must be a valid address )
* 3 . A secret key managed by the kernel
*
* The result is stored to the address held in SP .
*/
void hashst(unsigned long lr, void *sp)
{
asm volatile ("addi 31, %0, 0;" /* set r31 (pretend LR) to lr */
"addi 30, %1, 8;" /* set r30 (pretend SP) to sp + 8 */
PPC_RAW_HASHST(31 , -8 , 30 ) /* compute hash into stack location */
: : "r" (lr), "r" (sp) : "r31" , "r30" , "memory" );
}
/*
* Perform a hashchk instruction . A hash is computed as per hashst ( ) ,
* however the result is not stored to memory . Instead the existing
* value is read and compared against the computed hash .
*
* If they match , execution continues .
* If they differ , an interrupt triggers .
*/
void hashchk(unsigned long lr, void *sp)
{
asm volatile ("addi 31, %0, 0;" /* set r31 (pretend LR) to lr */
"addi 30, %1, 8;" /* set r30 (pretend SP) to sp + 8 */
PPC_RAW_HASHCHK(31 , -8 , 30 ) /* check hash at stack location */
: : "r" (lr), "r" (sp) : "r31" , "r30" , "memory" );
}
void do_bad_hashchk(void )
{
unsigned long hash = 0 ;
hashst(0 , &hash);
hash += 1 ;
hashchk(0 , &hash);
}
Messung V0.5 in Prozent C=96 H=89 G=92
¤ Dauer der Verarbeitung: 0.6 Sekunden
(vorverarbeitet am 2026-10-12)
¤
*© Formatika GbR, Deutschland