Skip to content

Commit c1fe190

Browse files
mikeympe
authored andcommitted
powerpc: Add force enable of DAWR on P9 option
This adds a flag so that the DAWR can be enabled on P9 via: echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous The DAWR was previously force disabled on POWER9 in: 9654153 powerpc: Disable DAWR in the base POWER9 CPU features Also see Documentation/powerpc/DAWR-POWER9.txt This is a dangerous setting, USE AT YOUR OWN RISK. Some users may not care about a bad user crashing their box (ie. single user/desktop systems) and really want the DAWR. This allows them to force enable DAWR. This flag can also be used to disable DAWR access. Once this is cleared, all DAWR access should be cleared immediately and your machine once again safe from crashing. Userspace may get confused by toggling this. If DAWR is force enabled/disabled between getting the number of breakpoints (via PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an inconsistent view of what's available. Similarly for guests. For the DAWR to be enabled in a KVM guest, the DAWR needs to be force enabled in the host AND the guest. For this reason, this won't work on POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the dawr_enable_dangerous file will fail if the hypervisor doesn't support writing the DAWR. To double check the DAWR is working, run this kernel selftest: tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c Any errors/failures/skips mean something is wrong. Signed-off-by: Michael Neuling <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 88ec6b9 commit c1fe190

File tree

7 files changed

+123
-17
lines changed

7 files changed

+123
-17
lines changed

Documentation/powerpc/DAWR-POWER9.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,35 @@ POWER9. Loads and stores to the watchpoint locations will not be
5656
trapped in GDB. The watchpoint is remembered, so if the guest is
5757
migrated back to the POWER8 host, it will start working again.
5858

59+
Force enabling the DAWR
60+
=============================
61+
Kernels (since ~v5.2) have an option to force enable the DAWR via:
62+
63+
echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
64+
65+
This enables the DAWR even on POWER9.
66+
67+
This is a dangerous setting, USE AT YOUR OWN RISK.
68+
69+
Some users may not care about a bad user crashing their box
70+
(ie. single user/desktop systems) and really want the DAWR. This
71+
allows them to force enable DAWR.
72+
73+
This flag can also be used to disable DAWR access. Once this is
74+
cleared, all DAWR access should be cleared immediately and your
75+
machine once again safe from crashing.
76+
77+
Userspace may get confused by toggling this. If DAWR is force
78+
enabled/disabled between getting the number of breakpoints (via
79+
PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an
80+
inconsistent view of what's available. Similarly for guests.
81+
82+
For the DAWR to be enabled in a KVM guest, the DAWR needs to be force
83+
enabled in the host AND the guest. For this reason, this won't work on
84+
POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the
85+
dawr_enable_dangerous file will fail if the hypervisor doesn't support
86+
writing the DAWR.
87+
88+
To double check the DAWR is working, run this kernel selftest:
89+
tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
90+
Any errors/failures/skips mean something is wrong.

arch/powerpc/include/asm/hw_breakpoint.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,18 @@ static inline void hw_breakpoint_disable(void)
9090
extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
9191
int hw_breakpoint_handler(struct die_args *args);
9292

93+
extern int set_dawr(struct arch_hw_breakpoint *brk);
94+
extern bool dawr_force_enable;
95+
static inline bool dawr_enabled(void)
96+
{
97+
return dawr_force_enable;
98+
}
99+
93100
#else /* CONFIG_HAVE_HW_BREAKPOINT */
94101
static inline void hw_breakpoint_disable(void) { }
95102
static inline void thread_change_pc(struct task_struct *tsk,
96103
struct pt_regs *regs) { }
104+
static inline bool dawr_enabled(void) { return false; }
97105
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
98106
#endif /* __KERNEL__ */
99107
#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */

arch/powerpc/kernel/hw_breakpoint.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@
2929
#include <linux/kernel.h>
3030
#include <linux/sched.h>
3131
#include <linux/smp.h>
32+
#include <linux/debugfs.h>
33+
#include <linux/init.h>
3234

3335
#include <asm/hw_breakpoint.h>
3436
#include <asm/processor.h>
3537
#include <asm/sstep.h>
3638
#include <asm/debug.h>
39+
#include <asm/debugfs.h>
40+
#include <asm/hvcall.h>
3741
#include <linux/uaccess.h>
3842

3943
/*
@@ -174,7 +178,7 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
174178
if (!ppc_breakpoint_available())
175179
return -ENODEV;
176180
length_max = 8; /* DABR */
177-
if (cpu_has_feature(CPU_FTR_DAWR)) {
181+
if (dawr_enabled()) {
178182
length_max = 512 ; /* 64 doublewords */
179183
/* DAWR region can't cross 512 boundary */
180184
if ((attr->bp_addr >> 9) !=
@@ -376,3 +380,59 @@ void hw_breakpoint_pmu_read(struct perf_event *bp)
376380
{
377381
/* TODO */
378382
}
383+
384+
bool dawr_force_enable;
385+
EXPORT_SYMBOL_GPL(dawr_force_enable);
386+
387+
static ssize_t dawr_write_file_bool(struct file *file,
388+
const char __user *user_buf,
389+
size_t count, loff_t *ppos)
390+
{
391+
struct arch_hw_breakpoint null_brk = {0, 0, 0};
392+
size_t rc;
393+
394+
/* Send error to user if they hypervisor won't allow us to write DAWR */
395+
if ((!dawr_force_enable) &&
396+
(firmware_has_feature(FW_FEATURE_LPAR)) &&
397+
(set_dawr(&null_brk) != H_SUCCESS))
398+
return -1;
399+
400+
rc = debugfs_write_file_bool(file, user_buf, count, ppos);
401+
if (rc)
402+
return rc;
403+
404+
/* If we are clearing, make sure all CPUs have the DAWR cleared */
405+
if (!dawr_force_enable)
406+
smp_call_function((smp_call_func_t)set_dawr, &null_brk, 0);
407+
408+
return rc;
409+
}
410+
411+
static const struct file_operations dawr_enable_fops = {
412+
.read = debugfs_read_file_bool,
413+
.write = dawr_write_file_bool,
414+
.open = simple_open,
415+
.llseek = default_llseek,
416+
};
417+
418+
static int __init dawr_force_setup(void)
419+
{
420+
dawr_force_enable = false;
421+
422+
if (cpu_has_feature(CPU_FTR_DAWR)) {
423+
/* Don't setup sysfs file for user control on P8 */
424+
dawr_force_enable = true;
425+
return 0;
426+
}
427+
428+
if (PVR_VER(mfspr(SPRN_PVR)) == PVR_POWER9) {
429+
/* Turn DAWR off by default, but allow admin to turn it on */
430+
dawr_force_enable = false;
431+
debugfs_create_file_unsafe("dawr_enable_dangerous", 0600,
432+
powerpc_debugfs_root,
433+
&dawr_force_enable,
434+
&dawr_enable_fops);
435+
}
436+
return 0;
437+
}
438+
arch_initcall(dawr_force_setup);

arch/powerpc/kernel/process.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include <asm/cpu_has_feature.h>
6868
#include <asm/asm-prototypes.h>
6969
#include <asm/stacktrace.h>
70+
#include <asm/hw_breakpoint.h>
7071

7172
#include <linux/kprobes.h>
7273
#include <linux/kdebug.h>
@@ -784,7 +785,7 @@ static inline int set_dabr(struct arch_hw_breakpoint *brk)
784785
return __set_dabr(dabr, dabrx);
785786
}
786787

787-
static inline int set_dawr(struct arch_hw_breakpoint *brk)
788+
int set_dawr(struct arch_hw_breakpoint *brk)
788789
{
789790
unsigned long dawr, dawrx, mrd;
790791

@@ -816,7 +817,7 @@ void __set_breakpoint(struct arch_hw_breakpoint *brk)
816817
{
817818
memcpy(this_cpu_ptr(&current_brk), brk, sizeof(*brk));
818819

819-
if (cpu_has_feature(CPU_FTR_DAWR))
820+
if (dawr_enabled())
820821
// Power8 or later
821822
set_dawr(brk);
822823
else if (!cpu_has_feature(CPU_FTR_ARCH_207S))
@@ -830,8 +831,8 @@ void __set_breakpoint(struct arch_hw_breakpoint *brk)
830831
/* Check if we have DAWR or DABR hardware */
831832
bool ppc_breakpoint_available(void)
832833
{
833-
if (cpu_has_feature(CPU_FTR_DAWR))
834-
return true; /* POWER8 DAWR */
834+
if (dawr_enabled())
835+
return true; /* POWER8 DAWR or POWER9 forced DAWR */
835836
if (cpu_has_feature(CPU_FTR_ARCH_207S))
836837
return false; /* POWER9 with DAWR disabled */
837838
/* DABR: Everything but POWER8 and POWER9 */

arch/powerpc/kernel/ptrace.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <asm/tm.h>
4444
#include <asm/asm-prototypes.h>
4545
#include <asm/debug.h>
46+
#include <asm/hw_breakpoint.h>
4647

4748
#define CREATE_TRACE_POINTS
4849
#include <trace/events/syscalls.h>
@@ -3088,7 +3089,7 @@ long arch_ptrace(struct task_struct *child, long request,
30883089
dbginfo.sizeof_condition = 0;
30893090
#ifdef CONFIG_HAVE_HW_BREAKPOINT
30903091
dbginfo.features = PPC_DEBUG_FEATURE_DATA_BP_RANGE;
3091-
if (cpu_has_feature(CPU_FTR_DAWR))
3092+
if (dawr_enabled())
30923093
dbginfo.features |= PPC_DEBUG_FEATURE_DATA_BP_DAWR;
30933094
#else
30943095
dbginfo.features = 0;

arch/powerpc/kvm/book3s_hv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include <asm/opal.h>
7575
#include <asm/xics.h>
7676
#include <asm/xive.h>
77+
#include <asm/hw_breakpoint.h>
7778

7879
#include "book3s.h"
7980

@@ -3374,7 +3375,7 @@ static int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit,
33743375
mtspr(SPRN_PURR, vcpu->arch.purr);
33753376
mtspr(SPRN_SPURR, vcpu->arch.spurr);
33763377

3377-
if (cpu_has_feature(CPU_FTR_DAWR)) {
3378+
if (dawr_enabled()) {
33783379
mtspr(SPRN_DAWR, vcpu->arch.dawr);
33793380
mtspr(SPRN_DAWRX, vcpu->arch.dawrx);
33803381
}

arch/powerpc/kvm/book3s_hv_rmhandlers.S

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -822,18 +822,21 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
822822
mtspr SPRN_IAMR, r5
823823
mtspr SPRN_PSPB, r6
824824
mtspr SPRN_FSCR, r7
825-
ld r5, VCPU_DAWR(r4)
826-
ld r6, VCPU_DAWRX(r4)
827-
ld r7, VCPU_CIABR(r4)
828-
ld r8, VCPU_TAR(r4)
829825
/*
830826
* Handle broken DAWR case by not writing it. This means we
831827
* can still store the DAWR register for migration.
832828
*/
833-
BEGIN_FTR_SECTION
829+
LOAD_REG_ADDR(r5, dawr_force_enable)
830+
lbz r5, 0(r5)
831+
cmpdi r5, 0
832+
beq 1f
833+
ld r5, VCPU_DAWR(r4)
834+
ld r6, VCPU_DAWRX(r4)
834835
mtspr SPRN_DAWR, r5
835836
mtspr SPRN_DAWRX, r6
836-
END_FTR_SECTION_IFSET(CPU_FTR_DAWR)
837+
1:
838+
ld r7, VCPU_CIABR(r4)
839+
ld r8, VCPU_TAR(r4)
837840
mtspr SPRN_CIABR, r7
838841
mtspr SPRN_TAR, r8
839842
ld r5, VCPU_IC(r4)
@@ -2513,11 +2516,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
25132516
blr
25142517

25152518
2:
2516-
BEGIN_FTR_SECTION
2517-
/* POWER9 with disabled DAWR */
2519+
LOAD_REG_ADDR(r11, dawr_force_enable)
2520+
lbz r11, 0(r11)
2521+
cmpdi r11, 0
25182522
li r3, H_HARDWARE
2519-
blr
2520-
END_FTR_SECTION_IFCLR(CPU_FTR_DAWR)
2523+
beqlr
25212524
/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
25222525
rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
25232526
rlwimi r5, r4, 2, DAWRX_WT

0 commit comments

Comments
 (0)