Commit 865f099d authored by Alice Frosi's avatar Alice Frosi Committed by Andrei Vagin

s390: Add test case for RI

- Add new test "s390x_runtime_instr" to check if the RI control block is
   correctly restored when the RI is active.

 - Add RI control block in test s390x_regs_check.c

The original test case for RI has been provided by
Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: 's avatarAlice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: 's avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 581f731b
...@@ -188,7 +188,8 @@ endif ...@@ -188,7 +188,8 @@ endif
ifeq ($(SRCARCH),s390) ifeq ($(SRCARCH),s390)
TST_NOFILE += s390x_regs_check \ TST_NOFILE += s390x_regs_check \
s390x_gs_threads s390x_gs_threads \
s390x_runtime_instr
endif endif
TST_FILE = \ TST_FILE = \
......
...@@ -226,6 +226,36 @@ struct reg_set reg_set_gs_bc = { ...@@ -226,6 +226,36 @@ struct reg_set reg_set_gs_bc = {
.optional = true, .optional = true,
}; };
/*
* s390 runtime-instrumentation control block
*/
#define NT_S390_RI_CB 0x30d
struct ri_cb {
uint64_t regs[8];
};
struct ri_cb ri_cb_data = {
.regs = {
0x000002aa13aae000,
0x000002aa13aad000,
0x000002aa13aadfff,
0xe0a1000400000000,
0x0000000000000000,
0x0000000000004e20,
0x0000000000003479,
0x0000000000000000,
}
};
struct reg_set reg_set_ri_cb = {
.name = "RI_CB",
.nr = NT_S390_RI_CB,
.data = &ri_cb_data,
.len = sizeof(ri_cb_data),
.optional = true,
};
/* /*
* Vector with all regsets * Vector with all regsets
*/ */
...@@ -235,6 +265,7 @@ struct reg_set *reg_set_vec[] = { ...@@ -235,6 +265,7 @@ struct reg_set *reg_set_vec[] = {
&reg_set_vxrs_high, &reg_set_vxrs_high,
&reg_set_gs_cb, &reg_set_gs_cb,
&reg_set_gs_bc, &reg_set_gs_bc,
&reg_set_ri_cb,
NULL, NULL,
}; };
......
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <asm/ptrace.h>
#include <linux/elf.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <ucontext.h>
#include <signal.h>
#include <string.h>
#include "zdtmtst.h"
#ifndef __NR_s390_runtime_instr
#define __NR_s390_runtime_instr 342
#endif
#define NT_S390_RI_CB 0x30d
#define BUF_SIZE (1024*1024)
const char *test_doc = "Check runtime-instrumentation";
/* Original test provided by Martin Schwidefsky <schwidefsky@de.ibm.com> */
const char *test_author = "Alice Frosi <alice@linux.vnet.ibm.com>";
struct runtime_instr_cb {
unsigned long rca;
unsigned long roa;
unsigned long rla;
unsigned int v : 1;
unsigned int s : 1;
unsigned int k : 1;
unsigned int h : 1;
unsigned int a : 1;
unsigned int reserved1 : 3;
unsigned int ps : 1;
unsigned int qs : 1;
unsigned int pc : 1;
unsigned int qc : 1;
unsigned int reserved2 : 1;
unsigned int g : 1;
unsigned int u : 1;
unsigned int l : 1;
unsigned int key : 4;
unsigned int reserved3 : 8;
unsigned int t : 1;
unsigned int rgs : 3;
unsigned int m : 4;
unsigned int n : 1;
unsigned int mae : 1;
unsigned int reserved4 : 2;
unsigned int c : 1;
unsigned int r : 1;
unsigned int b : 1;
unsigned int j : 1;
unsigned int e : 1;
unsigned int x : 1;
unsigned int reserved5 : 2;
unsigned int bpxn : 1;
unsigned int bpxt : 1;
unsigned int bpti : 1;
unsigned int bpni : 1;
unsigned int reserved6 : 2;
unsigned int d : 1;
unsigned int f : 1;
unsigned int ic : 4;
unsigned int dc : 4;
unsigned long reserved7;
unsigned long sf;
unsigned long rsic;
unsigned long reserved8;
};
/*
* Return PSW mask
*/
static inline unsigned long extract_psw(void)
{
unsigned int reg1, reg2;
asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2));
return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
}
/*
* Enable runtime-instrumentation
*/
static inline void rion(void)
{
asm volatile (".word 0xaa01, 0x0000");
}
/*
* Disable runtime-instrumentation
*/
static inline void rioff(void)
{
asm volatile (".word 0xaa03, 0x0000");
}
/*
* Modify the current runtime-instrumentation control block
*/
static inline void mric(struct runtime_instr_cb *cb)
{
asm volatile(".insn rsy,0xeb0000000062,0,0,%0" : : "Q" (*cb));
}
/*
* Store the current runtime-instrumentation control block
*/
static inline void stric(struct runtime_instr_cb *cb)
{
asm volatile(".insn rsy,0xeb0000000061,0,0,%0" : "=Q" (*cb) : : "cc");
}
/*
* Ensure that runtime-intstrumentation is still working after C/R
*/
int main(int argc, char **argv)
{
struct runtime_instr_cb ricb, ricb_check;
unsigned long *ricb_check_ptr = (unsigned long *) &ricb_check;
unsigned long *ricb_ptr = (unsigned long *) &ricb;
unsigned long psw_mask;
void *buf;
int i;
test_init(argc, argv);
buf = malloc(BUF_SIZE);
memset(buf, 0, BUF_SIZE);
memset(&ricb, 0, sizeof(ricb));
/* Initialize the default RI control block in the kernel */
if (syscall(__NR_s390_runtime_instr, 1, NULL) < 0) {
if (errno == EOPNOTSUPP) {
test_daemon();
test_waitsig();
skip("RI not supported");
pass();
return 0;
}
fail("Fail with error %d", errno);
return -1;
}
/* Set buffer for RI */
ricb.rca = ricb.roa = (unsigned long) buf;
ricb.rla = (unsigned long) buf + BUF_SIZE;
mric(&ricb);
/* Enable RI - afterwards the PSW will have RI bit set */
rion();
psw_mask = extract_psw();
/* Verify that the RI bit is set in the PSW */
if (!(psw_mask & PSW_MASK_RI)) {
fail("Failed to enable RI");
return -1;
}
/* Collect RI records until we hit buffer-full condition */
while (ricb.rca < ricb.rla + 1) {
for (i = 0; i < 10000; i++)
asm volatile("" : : : "memory");
rioff();
stric(&ricb);
rion();
}
/* Disable RI */
rioff();
/* Save the current RI control block */
stric(&ricb);
ricb_check = ricb;
/* Re-enable RI for checkpoint */
rion();
/* Do C/R now */
test_daemon();
test_waitsig();
/* Verify that the RI bit is set in the PSW */
psw_mask = extract_psw();
if (!(psw_mask & PSW_MASK_RI)) {
fail("RI bit in PSW not set");
return -1;
}
/*
* Verify that the RI block has been restored correctly
* and the buffer is unchanged
*/
rioff();
stric(&ricb);
for (i = 0; i < 8; i++) {
if (ricb_ptr[i] == ricb_check_ptr[i])
continue;
/* Skip sf field because its value may change */
if (i == 6)
continue;
fail("%d:Got %016lx expected %016lx",
i, ricb_ptr[i], ricb_check_ptr[i]);
return -1;
}
pass();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment