These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / arm64 / kernel / hw_breakpoint.c
index e7d934d..b45c95d 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/smp.h>
 
+#include <asm/compat.h>
 #include <asm/current.h>
 #include <asm/debug-monitors.h>
 #include <asm/hw_breakpoint.h>
-#include <asm/kdebug.h>
 #include <asm/traps.h>
 #include <asm/cputype.h>
 #include <asm/system_misc.h>
@@ -49,18 +49,6 @@ static DEFINE_PER_CPU(int, stepping_kernel_bp);
 static int core_num_brps;
 static int core_num_wrps;
 
-/* Determine number of BRP registers available. */
-static int get_num_brps(void)
-{
-       return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
-}
-
-/* Determine number of WRP registers available. */
-static int get_num_wrps(void)
-{
-       return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
-}
-
 int hw_breakpoint_slots(int type)
 {
        /*
@@ -157,7 +145,7 @@ static void write_wb_reg(int reg, int n, u64 val)
  * Convert a breakpoint privilege level to the corresponding exception
  * level.
  */
-static enum debug_el debug_exception_level(int privilege)
+static enum dbg_active_el debug_exception_level(int privilege)
 {
        switch (privilege) {
        case AARCH64_BREAKPOINT_EL0:
@@ -176,6 +164,20 @@ enum hw_breakpoint_ops {
        HW_BREAKPOINT_RESTORE
 };
 
+static int is_compat_bp(struct perf_event *bp)
+{
+       struct task_struct *tsk = bp->hw.target;
+
+       /*
+        * tsk can be NULL for per-cpu (non-ptrace) breakpoints.
+        * In this case, use the native interface, since we don't have
+        * the notion of a "compat CPU" and could end up relying on
+        * deprecated behaviour if we use unaligned watchpoints in
+        * AArch64 state.
+        */
+       return tsk && is_compat_thread(task_thread_info(tsk));
+}
+
 /**
  * hw_breakpoint_slot_setup - Find and setup a perf slot according to
  *                           operations
@@ -231,7 +233,7 @@ static int hw_breakpoint_control(struct perf_event *bp,
        struct perf_event **slots;
        struct debug_info *debug_info = &current->thread.debug;
        int i, max_slots, ctrl_reg, val_reg, reg_enable;
-       enum debug_el dbg_el = debug_exception_level(info->ctrl.privilege);
+       enum dbg_active_el dbg_el = debug_exception_level(info->ctrl.privilege);
        u32 ctrl;
 
        if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
@@ -433,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)
         * Watchpoints can be of length 1, 2, 4 or 8 bytes.
         */
        if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
-               if (is_compat_task()) {
+               if (is_compat_bp(bp)) {
                        if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
                            info->ctrl.len != ARM_BREAKPOINT_LEN_4)
                                return -EINVAL;
@@ -490,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
         * AArch32 tasks expect some simple alignment fixups, so emulate
         * that here.
         */
-       if (is_compat_task()) {
+       if (is_compat_bp(bp)) {
                if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
                        alignment_mask = 0x7;
                else
@@ -538,7 +540,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
  * exception level at the register level.
  * This is used when single-stepping after a breakpoint exception.
  */
-static void toggle_bp_registers(int reg, enum debug_el el, int enable)
+static void toggle_bp_registers(int reg, enum dbg_active_el el, int enable)
 {
        int i, max_slots, privilege;
        u32 ctrl;
@@ -885,7 +887,7 @@ static int hw_breakpoint_reset_notify(struct notifier_block *self,
                                                void *hcpu)
 {
        int cpu = (long)hcpu;
-       if (action == CPU_ONLINE)
+       if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
                smp_call_function_single(cpu, hw_breakpoint_reset, NULL, 1);
        return NOTIFY_OK;
 }