#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"
 
 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 */
 
                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;
 }
 
  */
 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;
 
        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;
 }