powerpc: Fix compile issue with force DAWR
authorMichael Neuling <mikey@neuling.org>
Tue, 4 Jun 2019 03:00:37 +0000 (13:00 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 3 Jul 2019 05:19:35 +0000 (15:19 +1000)
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 moves a bunch of code around to fix this. It moves a lot of the
DAWR code in a new file and creates a new CONFIG_PPC_DAWR to enable
compiling it.

Fixes: c1fe190c0672 ("powerpc: Add force enable of DAWR on P9 option")
Signed-off-by: Michael Neuling <mikey@neuling.org>
[mpe: Minor formatting in set_dawr()]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/Kconfig
arch/powerpc/include/asm/hw_breakpoint.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/dawr.c [new file with mode: 0644]
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/process.c
arch/powerpc/kvm/Kconfig

index 3adff91..8769026 100644 (file)
@@ -236,6 +236,7 @@ config PPC
        select OLD_SIGSUSPEND
        select PCI_DOMAINS                      if PCI
        select PCI_SYSCALL                      if PCI
+       select PPC_DAWR                         if PPC64
        select RTC_LIB
        select SPARSE_IRQ
        select SYSCTL_EXCEPTION_TRACE
@@ -372,6 +373,9 @@ config PPC_ADV_DEBUG_DAC_RANGE
        depends on PPC_ADV_DEBUG_REGS && 44x
        default y
 
+config PPC_DAWR
+       bool
+
 config ZONE_DMA
        bool
        default y if PPC_BOOK3E_64
index 0fe8c1e..41abdae 100644 (file)
@@ -90,18 +90,25 @@ 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);
+#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) { }
+
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+
+#ifdef CONFIG_PPC_DAWR
 extern bool dawr_force_enable;
 static inline bool dawr_enabled(void)
 {
        return dawr_force_enable;
 }
-
-#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) { }
+int set_dawr(struct arch_hw_breakpoint *brk);
+#else
 static inline bool dawr_enabled(void) { return false; }
-#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+static inline int set_dawr(struct arch_hw_breakpoint *brk) { return -1; }
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */
index 0ea6c4a..56dfa7a 100644 (file)
@@ -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)         += 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 (file)
index 0000000..5f66b95
--- /dev/null
@@ -0,0 +1,101 @@
+// 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);
+
+int set_dawr(struct arch_hw_breakpoint *brk)
+{
+       unsigned long dawr, dawrx, mrd;
+
+       dawr = brk->address;
+
+       dawrx  = (brk->type & (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE))
+               << (63 - 58);
+       dawrx |= ((brk->type & (HW_BRK_TYPE_TRANSLATE)) >> 2) << (63 - 59);
+       dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) >> 3;
+       /*
+        * DAWR length is stored in field MDR bits 48:53.  Matches range in
+        * doublewords (64 bits) baised by -1 eg. 0b000000=1DW and
+        * 0b111111=64DW.
+        * brk->len is in bytes.
+        * This aligns up to double word size, shifts and does the bias.
+        */
+       mrd = ((brk->len + 7) >> 3) - 1;
+       dawrx |= (mrd & 0x3f) << (63 - 53);
+
+       if (ppc_md.set_dawr)
+               return ppc_md.set_dawr(dawr, dawrx);
+
+       mtspr(SPRN_DAWR, dawr);
+       mtspr(SPRN_DAWRX, dawrx);
+
+       return 0;
+}
+
+static void set_dawr_cb(void *info)
+{
+       set_dawr(info);
+}
+
+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 -ENODEV;
+
+       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(set_dawr_cb, &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)
+{
+       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 */
+               debugfs_create_file_unsafe("dawr_enable_dangerous", 0600,
+                                          powerpc_debugfs_root,
+                                          &dawr_force_enable,
+                                          &dawr_enable_fops);
+       }
+       return 0;
+}
+arch_initcall(dawr_force_setup);
index ca3a235..95605a9 100644 (file)
@@ -380,64 +380,3 @@ void hw_breakpoint_pmu_read(struct perf_event *bp)
 {
        /* TODO */
 }
-
-bool dawr_force_enable;
-EXPORT_SYMBOL_GPL(dawr_force_enable);
-
-static void set_dawr_cb(void *info)
-{
-       set_dawr(info);
-}
-
-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(set_dawr_cb, &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);
index 87da401..03a2da3 100644 (file)
@@ -797,34 +797,6 @@ static inline int set_dabr(struct arch_hw_breakpoint *brk)
        return __set_dabr(dabr, dabrx);
 }
 
-int set_dawr(struct arch_hw_breakpoint *brk)
-{
-       unsigned long dawr, dawrx, mrd;
-
-       dawr = brk->address;
-
-       dawrx  = (brk->type & (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)) \
-                                  << (63 - 58); //* read/write bits */
-       dawrx |= ((brk->type & (HW_BRK_TYPE_TRANSLATE)) >> 2) \
-                                  << (63 - 59); //* translate */
-       dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) \
-                                  >> 3; //* PRIM bits */
-       /* dawr length is stored in field MDR bits 48:53.  Matches range in
-          doublewords (64 bits) baised by -1 eg. 0b000000=1DW and
-          0b111111=64DW.
-          brk->len is in bytes.
-          This aligns up to double word size, shifts and does the bias.
-       */
-       mrd = ((brk->len + 7) >> 3) - 1;
-       dawrx |= (mrd & 0x3f) << (63 - 53);
-
-       if (ppc_md.set_dawr)
-               return ppc_md.set_dawr(dawr, dawrx);
-       mtspr(SPRN_DAWR, dawr);
-       mtspr(SPRN_DAWRX, dawrx);
-       return 0;
-}
-
 void __set_breakpoint(struct arch_hw_breakpoint *brk)
 {
        memcpy(this_cpu_ptr(&current_brk), brk, sizeof(*brk));
index f53997a..b8e13d5 100644 (file)
@@ -38,6 +38,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