[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