aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorJack Miller <jack@codezen.org>2016-06-08 22:31:09 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-06-21 01:30:50 -0400
commitbd3ea317fddfd0f2044f94bed294b90c4bc8e69e (patch)
tree051da254ea09ce51759123472fbcc52002c0ad53 /arch/powerpc
parentb57bd2de8c6c9aa03f1b899edd6f5582cc8b5b08 (diff)
powerpc: Load Monitor Register Support
This enables new registers, LMRR and LMSER, that can trigger an EBB in userspace code when a monitored load (via the new ldmx instruction) loads memory from a monitored space. This facility is controlled by a new FSCR bit, LM. This patch disables the FSCR LM control bit on task init and enables that bit when a load monitor facility unavailable exception is taken for using it. On context switch, this bit is then used to determine whether the two relevant registers are saved and restored. This is done lazily for performance reasons. Signed-off-by: Jack Miller <jack@codezen.org> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/processor.h2
-rw-r--r--arch/powerpc/include/asm/reg.h5
-rw-r--r--arch/powerpc/kernel/process.c18
-rw-r--r--arch/powerpc/kernel/traps.c9
4 files changed, 34 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index f6b1a5f51d05..b5925d5d4985 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -314,6 +314,8 @@ struct thread_struct {
314 unsigned long mmcr2; 314 unsigned long mmcr2;
315 unsigned mmcr0; 315 unsigned mmcr0;
316 unsigned used_ebb; 316 unsigned used_ebb;
317 unsigned long lmrr;
318 unsigned long lmser;
317#endif 319#endif
318}; 320};
319 321
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index a0948f40bc7b..ce44fe27f48f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -282,6 +282,8 @@
282#define SPRN_HRMOR 0x139 /* Real mode offset register */ 282#define SPRN_HRMOR 0x139 /* Real mode offset register */
283#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ 283#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */
284#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ 284#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
285#define SPRN_LMRR 0x32D /* Load Monitor Region Register */
286#define SPRN_LMSER 0x32E /* Load Monitor Section Enable Register */
285#define SPRN_IC 0x350 /* Virtual Instruction Count */ 287#define SPRN_IC 0x350 /* Virtual Instruction Count */
286#define SPRN_VTB 0x351 /* Virtual Time Base */ 288#define SPRN_VTB 0x351 /* Virtual Time Base */
287#define SPRN_LDBAR 0x352 /* LD Base Address Register */ 289#define SPRN_LDBAR 0x352 /* LD Base Address Register */
@@ -291,6 +293,7 @@
291#define SPRN_PMCR 0x374 /* Power Management Control Register */ 293#define SPRN_PMCR 0x374 /* Power Management Control Register */
292 294
293/* HFSCR and FSCR bit numbers are the same */ 295/* HFSCR and FSCR bit numbers are the same */
296#define FSCR_LM_LG 11 /* Enable Load Monitor Registers */
294#define FSCR_TAR_LG 8 /* Enable Target Address Register */ 297#define FSCR_TAR_LG 8 /* Enable Target Address Register */
295#define FSCR_EBB_LG 7 /* Enable Event Based Branching */ 298#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
296#define FSCR_TM_LG 5 /* Enable Transactional Memory */ 299#define FSCR_TM_LG 5 /* Enable Transactional Memory */
@@ -300,10 +303,12 @@
300#define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */ 303#define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */
301#define FSCR_FP_LG 0 /* Enable Floating Point */ 304#define FSCR_FP_LG 0 /* Enable Floating Point */
302#define SPRN_FSCR 0x099 /* Facility Status & Control Register */ 305#define SPRN_FSCR 0x099 /* Facility Status & Control Register */
306#define FSCR_LM __MASK(FSCR_LM_LG)
303#define FSCR_TAR __MASK(FSCR_TAR_LG) 307#define FSCR_TAR __MASK(FSCR_TAR_LG)
304#define FSCR_EBB __MASK(FSCR_EBB_LG) 308#define FSCR_EBB __MASK(FSCR_EBB_LG)
305#define FSCR_DSCR __MASK(FSCR_DSCR_LG) 309#define FSCR_DSCR __MASK(FSCR_DSCR_LG)
306#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */ 310#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */
311#define HFSCR_LM __MASK(FSCR_LM_LG)
307#define HFSCR_TAR __MASK(FSCR_TAR_LG) 312#define HFSCR_TAR __MASK(FSCR_TAR_LG)
308#define HFSCR_EBB __MASK(FSCR_EBB_LG) 313#define HFSCR_EBB __MASK(FSCR_EBB_LG)
309#define HFSCR_TM __MASK(FSCR_TM_LG) 314#define HFSCR_TM __MASK(FSCR_TM_LG)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6d0a831bc7d8..ddceeb96e8fb 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1017,6 +1017,14 @@ static inline void save_sprs(struct thread_struct *t)
1017 */ 1017 */
1018 t->tar = mfspr(SPRN_TAR); 1018 t->tar = mfspr(SPRN_TAR);
1019 } 1019 }
1020
1021 if (cpu_has_feature(CPU_FTR_ARCH_300)) {
1022 /* Conditionally save Load Monitor registers, if enabled */
1023 if (t->fscr & FSCR_LM) {
1024 t->lmrr = mfspr(SPRN_LMRR);
1025 t->lmser = mfspr(SPRN_LMSER);
1026 }
1027 }
1020#endif 1028#endif
1021} 1029}
1022 1030
@@ -1052,6 +1060,16 @@ static inline void restore_sprs(struct thread_struct *old_thread,
1052 if (old_thread->tar != new_thread->tar) 1060 if (old_thread->tar != new_thread->tar)
1053 mtspr(SPRN_TAR, new_thread->tar); 1061 mtspr(SPRN_TAR, new_thread->tar);
1054 } 1062 }
1063
1064 if (cpu_has_feature(CPU_FTR_ARCH_300)) {
1065 /* Conditionally restore Load Monitor registers, if enabled */
1066 if (new_thread->fscr & FSCR_LM) {
1067 if (old_thread->lmrr != new_thread->lmrr)
1068 mtspr(SPRN_LMRR, new_thread->lmrr);
1069 if (old_thread->lmser != new_thread->lmser)
1070 mtspr(SPRN_LMSER, new_thread->lmser);
1071 }
1072 }
1055#endif 1073#endif
1056} 1074}
1057 1075
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d2518c3cbf04..f7e2f2e318bd 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1377,6 +1377,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
1377 [FSCR_TM_LG] = "TM", 1377 [FSCR_TM_LG] = "TM",
1378 [FSCR_EBB_LG] = "EBB", 1378 [FSCR_EBB_LG] = "EBB",
1379 [FSCR_TAR_LG] = "TAR", 1379 [FSCR_TAR_LG] = "TAR",
1380 [FSCR_LM_LG] = "LM",
1380 }; 1381 };
1381 char *facility = "unknown"; 1382 char *facility = "unknown";
1382 u64 value; 1383 u64 value;
@@ -1434,6 +1435,14 @@ void facility_unavailable_exception(struct pt_regs *regs)
1434 emulate_single_step(regs); 1435 emulate_single_step(regs);
1435 } 1436 }
1436 return; 1437 return;
1438 } else if ((status == FSCR_LM_LG) && cpu_has_feature(CPU_FTR_ARCH_300)) {
1439 /*
1440 * This process has touched LM, so turn it on forever
1441 * for this process
1442 */
1443 current->thread.fscr |= FSCR_LM;
1444 mtspr(SPRN_FSCR, current->thread.fscr);
1445 return;
1437 } 1446 }
1438 1447
1439 if ((status < ARRAY_SIZE(facility_strings)) && 1448 if ((status < ARRAY_SIZE(facility_strings)) &&