#ifdef CONFIG_VSX
        struct ppc_emulated_entry vsx;
 #endif
+#ifdef CONFIG_PPC64
+       struct ppc_emulated_entry mfdscr;
+       struct ppc_emulated_entry mtdscr;
+#endif
 } ppc_emulated;
 
 extern u32 ppc_warn_emulated;
 
 #define PPC_INST_RFCI                  0x4c000066
 #define PPC_INST_RFDI                  0x4c00004e
 #define PPC_INST_RFMCI                 0x4c00004c
+#define PPC_INST_MFSPR_DSCR            0x7c1102a6
+#define PPC_INST_MFSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_MTSPR_DSCR            0x7c1103a6
+#define PPC_INST_MTSPR_DSCR_MASK       0xfc1fffff
 
 #define PPC_INST_STRING                        0x7c00042a
 #define PPC_INST_STRING_MASK           0xfc0007fe
 
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        void*           kvm_shadow_vcpu; /* KVM internal data */
 #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
+#ifdef CONFIG_PPC64
+       unsigned long   dscr;
+       int             dscr_inherit;
+#endif
 };
 
 #define ARCH_MIN_TASKALIGN 16
 
        DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
        DEFINE(SIGSEGV, SIGSEGV);
        DEFINE(NMI_MASK, NMI_MASK);
+       DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
 #else
        DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
 #endif /* CONFIG_PPC64 */
 
        std     r24,THREAD_VRSAVE(r3)
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
+       mfspr   r25,SPRN_DSCR
+       std     r25,THREAD_DSCR(r3)
+END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
+#endif
        and.    r0,r0,r22
        beq+    1f
        andc    r22,r22,r0
        mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
+       ld      r0,THREAD_DSCR(r4)
+       cmpd    r0,r25
+       beq     1f
+       mtspr   SPRN_DSCR,r0
+1:     
+END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
+#endif
 
        /* r3-r13 are destroyed -- Cort */
        REST_8GPRS(14, r1)
 
 /*
  * Copy a thread..
  */
+extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
+
 int copy_thread(unsigned long clone_flags, unsigned long usp,
                unsigned long unused, struct task_struct *p,
                struct pt_regs *regs)
                p->thread.ksp_vsid = sp_vsid;
        }
 #endif /* CONFIG_PPC_STD_MMU_64 */
+#ifdef CONFIG_PPC64 
+       if (cpu_has_feature(CPU_FTR_DSCR)) {
+               if (current->thread.dscr_inherit) {
+                       p->thread.dscr_inherit = 1;
+                       p->thread.dscr = current->thread.dscr;
+               } else if (0 != dscr_default) {
+                       p->thread.dscr_inherit = 1;
+                       p->thread.dscr = dscr_default;
+               } else {
+                       p->thread.dscr_inherit = 0;
+                       p->thread.dscr = 0;
+               }
+       }
+#endif
 
        /*
         * The PPC64 ABI makes use of a TOC to contain function 
 
 static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
 static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
 static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
+
+unsigned long dscr_default = 0;
+EXPORT_SYMBOL(dscr_default);
+
+static ssize_t show_dscr_default(struct sysdev_class *class,
+               struct sysdev_class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lx\n", dscr_default);
+}
+
+static ssize_t __used store_dscr_default(struct sysdev_class *class,
+               struct sysdev_class_attribute *attr, const char *buf,
+               size_t count)
+{
+       unsigned long val;
+       int ret = 0;
+       
+       ret = sscanf(buf, "%lx", &val);
+       if (ret != 1)
+               return -EINVAL;
+       dscr_default = val;
+
+       return count;
+}
+
+static SYSDEV_CLASS_ATTR(dscr_default, 0600,
+               show_dscr_default, store_dscr_default);
+
+static void sysfs_create_dscr_default(void)
+{
+       int err = 0;
+       if (cpu_has_feature(CPU_FTR_DSCR))
+               err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+                       &attr_dscr_default.attr);
+}
 #endif /* CONFIG_PPC64 */
 
 #ifdef HAS_PPC_PMC_PA6T
                if (cpu_online(cpu))
                        register_cpu_online(cpu);
        }
+#ifdef CONFIG_PPC64
+       sysfs_create_dscr_default();
+#endif /* CONFIG_PPC64 */
 
        return 0;
 }
 
                return emulate_isel(regs, instword);
        }
 
+#ifdef CONFIG_PPC64
+       /* Emulate the mfspr rD, DSCR. */
+       if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) &&
+                       cpu_has_feature(CPU_FTR_DSCR)) {
+               PPC_WARN_EMULATED(mfdscr, regs);
+               rd = (instword >> 21) & 0x1f;
+               regs->gpr[rd] = mfspr(SPRN_DSCR);
+               return 0;
+       }
+       /* Emulate the mtspr DSCR, rD. */
+       if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) &&
+                       cpu_has_feature(CPU_FTR_DSCR)) {
+               PPC_WARN_EMULATED(mtdscr, regs);
+               rd = (instword >> 21) & 0x1f;
+               mtspr(SPRN_DSCR, regs->gpr[rd]);
+               current->thread.dscr_inherit = 1;
+               return 0;
+       }
+#endif
+
        return -EINVAL;
 }
 
 #ifdef CONFIG_VSX
        WARN_EMULATED_SETUP(vsx),
 #endif
+#ifdef CONFIG_PPC64
+       WARN_EMULATED_SETUP(mfdscr),
+       WARN_EMULATED_SETUP(mtdscr),
+#endif
 };
 
 u32 ppc_warn_emulated;