162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * Copyright 2018 IBM Corporation. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define __SANE_USERSPACE_TYPES__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <sys/types.h> 1062306a36Sopenharmony_ci#include <stdint.h> 1162306a36Sopenharmony_ci#include <unistd.h> 1262306a36Sopenharmony_ci#include <signal.h> 1362306a36Sopenharmony_ci#include <stdlib.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci#include <stdio.h> 1662306a36Sopenharmony_ci#include <sys/utsname.h> 1762306a36Sopenharmony_ci#include "reg.h" 1862306a36Sopenharmony_ci#include "utils.h" 1962306a36Sopenharmony_ci#include "flush_utils.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic inline __u64 load(void *addr) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci __u64 tmp; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci asm volatile("ld %0,0(%1)" : "=r"(tmp) : "b"(addr)); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci return tmp; 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid syscall_loop(char *p, unsigned long iterations, 3162306a36Sopenharmony_ci unsigned long zero_size) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci for (unsigned long i = 0; i < iterations; i++) { 3462306a36Sopenharmony_ci for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE) 3562306a36Sopenharmony_ci load(p + j); 3662306a36Sopenharmony_ci getppid(); 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_civoid syscall_loop_uaccess(char *p, unsigned long iterations, 4162306a36Sopenharmony_ci unsigned long zero_size) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct utsname utsname; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci for (unsigned long i = 0; i < iterations; i++) { 4662306a36Sopenharmony_ci for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE) 4762306a36Sopenharmony_ci load(p + j); 4862306a36Sopenharmony_ci uname(&utsname); 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic void sigill_handler(int signr, siginfo_t *info, void *unused) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci static int warned; 5562306a36Sopenharmony_ci ucontext_t *ctx = (ucontext_t *)unused; 5662306a36Sopenharmony_ci unsigned long *pc = &UCONTEXT_NIA(ctx); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* mtspr 3,RS to check for move to DSCR below */ 5962306a36Sopenharmony_ci if ((*((unsigned int *)*pc) & 0xfc1fffff) == 0x7c0303a6) { 6062306a36Sopenharmony_ci if (!warned++) 6162306a36Sopenharmony_ci printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n"); 6262306a36Sopenharmony_ci *pc += 4; 6362306a36Sopenharmony_ci } else { 6462306a36Sopenharmony_ci printf("SIGILL at %p\n", pc); 6562306a36Sopenharmony_ci abort(); 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_civoid set_dscr(unsigned long val) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci static int init; 7262306a36Sopenharmony_ci struct sigaction sa; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (!init) { 7562306a36Sopenharmony_ci memset(&sa, 0, sizeof(sa)); 7662306a36Sopenharmony_ci sa.sa_sigaction = sigill_handler; 7762306a36Sopenharmony_ci sa.sa_flags = SA_SIGINFO; 7862306a36Sopenharmony_ci if (sigaction(SIGILL, &sa, NULL)) 7962306a36Sopenharmony_ci perror("sigill_handler"); 8062306a36Sopenharmony_ci init = 1; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci mtspr(SPRN_DSCR, val); 8462306a36Sopenharmony_ci} 85