summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/char/zcore.c70
1 files changed, 54 insertions, 16 deletions
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index c839a1593b8f..e0c87a83eb34 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -28,6 +28,7 @@
#include <asm/processor.h>
#include <asm/irqflags.h>
#include <asm/checksum.h>
+#include <asm/os_info.h>
#include <asm/switch_to.h>
#include "sclp.h"
@@ -151,6 +152,9 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
static int __init init_cpu_info(enum arch_id arch)
{
struct save_area_ext *sa_ext;
+ struct _lowcore *lc;
+ void *ptr;
+ int i;
/* get info for boot cpu from lowcore, stored in the HSA */
@@ -162,8 +166,18 @@ static int __init init_cpu_info(enum arch_id arch)
TRACE("could not copy from HSA\n");
return -EIO;
}
- if (MACHINE_HAS_VX)
- save_vx_regs_safe(sa_ext->vx_regs);
+ if (!MACHINE_HAS_VX)
+ return 0;
+
+ save_vx_regs_safe(sa_ext->vx_regs);
+ /* Get address of the vector register save area for each CPU */
+ for (i = 0; i < dump_save_areas.count; i++) {
+ sa_ext = dump_save_areas.areas[i];
+ lc = (struct _lowcore *)(unsigned long) sa_ext->sa.pref_reg;
+ ptr = &lc->vector_save_area_addr;
+ copy_from_oldmem(&sa_ext->vx_sa_addr, ptr,
+ sizeof(sa_ext->vx_sa_addr));
+ }
return 0;
}
@@ -245,6 +259,8 @@ static int copy_lc(void __user *buf, void *sa, int sa_off, int len)
*/
static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
{
+ struct save_area_ext *sa_ext;
+ struct save_area *sa;
unsigned long end;
int i;
@@ -255,26 +271,48 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
for (i = 0; i < dump_save_areas.count; i++) {
unsigned long cp_start, cp_end; /* copy range */
unsigned long sa_start, sa_end; /* save area range */
- unsigned long prefix;
unsigned long sa_off, len, buf_off;
- struct save_area *save_area = &dump_save_areas.areas[i]->sa;
- prefix = save_area->pref_reg;
- sa_start = prefix + sys_info.sa_base;
- sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
+ sa_ext = dump_save_areas.areas[i];
+ sa = &sa_ext->sa;
+
+ /* Copy the 512 bytes lowcore save area 0x1200 - 0x1400 */
+ sa_start = sa->pref_reg + sys_info.sa_base;
+ sa_end = sa_start + sys_info.sa_size;
+
+ if (end >= sa_start && start < sa_end) {
+ cp_start = max(start, sa_start);
+ cp_end = min(end, sa_end);
+ buf_off = cp_start - start;
+ sa_off = cp_start - sa_start;
+ len = cp_end - cp_start;
- if ((end < sa_start) || (start > sa_end))
+ TRACE("copy_lc: %lx-%lx\n", cp_start, cp_end);
+ if (copy_lc(buf + buf_off, sa, sa_off, len))
+ return -EFAULT;
+ }
+
+ if (!MACHINE_HAS_VX)
continue;
- cp_start = max(start, sa_start);
- cp_end = min(end, sa_end);
- buf_off = cp_start - start;
- sa_off = cp_start - sa_start;
- len = cp_end - cp_start;
+ /* Copy the 512 bytes vector save area */
+ sa_start = sa_ext->vx_sa_addr & -1024UL;
+ sa_end = sa_start + 512;
- TRACE("copy_lc for: %lx\n", start);
- if (copy_lc(buf + buf_off, save_area, sa_off, len))
- return -EFAULT;
+ if (end >= sa_start && start < sa_end) {
+ cp_start = max(start, sa_start);
+ cp_end = min(end, sa_end);
+
+ buf_off = cp_start - start;
+ sa_off = cp_start - sa_start;
+ len = cp_end - cp_start;
+
+ TRACE("copy vxrs: %lx-%lx\n", cp_start, cp_end);
+ if (copy_to_user(buf + buf_off,
+ (void *) &sa_ext->vx_regs + sa_off,
+ len))
+ return -EFAULT;
+ }
}
return 0;
}