Signed-off-by: Christophe Lombard <clomb...@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/cputable.h | 4 +++-
arch/powerpc/include/asm/emulated_ops.h | 2 ++
arch/powerpc/include/asm/ppc-opcode.h | 4 ++++
arch/powerpc/include/asm/processor.h | 1 +
arch/powerpc/kernel/process.c | 8 ++++++++
arch/powerpc/kernel/traps.c | 21 +++++++++++++++++++++
6 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/cputable.h
b/arch/powerpc/include/asm/cputable.h
index d02ad93..706f668 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -215,6 +215,7 @@ enum {
#define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000)
#define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000)
#define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000)
+#define CPU_FTR_TIDR LONG_ASM_CONST(0x8000000000000000)
#ifndef __ASSEMBLY__
@@ -474,7 +475,8 @@ enum {
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
- CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300)
+ CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
+ CPU_FTR_TIDR)
#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
(~CPU_FTR_SAO))
#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
diff --git a/arch/powerpc/include/asm/emulated_ops.h
b/arch/powerpc/include/asm/emulated_ops.h
index f00e10e..e83ad42 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -54,6 +54,8 @@ extern struct ppc_emulated {
#ifdef CONFIG_PPC64
struct ppc_emulated_entry mfdscr;
struct ppc_emulated_entry mtdscr;
+ struct ppc_emulated_entry mftidr;
+ struct ppc_emulated_entry mttidr;
struct ppc_emulated_entry lq_stq;
#endif
} ppc_emulated;
diff --git a/arch/powerpc/include/asm/ppc-opcode.h
b/arch/powerpc/include/asm/ppc-opcode.h
index fa9ebae..3ebc446 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -241,6 +241,10 @@
#define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1ffffe
#define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6
#define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1ffffe
+#define PPC_INST_MFSPR_TIDR 0x7d2452a6
+#define PPC_INST_MFSPR_TIDR_MASK 0xfd2ffffe
+#define PPC_INST_MTSPR_TIDR 0x7d2453a6
+#define PPC_INST_MTSPR_TIDR_MASK 0xfd2ffffe
#define PPC_INST_MFVSRD 0x7c000066
#define PPC_INST_MTVSRD 0x7c000166
#define PPC_INST_SLBFEE 0x7c0007a7
diff --git a/arch/powerpc/include/asm/processor.h
b/arch/powerpc/include/asm/processor.h
index fab7ff8..58cc212 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -329,6 +329,7 @@ struct thread_struct {
*/
int dscr_inherit;
unsigned long ppr; /* used to save/restore SMT priority */
+ unsigned long tidr;
#endif
#ifdef CONFIG_PPC_BOOK3S_64
unsigned long tar;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 9f3e2c9..f06ea10 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1084,6 +1084,9 @@ static inline void save_sprs(struct thread_struct *t)
if (cpu_has_feature(CPU_FTR_DSCR))
t->dscr = mfspr(SPRN_DSCR);
+ if (cpu_has_feature(CPU_FTR_TIDR))
+ t->tidr = mfspr(SPRN_TIDR);
+
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
t->bescr = mfspr(SPRN_BESCR);
t->ebbhr = mfspr(SPRN_EBBHR);
@@ -1120,6 +1123,11 @@ static inline void restore_sprs(struct thread_struct
*old_thread,
mtspr(SPRN_DSCR, dscr);
}
+ if (cpu_has_feature(CPU_FTR_TIDR)) {
+ if (old_thread->tidr != new_thread->tidr)
+ mtspr(SPRN_TIDR, new_thread->tidr);
+ }
+
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
if (old_thread->bescr != new_thread->bescr)
mtspr(SPRN_BESCR, new_thread->bescr);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bfcfd9e..b829de7 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1141,6 +1141,25 @@ static int emulate_instruction(struct pt_regs *regs)
mtspr(SPRN_DSCR, current->thread.dscr);
return 0;
}
+ /* Emulate the mfspr rD, TIDR. */
+ if (((instword & PPC_INST_MFSPR_TIDR_MASK) ==
+ PPC_INST_MFSPR_TIDR) &&
+ cpu_has_feature(CPU_FTR_TIDR)) {
+ PPC_WARN_EMULATED(mftidr, regs);
+ rd = (instword >> 21) & 0x1f;
+ regs->gpr[rd] = mfspr(SPRN_TIDR);
+ return 0;
+ }
+ /* Emulate the mtspr TIDR, rD. */
+ if (((instword & PPC_INST_MTSPR_TIDR_MASK) ==
+ PPC_INST_MTSPR_TIDR) &&
+ cpu_has_feature(CPU_FTR_TIDR)) {
+ PPC_WARN_EMULATED(mttidr, regs);
+ rd = (instword >> 21) & 0x1f;
+ current->thread.tidr = regs->gpr[rd];
+ mtspr(SPRN_TIDR, regs->gpr[rd]);
+ return 0;
+ }
#endif
return -EINVAL;
@@ -2036,6 +2055,8 @@ struct ppc_emulated ppc_emulated = {
#ifdef CONFIG_PPC64
WARN_EMULATED_SETUP(mfdscr),
WARN_EMULATED_SETUP(mtdscr),
+ WARN_EMULATED_SETUP(mftidr),
+ WARN_EMULATED_SETUP(mttidr),
WARN_EMULATED_SETUP(lq_stq),
#endif
};