extern struct vdso_data *vdso_data;
 
+void vdso_alloc_boot_cpu(struct lowcore *lowcore);
 int vdso_alloc_per_cpu(struct lowcore *lowcore);
 void vdso_free_per_cpu(struct lowcore *lowcore);
 
 
                if (MACHINE_HAS_GS)
                        lc->mcesad |= bits;
        }
-       lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
+       vdso_alloc_boot_cpu(lc);
        lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
        lc->async_enter_timer = S390_lowcore.async_enter_timer;
        lc->exit_timer = S390_lowcore.exit_timer;
 
  */
 #define SEGMENT_ORDER  2
 
+/*
+ * The initial vdso_data structure for the boot CPU. Eventually
+ * it is replaced with a properly allocated structure in vdso_init.
+ * This is necessary because a valid S390_lowcore.vdso_per_cpu_data
+ * pointer is required to be able to return from an interrupt or
+ * program check. See the exit paths in entry.S.
+ */
+struct vdso_data boot_vdso_data __initdata;
+
+void __init vdso_alloc_boot_cpu(struct lowcore *lowcore)
+{
+       lowcore->vdso_per_cpu_data = (unsigned long) &boot_vdso_data;
+}
+
 int vdso_alloc_per_cpu(struct lowcore *lowcore)
 {
        unsigned long segment_table, page_table, page_frame;