[PATCH v2] powerpc: Fix compile issue with force DAWR
Michael Neuling
mikey at neuling.org
Tue May 14 14:47:41 AEST 2019
On Mon, 2019-05-13 at 11:08 +0200, Christophe Leroy wrote:
>
> Le 13/05/2019 à 09:17, Michael Neuling a écrit :
> > If you compile with KVM but without CONFIG_HAVE_HW_BREAKPOINT you fail
> > at linking with:
> > arch/powerpc/kvm/book3s_hv_rmhandlers.o:(.text+0x708): undefined
> > reference to `dawr_force_enable'
> >
> > This was caused by commit c1fe190c0672 ("powerpc: Add force enable of
> > DAWR on P9 option").
> >
> > This puts more of the dawr infrastructure in a new file.
>
> I think you are doing a bit more than that. I think you should explain
> that you define a new CONFIG_ option, when it is selected, etc ...
>
> The commit you are referring to is talking about P9. It looks like your
> patch covers a lot more, so it should be mentionned her I guess.
Not really. It looks like I'm doing a lot but I'm really just moving code around
to deal with the ugliness of a bunch of config options and dependencies.
> > Signed-off-by: Michael Neuling <mikey at neuling.org>
>
> You should add a Fixes: tag, ie:
>
> Fixes: c1fe190c0672 ("powerpc: Add force enable of DAWR on P9 option")
Ok
>
> > --
> > v2:
> > Fixes based on Christophe Leroy's comments:
> > - Fix commit message formatting
> > - Move more DAWR code into dawr.c
> > ---
> > arch/powerpc/Kconfig | 5 ++
> > arch/powerpc/include/asm/hw_breakpoint.h | 20 ++++---
> > arch/powerpc/kernel/Makefile | 1 +
> > arch/powerpc/kernel/dawr.c | 75 ++++++++++++++++++++++++
> > arch/powerpc/kernel/hw_breakpoint.c | 56 ------------------
> > arch/powerpc/kvm/Kconfig | 1 +
> > 6 files changed, 94 insertions(+), 64 deletions(-)
> > create mode 100644 arch/powerpc/kernel/dawr.c
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 2711aac246..f4b19e48cc 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -242,6 +242,7 @@ config PPC
> > select SYSCTL_EXCEPTION_TRACE
> > select THREAD_INFO_IN_TASK
> > select VIRT_TO_BUS if !PPC64
> > + select PPC_DAWR_FORCE_ENABLE if PPC64 || PERF
>
> What's PERF ? Did you mean PERF_EVENTS ?
>
> Then what you mean is:
> - Selected all the time for PPC64
> - Selected for PPC32 when PERF is also selected.
>
> Is that what you want ? At first I thought it was linked to P9.
This is wrong. I think we just want PPC64. PERF is a red herring.
> And ... did you read below statement ?
Clearly not :-)
>
> > #
> > # Please keep this list sorted alphabetically.
> > #
> > @@ -369,6 +370,10 @@ config PPC_ADV_DEBUG_DAC_RANGE
> > depends on PPC_ADV_DEBUG_REGS && 44x
> > default y
> >
> > +config PPC_DAWR_FORCE_ENABLE
> > + bool
> > + default y
> > +
>
> Why defaulting it to y. Then how is it set to n ?
Good point.
>
> > config ZONE_DMA
> > bool
> > default y if PPC_BOOK3E_64
> > diff --git a/arch/powerpc/include/asm/hw_breakpoint.h
> > b/arch/powerpc/include/asm/hw_breakpoint.h
> > index 0fe8c1e46b..ffbc8eab41 100644
> > --- a/arch/powerpc/include/asm/hw_breakpoint.h
> > +++ b/arch/powerpc/include/asm/hw_breakpoint.h
> > @@ -47,6 +47,8 @@ struct arch_hw_breakpoint {
> > #define HW_BRK_TYPE_PRIV_ALL (HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL |
> > \
> > HW_BRK_TYPE_HYP)
> >
> > +extern int set_dawr(struct arch_hw_breakpoint *brk);
> > +
> > #ifdef CONFIG_HAVE_HW_BREAKPOINT
> > #include <linux/kdebug.h>
> > #include <asm/reg.h>
> > @@ -90,18 +92,20 @@ static inline void hw_breakpoint_disable(void)
> > extern void thread_change_pc(struct task_struct *tsk, struct pt_regs
> > *regs);
> > int hw_breakpoint_handler(struct die_args *args);
> >
> > -extern int set_dawr(struct arch_hw_breakpoint *brk);
> > -extern bool dawr_force_enable;
> > -static inline bool dawr_enabled(void)
> > -{
> > - return dawr_force_enable;
> > -}
> > -
>
> That's a very simple function, why not keep it here (or in another .h)
> as 'static inline' ?
Sure.
> > #else /* CONFIG_HAVE_HW_BREAKPOINT */
> > static inline void hw_breakpoint_disable(void) { }
> > static inline void thread_change_pc(struct task_struct *tsk,
> > struct pt_regs *regs) { }
> > -static inline bool dawr_enabled(void) { return false; }
> > +
> > #endif /* CONFIG_HAVE_HW_BREAKPOINT */
> > +
> > +extern bool dawr_force_enable;
> > +
> > +#ifdef CONFIG_PPC_DAWR_FORCE_ENABLE
> > +extern bool dawr_enabled(void);
>
> Functions should not be 'extern'. I'm sure checkpatch --strict will tell
> you.
That's not what's currently being done in this header file. I'm keeping with
the style of that file.
> > +#else
> > +#define dawr_enabled() true
>
> true by default ?
> Previously it was false by default.
Thanks, yeah that's wrong but I need to rethink the config option to make it
CONFIG_PPC_DAWR.
This patch is far more difficult than it should be due to the mess that
CONFIG_HAVE_HW_BREAKPOINT and CONFIG_PPC_ADV_DEBUG_REGS creates in ptrace.c and
process.c. We really need to fix up
https://github.com/linuxppc/issues/issues/128
> And why a #define ? That's better to keep a static inline.
Changed.
>
> > +#endif
> > +
> > #endif /* __KERNEL__ */
> > #endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */
> > diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> > index 0ea6c4aa3a..a9c497c34f 100644
> > --- a/arch/powerpc/kernel/Makefile
> > +++ b/arch/powerpc/kernel/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_PPC64) += setup_64.o
> > sys_ppc32.o \
> > obj-$(CONFIG_VDSO32) += vdso32/
> > obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o
> > obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
> > +obj-$(CONFIG_PPC_DAWR_FORCE_ENABLE) += dawr.o
> > obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o
> > obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o
> > obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o
> > diff --git a/arch/powerpc/kernel/dawr.c b/arch/powerpc/kernel/dawr.c
> > new file mode 100644
> > index 0000000000..cf1d02fe1e
> > --- /dev/null
> > +++ b/arch/powerpc/kernel/dawr.c
> > @@ -0,0 +1,75 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +//
> > +// DAWR infrastructure
> > +//
> > +// Copyright 2019, Michael Neuling, IBM Corporation.
> > +
> > +#include <linux/types.h>
> > +#include <linux/export.h>
> > +#include <linux/fs.h>
> > +#include <linux/debugfs.h>
> > +#include <asm/debugfs.h>
> > +#include <asm/machdep.h>
> > +#include <asm/hvcall.h>
> > +
> > +bool dawr_force_enable;
> > +EXPORT_SYMBOL_GPL(dawr_force_enable);
> > +
> > +extern bool dawr_enabled(void)
>
> extern ????
oops
>
> > +{
> > + return dawr_force_enable;
> > +}
> > +EXPORT_SYMBOL_GPL(dawr_enabled);
>
> Since dawr_force_enable is also exported, I see no point in having such
> a tiny function as an exported function, was better as a 'static inline'.
Yep, changed to static inline.
> > +
> > +static ssize_t dawr_write_file_bool(struct file *file,
> > + const char __user *user_buf,
> > + size_t count, loff_t *ppos)
> > +{
> > + struct arch_hw_breakpoint null_brk = {0, 0, 0};
> > + size_t rc;
> > +
> > + /* Send error to user if they hypervisor won't allow us to write DAWR */
> > + if ((!dawr_force_enable) &&
> > + (firmware_has_feature(FW_FEATURE_LPAR)) &&
> > + (set_dawr(&null_brk) != H_SUCCESS))
>
> The above is not real clear.
> set_dabr() returns 0, H_SUCCESS is not used there.
It pseries_set_dawr() will return a hcall number.
This code hasn't changed. I'm just moving it.
>
> > + return -1;
> > +
> > + rc = debugfs_write_file_bool(file, user_buf, count, ppos);
> > + if (rc)
> > + return rc;
> > +
> > + /* If we are clearing, make sure all CPUs have the DAWR cleared */
> > + if (!dawr_force_enable)
> > + smp_call_function((smp_call_func_t)set_dawr, &null_brk, 0);
> > +
> > + return rc;
> > +}
> > +
> > +static const struct file_operations dawr_enable_fops = {
> > + .read = debugfs_read_file_bool,
> > + .write = dawr_write_file_bool,
> > + .open = simple_open,
> > + .llseek = default_llseek,
> > +};
> > +
> > +static int __init dawr_force_setup(void)
> > +{
> > + dawr_force_enable = false;
>
> The above is not needed, the BSS is zeroised at kernel startup.
>
> > +
> > + if (cpu_has_feature(CPU_FTR_DAWR)) {
> > + /* Don't setup sysfs file for user control on P8 */
> > + dawr_force_enable = true;
>
> Strange comment, word "don't" doesn't really fit with a 'true'
>
> > + return 0;
> > + }
> > +
> > + if (PVR_VER(mfspr(SPRN_PVR)) == PVR_POWER9) {
>
> You could use pvr_version_is(PVR_POWER9) instead of open codiing.
All this code hasn't changed. I'm just moving it.
Feel free to clean it up but lets fix a real problem here.
>
> > + /* Turn DAWR off by default, but allow admin to turn it on */
> > + dawr_force_enable = false;
> > + debugfs_create_file_unsafe("dawr_enable_dangerous", 0600,
> > + powerpc_debugfs_root,
> > + &dawr_force_enable,
> > + &dawr_enable_fops);
> > + }
> > + return 0;
> > +}
> > +arch_initcall(dawr_force_setup);
>
> Wouldn't it also make sense to move set_dawr() from process.c to here ?
Yep, done.
>
> > diff --git a/arch/powerpc/kernel/hw_breakpoint.c
> > b/arch/powerpc/kernel/hw_breakpoint.c
> > index da307dd93e..95605a9c9a 100644
> > --- a/arch/powerpc/kernel/hw_breakpoint.c
> > +++ b/arch/powerpc/kernel/hw_breakpoint.c
> > @@ -380,59 +380,3 @@ void hw_breakpoint_pmu_read(struct perf_event *bp)
> > {
> > /* TODO */
> > }
> > -
> > -bool dawr_force_enable;
> > -EXPORT_SYMBOL_GPL(dawr_force_enable);
> > -
> > -static ssize_t dawr_write_file_bool(struct file *file,
> > - const char __user *user_buf,
> > - size_t count, loff_t *ppos)
> > -{
> > - struct arch_hw_breakpoint null_brk = {0, 0, 0};
> > - size_t rc;
> > -
> > - /* Send error to user if they hypervisor won't allow us to write DAWR */
> > - if ((!dawr_force_enable) &&
> > - (firmware_has_feature(FW_FEATURE_LPAR)) &&
> > - (set_dawr(&null_brk) != H_SUCCESS))
> > - return -1;
> > -
> > - rc = debugfs_write_file_bool(file, user_buf, count, ppos);
> > - if (rc)
> > - return rc;
> > -
> > - /* If we are clearing, make sure all CPUs have the DAWR cleared */
> > - if (!dawr_force_enable)
> > - smp_call_function((smp_call_func_t)set_dawr, &null_brk, 0);
> > -
> > - return rc;
> > -}
> > -
> > -static const struct file_operations dawr_enable_fops = {
> > - .read = debugfs_read_file_bool,
> > - .write = dawr_write_file_bool,
> > - .open = simple_open,
> > - .llseek = default_llseek,
> > -};
> > -
> > -static int __init dawr_force_setup(void)
> > -{
> > - dawr_force_enable = false;
> > -
> > - if (cpu_has_feature(CPU_FTR_DAWR)) {
> > - /* Don't setup sysfs file for user control on P8 */
> > - dawr_force_enable = true;
> > - return 0;
> > - }
> > -
> > - if (PVR_VER(mfspr(SPRN_PVR)) == PVR_POWER9) {
> > - /* Turn DAWR off by default, but allow admin to turn it on */
> > - dawr_force_enable = false;
> > - debugfs_create_file_unsafe("dawr_enable_dangerous", 0600,
> > - powerpc_debugfs_root,
> > - &dawr_force_enable,
> > - &dawr_enable_fops);
> > - }
> > - return 0;
> > -}
> > -arch_initcall(dawr_force_setup);
> > diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
> > index bfdde04e49..9c0d315108 100644
> > --- a/arch/powerpc/kvm/Kconfig
> > +++ b/arch/powerpc/kvm/Kconfig
> > @@ -39,6 +39,7 @@ config KVM_BOOK3S_32_HANDLER
> > config KVM_BOOK3S_64_HANDLER
> > bool
> > select KVM_BOOK3S_HANDLER
> > + select PPC_DAWR_FORCE_ENABLE
> >
> > config KVM_BOOK3S_PR_POSSIBLE
> > bool
> >
>
> Christophe
>
More information about the Linuxppc-dev
mailing list