Commit a1442104 authored by Alice Frosi's avatar Alice Frosi Committed by Andrei Vagin

s390: Add guarded-storage support

Dump and restore tasks with GS control blocks. Guarded-storage is a new
s390 feature to improve garbage collecting languages like Java.

There are two control blocks in the CPU:

 - GS control block
 - GS broadcast control block

Both control blocks have to be dumped and restored for all threads.
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 04e0bcae
...@@ -38,12 +38,18 @@ struct prfpreg { ...@@ -38,12 +38,18 @@ struct prfpreg {
}; };
#define USER_FPREGS_VXRS 0x000000001 #define USER_FPREGS_VXRS 0x000000001
/* Guarded-storage control block */
#define USER_GS_CB 0x000000002
/* Guarded-storage broadcast control block */
#define USER_GS_BC 0x000000004
typedef struct { typedef struct {
uint32_t flags; uint32_t flags;
struct prfpreg prfpreg; struct prfpreg prfpreg;
uint64_t vxrs_low[16]; uint64_t vxrs_low[16];
vector128_t vxrs_high[16]; vector128_t vxrs_high[16];
uint64_t gs_cb[4];
uint64_t gs_bc[4];
} user_fpregs_struct_t; } user_fpregs_struct_t;
typedef struct { typedef struct {
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#define NT_PRFPREG 2 #define NT_PRFPREG 2
#define NT_S390_VXRS_LOW 0x309 #define NT_S390_VXRS_LOW 0x309
#define NT_S390_VXRS_HIGH 0x30a #define NT_S390_VXRS_HIGH 0x30a
#define NT_S390_GS_CB 0x30b
#define NT_S390_GS_BC 0x30c
/* /*
* Print general purpose and access registers * Print general purpose and access registers
...@@ -40,17 +42,12 @@ static void print_user_regs_struct(const char *msg, int pid, ...@@ -40,17 +42,12 @@ static void print_user_regs_struct(const char *msg, int pid,
} }
/* /*
* Print floating point and vector registers * Print vector registers
*/ */
static void print_user_fpregs_struct(const char *msg, int pid, static void print_vxrs(user_fpregs_struct_t *fpregs)
user_fpregs_struct_t *fpregs)
{ {
int i; int i;
pr_debug("%s: FP registers for pid=%d\n", msg, pid);
pr_debug(" fpc %08x\n", fpregs->prfpreg.fpc);
for (i = 0; i < 16; i++)
pr_debug(" f%02d %016lx\n", i, fpregs->prfpreg.fprs[i]);
if (!(fpregs->flags & USER_FPREGS_VXRS)) { if (!(fpregs->flags & USER_FPREGS_VXRS)) {
pr_debug(" No VXRS\n"); pr_debug(" No VXRS\n");
return; return;
...@@ -63,6 +60,53 @@ static void print_user_fpregs_struct(const char *msg, int pid, ...@@ -63,6 +60,53 @@ static void print_user_fpregs_struct(const char *msg, int pid,
fpregs->vxrs_high[i].part2); fpregs->vxrs_high[i].part2);
} }
/*
* Print guarded-storage control block
*/
static void print_gs_cb(user_fpregs_struct_t *fpregs)
{
int i;
if (!(fpregs->flags & USER_GS_CB)) {
pr_debug(" No GS_CB\n");
return;
}
for (i = 0; i < 4; i++)
pr_debug(" gs_cb%02d %016lx\n", i, fpregs->gs_cb[i]);
}
/*
* Print guarded-storage broadcast control block
*/
static void print_gs_bc(user_fpregs_struct_t *fpregs)
{
int i;
if (!(fpregs->flags & USER_GS_BC)) {
pr_debug(" No GS_BC\n");
return;
}
for (i = 0; i < 4; i++)
pr_debug(" gs_bc%02d %016lx\n", i, fpregs->gs_bc[i]);
}
/*
* Print FP registers, VX registers, and guarded storage
*/
static void print_user_fpregs_struct(const char *msg, int pid,
user_fpregs_struct_t *fpregs)
{
int i;
pr_debug("%s: FP registers for pid=%d\n", msg, pid);
pr_debug(" fpc %08x\n", fpregs->prfpreg.fpc);
for (i = 0; i < 16; i++)
pr_debug(" f%02d %016lx\n", i, fpregs->prfpreg.fprs[i]);
print_vxrs(fpregs);
print_gs_cb(fpregs);
print_gs_bc(fpregs);
}
int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe,
user_regs_struct_t *regs, user_regs_struct_t *regs,
user_fpregs_struct_t *fpregs) user_fpregs_struct_t *fpregs)
...@@ -148,7 +192,47 @@ int get_vx_regs(pid_t pid, user_fpregs_struct_t *fpregs) ...@@ -148,7 +192,47 @@ int get_vx_regs(pid_t pid, user_fpregs_struct_t *fpregs)
return 0; return 0;
} }
/*
* Get guarded-storage control block
*/
int get_gs_cb(pid_t pid, user_fpregs_struct_t *fpregs)
{
struct iovec iov;
fpregs->flags &= ~(USER_GS_CB | USER_GS_BC);
iov.iov_base = &fpregs->gs_cb;
iov.iov_len = sizeof(fpregs->gs_cb);
if (ptrace(PTRACE_GETREGSET, pid, NT_S390_GS_CB, &iov) < 0) {
switch (errno) {
case EINVAL:
case ENODEV:
memset(&fpregs->gs_cb, 0, sizeof(fpregs->gs_cb));
memset(&fpregs->gs_bc, 0, sizeof(fpregs->gs_bc));
pr_debug("GS_CB not supported\n");
return 0;
case ENODATA:
pr_debug("GS_CB not set\n");
break;
default:
return -1;
}
} else {
fpregs->flags |= USER_GS_CB;
}
iov.iov_base = &fpregs->gs_bc;
iov.iov_len = sizeof(fpregs->gs_bc);
if (ptrace(PTRACE_GETREGSET, pid, NT_S390_GS_BC, &iov) < 0) {
if (errno == ENODATA) {
pr_debug("GS_BC not set\n");
return 0;
}
pr_perror("Couldn't get GS_BC\n");
return -1;
}
fpregs->flags |= USER_GS_BC;
return 0;
}
/* /*
* Prepare task registers for restart * Prepare task registers for restart
*/ */
...@@ -172,6 +256,10 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, ...@@ -172,6 +256,10 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save,
pr_perror("Couldn't get vector registers"); pr_perror("Couldn't get vector registers");
return -1; return -1;
} }
if (get_gs_cb(pid, &fpregs)) {
pr_perror("Couldn't get guarded-storage");
return -1;
}
print_user_fpregs_struct("get_task_regs", pid, &fpregs); print_user_fpregs_struct("get_task_regs", pid, &fpregs);
/* Check for system call restarting. */ /* Check for system call restarting. */
if (regs->system_call) { if (regs->system_call) {
......
This diff is collapsed.
...@@ -30,10 +30,16 @@ message user_s390_fpregs_entry { ...@@ -30,10 +30,16 @@ message user_s390_fpregs_entry {
repeated uint64 fprs = 2; repeated uint64 fprs = 2;
} }
message user_s390_gs_cb_entry {
repeated uint64 regs = 1;
}
message thread_info_s390 { message thread_info_s390 {
required uint64 clear_tid_addr = 1[(criu).hex = true]; required uint64 clear_tid_addr = 1[(criu).hex = true];
required user_s390_regs_entry gpregs = 2[(criu).hex = true]; required user_s390_regs_entry gpregs = 2[(criu).hex = true];
required user_s390_fpregs_entry fpregs = 3[(criu).hex = true]; required user_s390_fpregs_entry fpregs = 3[(criu).hex = true];
optional user_s390_vxrs_low_entry vxrs_low = 4[(criu).hex = true]; optional user_s390_vxrs_low_entry vxrs_low = 4[(criu).hex = true];
optional user_s390_vxrs_high_entry vxrs_high = 5[(criu).hex = true]; optional user_s390_vxrs_high_entry vxrs_high = 5[(criu).hex = true];
optional user_s390_gs_cb_entry gs_cb = 6[(criu).hex = true];
optional user_s390_gs_cb_entry gs_bc = 7[(criu).hex = true];
} }
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