These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / powerpc / kernel / traps.c
index 19e4744..37de90f 100644 (file)
@@ -297,6 +297,8 @@ long machine_check_early(struct pt_regs *regs)
 
        __this_cpu_inc(irq_stat.mce_exceptions);
 
+       add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
+
        if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
                handled = cur_cpu_spec->machine_check_early(regs);
        return handled;
@@ -1377,6 +1379,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
        };
        char *facility = "unknown";
        u64 value;
+       u32 instword, rd;
        u8 status;
        bool hv;
 
@@ -1388,12 +1391,46 @@ void facility_unavailable_exception(struct pt_regs *regs)
 
        status = value >> 56;
        if (status == FSCR_DSCR_LG) {
-               /* User is acessing the DSCR.  Set the inherit bit and allow
-                * the user to set it directly in future by setting via the
-                * FSCR DSCR bit.  We always leave HFSCR DSCR set.
+               /*
+                * User is accessing the DSCR register using the problem
+                * state only SPR number (0x03) either through a mfspr or
+                * a mtspr instruction. If it is a write attempt through
+                * a mtspr, then we set the inherit bit. This also allows
+                * the user to write or read the register directly in the
+                * future by setting via the FSCR DSCR bit. But in case it
+                * is a read DSCR attempt through a mfspr instruction, we
+                * just emulate the instruction instead. This code path will
+                * always emulate all the mfspr instructions till the user
+                * has attempted atleast one mtspr instruction. This way it
+                * preserves the same behaviour when the user is accessing
+                * the DSCR through privilege level only SPR number (0x11)
+                * which is emulated through illegal instruction exception.
+                * We always leave HFSCR DSCR set.
                 */
-               current->thread.dscr_inherit = 1;
-               mtspr(SPRN_FSCR, value | FSCR_DSCR);
+               if (get_user(instword, (u32 __user *)(regs->nip))) {
+                       pr_err("Failed to fetch the user instruction\n");
+                       return;
+               }
+
+               /* Write into DSCR (mtspr 0x03, RS) */
+               if ((instword & PPC_INST_MTSPR_DSCR_USER_MASK)
+                               == PPC_INST_MTSPR_DSCR_USER) {
+                       rd = (instword >> 21) & 0x1f;
+                       current->thread.dscr = regs->gpr[rd];
+                       current->thread.dscr_inherit = 1;
+                       mtspr(SPRN_FSCR, value | FSCR_DSCR);
+               }
+
+               /* Read from DSCR (mfspr RT, 0x03) */
+               if ((instword & PPC_INST_MFSPR_DSCR_USER_MASK)
+                               == PPC_INST_MFSPR_DSCR_USER) {
+                       if (emulate_instruction(regs)) {
+                               pr_err("DSCR based mfspr emulation failed\n");
+                               return;
+                       }
+                       regs->nip += 4;
+                       emulate_single_step(regs);
+               }
                return;
        }