cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptrace-tm-spr.c (3137B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Ptrace test TM SPR registers
      4 *
      5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
      6 */
      7#include "ptrace.h"
      8#include "tm.h"
      9
     10/* Tracee and tracer shared data */
     11struct shared {
     12	int flag;
     13	struct tm_spr_regs regs;
     14};
     15unsigned long tfhar;
     16
     17int shm_id;
     18struct shared *cptr, *pptr;
     19
     20int shm_id1;
     21int *cptr1, *pptr1;
     22
     23#define TM_KVM_SCHED   0xe0000001ac000001
     24int validate_tm_spr(struct tm_spr_regs *regs)
     25{
     26	FAIL_IF(regs->tm_tfhar != tfhar);
     27	FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
     28
     29	return TEST_PASS;
     30}
     31
     32void tm_spr(void)
     33{
     34	unsigned long result, texasr;
     35	int ret;
     36
     37	cptr = (struct shared *)shmat(shm_id, NULL, 0);
     38	cptr1 = (int *)shmat(shm_id1, NULL, 0);
     39
     40trans:
     41	cptr1[0] = 0;
     42	asm __volatile__(
     43		"1: ;"
     44		/* TM failover handler should follow "tbegin.;" */
     45		"mflr 31;"
     46		"bl 4f;"	/* $ = TFHAR - 12 */
     47		"4: ;"
     48		"mflr %[tfhar];"
     49		"mtlr 31;"
     50
     51		"tbegin.;"
     52		"beq 2f;"
     53
     54		"tsuspend.;"
     55		"li 8, 1;"
     56		"sth 8, 0(%[cptr1]);"
     57		"tresume.;"
     58		"b .;"
     59
     60		"tend.;"
     61		"li 0, 0;"
     62		"ori %[res], 0, 0;"
     63		"b 3f;"
     64
     65		"2: ;"
     66
     67		"li 0, 1;"
     68		"ori %[res], 0, 0;"
     69		"mfspr %[texasr], %[sprn_texasr];"
     70
     71		"3: ;"
     72		: [tfhar] "=r" (tfhar), [res] "=r" (result),
     73		[texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
     74		: [sprn_texasr] "i"  (SPRN_TEXASR)
     75		: "memory", "r0", "r8", "r31"
     76		);
     77
     78	/* There are 2 32bit instructions before tbegin. */
     79	tfhar += 12;
     80
     81	if (result) {
     82		if (!cptr->flag)
     83			goto trans;
     84
     85		ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
     86		shmdt((void *)cptr);
     87		shmdt((void *)cptr1);
     88		if (ret)
     89			exit(1);
     90		exit(0);
     91	}
     92	shmdt((void *)cptr);
     93	shmdt((void *)cptr1);
     94	exit(1);
     95}
     96
     97int trace_tm_spr(pid_t child)
     98{
     99	FAIL_IF(start_trace(child));
    100	FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
    101
    102	printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
    103				pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
    104
    105	pptr->flag = 1;
    106	FAIL_IF(stop_trace(child));
    107
    108	return TEST_PASS;
    109}
    110
    111int ptrace_tm_spr(void)
    112{
    113	pid_t pid;
    114	int ret, status;
    115
    116	SKIP_IF(!have_htm());
    117	SKIP_IF(htm_is_synthetic());
    118	shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
    119	shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
    120	pid = fork();
    121	if (pid < 0) {
    122		perror("fork() failed");
    123		return TEST_FAIL;
    124	}
    125
    126	if (pid == 0)
    127		tm_spr();
    128
    129	if (pid) {
    130		pptr = (struct shared *)shmat(shm_id, NULL, 0);
    131		pptr1 = (int *)shmat(shm_id1, NULL, 0);
    132
    133		while (!pptr1[0])
    134			asm volatile("" : : : "memory");
    135		ret = trace_tm_spr(pid);
    136		if (ret) {
    137			kill(pid, SIGKILL);
    138			shmdt((void *)pptr);
    139			shmdt((void *)pptr1);
    140			shmctl(shm_id, IPC_RMID, NULL);
    141			shmctl(shm_id1, IPC_RMID, NULL);
    142			return TEST_FAIL;
    143		}
    144
    145		shmdt((void *)pptr);
    146		shmdt((void *)pptr1);
    147		ret = wait(&status);
    148		shmctl(shm_id, IPC_RMID, NULL);
    149		shmctl(shm_id1, IPC_RMID, NULL);
    150		if (ret != pid) {
    151			printf("Child's exit status not captured\n");
    152			return TEST_FAIL;
    153		}
    154
    155		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
    156			TEST_PASS;
    157	}
    158	return TEST_PASS;
    159}
    160
    161int main(int argc, char *argv[])
    162{
    163	return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
    164}