* [RFC Patch 5/5] PPC64-HWBKPT: Enable proper distinction of per-task and per-cpu breakpoints
From: K.Prasad @ 2010-05-24 4:04 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras,
Linux Kernel Mailing List
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, K.Prasad,
Roland McGrath
In-Reply-To: <20100524034520.964014525@linux.vnet.ibm.com>
Per-task and per-cpu breakpoints have to be unambiguously identified for
proper restoration of hw-breakpoints. The notion of pure user- and kernel-
space breakpoints is antiquated. Store 'pid' of the process against which
the perf-counter was requested to help proper distinction.
This helps seamless handling of kernel-space breakpoints within the context
of a user-space process and breakpoints for kernel-threads.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/kernel/hw_breakpoint.c | 24 +++++++++++++++++-------
include/linux/perf_event.h | 1 +
kernel/perf_event.c | 9 ++++++---
3 files changed, 24 insertions(+), 10 deletions(-)
Index: linux-2.6.ppc64_test/include/linux/perf_event.h
===================================================================
--- linux-2.6.ppc64_test.orig/include/linux/perf_event.h
+++ linux-2.6.ppc64_test/include/linux/perf_event.h
@@ -698,6 +698,7 @@ struct perf_event {
int oncpu;
int cpu;
+ pid_t pid;
struct list_head owner_entry;
struct task_struct *owner;
Index: linux-2.6.ppc64_test/kernel/perf_event.c
===================================================================
--- linux-2.6.ppc64_test.orig/kernel/perf_event.c
+++ linux-2.6.ppc64_test/kernel/perf_event.c
@@ -4684,6 +4684,7 @@ static const struct pmu *sw_perf_event_i
static struct perf_event *
perf_event_alloc(struct perf_event_attr *attr,
int cpu,
+ pid_t pid,
struct perf_event_context *ctx,
struct perf_event *group_leader,
struct perf_event *parent_event,
@@ -4717,6 +4718,7 @@ perf_event_alloc(struct perf_event_attr
mutex_init(&event->mmap_mutex);
event->cpu = cpu;
+ event->pid = pid;
event->attr = *attr;
event->group_leader = group_leader;
event->pmu = NULL;
@@ -5015,7 +5017,7 @@ SYSCALL_DEFINE5(perf_event_open,
goto err_put_context;
}
- event = perf_event_alloc(&attr, cpu, ctx, group_leader,
+ event = perf_event_alloc(&attr, cpu, pid, ctx, group_leader,
NULL, NULL, GFP_KERNEL);
err = PTR_ERR(event);
if (IS_ERR(event))
@@ -5090,7 +5092,7 @@ perf_event_create_kernel_counter(struct
goto err_exit;
}
- event = perf_event_alloc(attr, cpu, ctx, NULL,
+ event = perf_event_alloc(attr, cpu, pid, ctx, NULL,
NULL, overflow_handler, GFP_KERNEL);
if (IS_ERR(event)) {
err = PTR_ERR(event);
@@ -5142,7 +5144,8 @@ inherit_event(struct perf_event *parent_
parent_event = parent_event->parent;
child_event = perf_event_alloc(&parent_event->attr,
- parent_event->cpu, child_ctx,
+ parent_event->cpu, child->pid,
+ child_ctx,
group_leader, parent_event,
NULL, GFP_KERNEL);
if (IS_ERR(child_event))
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/hw_breakpoint.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
@@ -221,7 +221,7 @@ void thread_change_pc(struct task_struct
*/
int __kprobes hw_breakpoint_handler(struct die_args *args)
{
- bool is_kernel, is_ptrace_bp = false;
+ bool is_kernel, is_taskbound_bp, is_ptrace_bp = false;
int rc = NOTIFY_STOP;
struct perf_event *bp;
struct pt_regs *regs = args->regs;
@@ -246,6 +246,7 @@ int __kprobes hw_breakpoint_handler(stru
is_kernel = is_kernel_addr(bp->attr.bp_addr);
is_ptrace_bp = (bp->overflow_handler == ptrace_triggered) ?
true : false;
+ is_taskbound_bp = (bp->pid > 0) ? true : false;
/*
* Verify if dar lies within the address range occupied by the symbol
@@ -288,7 +289,14 @@ int __kprobes hw_breakpoint_handler(stru
/* emulate_step() could not execute it, single-step them */
if (stepped == 0) {
regs->msr |= MSR_SE;
- __get_cpu_var(last_hit_bp) = bp;
+ /*
+ * Kernel-space addresses can also be bound to a task. If so,
+ * store the breakpoint in its 'thread_struct'
+ */
+ if (is_taskbound_bp)
+ bp->ctx->task->thread.last_hit_ubp = bp;
+ else
+ __get_cpu_var(last_hit_bp) = bp;
goto out;
}
/*
@@ -310,17 +318,17 @@ out:
int __kprobes single_step_dabr_instruction(struct die_args *args)
{
struct pt_regs *regs = args->regs;
- struct perf_event *bp = NULL, *kernel_bp, *user_bp;
+ struct perf_event *bp = NULL, *kernel_bp, *per_task_bp;
struct arch_hw_breakpoint *bp_info;
/*
* Identify the cause of single-stepping and find the corresponding
* breakpoint structure
*/
- user_bp = current->thread.last_hit_ubp;
+ per_task_bp = current->thread.last_hit_ubp;
kernel_bp = __get_cpu_var(last_hit_bp);
- if (user_bp) {
- bp = user_bp;
+ if (per_task_bp) {
+ bp = per_task_bp;
current->thread.last_hit_ubp = NULL;
} else if (kernel_bp) {
bp = kernel_bp;
@@ -348,7 +356,9 @@ int __kprobes single_step_dabr_instructi
* for kernel-space breakpoints, so this cannot work along with other
* debuggers (like KGDB, xmon) which may be single-stepping kernel code.
*/
- if (!(user_bp && test_thread_flag(TIF_SINGLESTEP)))
+ if (!(per_task_bp &&
+ (!is_kernel_addr(bp->attr.bp_addr)) &&
+ test_thread_flag(TIF_SINGLESTEP)))
regs->msr &= ~MSR_SE;
set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
^ permalink raw reply
* Re: [RFC Patch 2/5] PPC64-HWBKPT: Implement hw-breakpoints for PowerPC Book III S
From: K.Prasad @ 2010-05-24 4:38 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, Roland McGrath
In-Reply-To: <20100524040225.GC20873@in.ibm.com>
On Mon, May 24, 2010 at 09:32:25AM +0530, K.Prasad wrote:
> Implement perf-events based hw-breakpoint interfaces for PowerPC Book III S
> processors. These interfaces help arbitrate requests from various users and
> schedules them as appropriate.
>
<snipped>
> +/*
> + * Handle debug exception notifications.
> + */
> +int __kprobes hw_breakpoint_handler(struct die_args *args)
> +{
> + bool is_kernel, is_ptrace_bp = false;
> + int rc = NOTIFY_STOP;
> + struct perf_event *bp;
> + struct pt_regs *regs = args->regs;
> + unsigned long dar = regs->dar;
> + int stepped = 1;
> + struct arch_hw_breakpoint *info;
> +
> + /* Disable breakpoints during exception handling */
> + set_dabr(0);
> + /*
> + * The counter may be concurrently released but that can only
> + * occur from a call_rcu() path. We can then safely fetch
> + * the breakpoint, use its callback, touch its counter
> + * while we are in an rcu_read_lock() path.
> + */
> + rcu_read_lock();
> +
> + bp = __get_cpu_var(bp_per_reg);
> + if (!bp)
> + goto out;
> + info = counter_arch_bp(bp);
> + is_kernel = is_kernel_addr(bp->attr.bp_addr);
> + is_ptrace_bp = (bp->overflow_handler == ptrace_triggered) ?
> + true : false;
> +
> + /*
> + * Verify if dar lies within the address range occupied by the symbol
> + * being watched to filter extraneous exceptions.
> + */
> + if (!((bp->attr.bp_addr <= dar) &&
> + (dar <= (bp->attr.bp_addr + bp->attr.bp_len))) &&
> + (!is_ptrace_bp))
> + /*
> + * This exception is triggered not because of a memory access on
> + * the monitored variable but in the double-word address range
> + * in which it is contained. We will consume this exception,
> + * considering it as 'noise'.
> + */
> + goto restore_bp;
> +
> + /*
> + * Return early after invoking user-callback function without restoring
> + * DABR if the breakpoint is from ptrace which always operates in
> + * one-shot mode. The ptrace-ed process will receive the SIGTRAP signal
> + * generated in do_dabr().
> + */
> + if (is_ptrace_bp) {
> + perf_bp_event(bp, regs);
> + rc = NOTIFY_DONE;
> + goto out;
> + }
> +
> + /*
> + * Do not emulate user-space instructions from kernel-space,
> + * instead single-step them.
> + */
> + if (!is_kernel) {
> + bp->ctx->task->thread.last_hit_ubp = bp;
> + regs->msr |= MSR_SE;
> + goto out;
> + }
> +
> + stepped = emulate_step(regs, regs->nip);
> + /* emulate_step() could not execute it, single-step them */
> + if (stepped == 0) {
As I was responding to one of the previous mails, I realised that I
had not made changes here as Paul Mackerras had suggested
(reference linuxppc-dev message-id:
20100520131003.GB29903@brick.ozlabs.ibm.com) i.e. uninstall breakpoint
if single-stepping failed.
I'll quickly send out a revised patch as a reply to this one. Regrets
for the confusion caused.
Thanks,
K.Prasad
> + regs->msr |= MSR_SE;
> + __get_cpu_var(last_hit_bp) = bp;
> + goto out;
> + }
> + /*
> + * As a policy, the callback is invoked in a 'trigger-after-execute'
> + * fashion
> + */
> + perf_bp_event(bp, regs);
> +
> +restore_bp:
> + set_dabr(info->address | info->type | DABR_TRANSLATION);
> +out:
> + rcu_read_unlock();
> + return rc;
> +}
^ permalink raw reply
* [Patch 2/4] PPC64-HWBKPT: Implement hw-breakpoints for PowerPC Book III S
From: K.Prasad @ 2010-05-24 10:33 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, K.Prasad,
Roland McGrath
In-Reply-To: <20100524102614.040177456@linux.vnet.ibm.com>
Implement perf-events based hw-breakpoint interfaces for PowerPC Book III S
processors. These interfaces help arbitrate requests from various users and
schedules them as appropriate.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 1
arch/powerpc/include/asm/cputable.h | 4
arch/powerpc/include/asm/hw_breakpoint.h | 49 ++++
arch/powerpc/include/asm/processor.h | 8
arch/powerpc/kernel/Makefile | 1
arch/powerpc/kernel/hw_breakpoint.c | 345 +++++++++++++++++++++++++++++++
arch/powerpc/kernel/machine_kexec_64.c | 3
arch/powerpc/kernel/process.c | 6
arch/powerpc/kernel/ptrace.c | 64 +++++
arch/powerpc/lib/Makefile | 1
include/linux/hw_breakpoint.h | 1
11 files changed, 483 insertions(+)
Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h
===================================================================
--- /dev/null
+++ linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h
@@ -0,0 +1,49 @@
+#ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H
+#define _PPC_BOOK3S_64_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+
+struct arch_hw_breakpoint {
+ u8 len; /* length of the target data symbol */
+ int type;
+ unsigned long address;
+};
+
+#include <linux/kdebug.h>
+#include <asm/reg.h>
+#include <asm/system.h>
+
+static inline int hw_breakpoint_slots(int type)
+{
+ return HBP_NUM;
+}
+struct perf_event;
+struct pmu;
+struct perf_sample_data;
+
+#define HW_BREAKPOINT_ALIGN 0x7
+/* Maximum permissible length of any HW Breakpoint */
+#define HW_BREAKPOINT_LEN 0x8
+
+extern int arch_bp_generic_fields(int type, int *gen_bp_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+ unsigned long val, void *data);
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
+
+extern struct pmu perf_ops_bp;
+extern void ptrace_triggered(struct perf_event *bp, int nmi,
+ struct perf_sample_data *data, struct pt_regs *regs);
+static inline void hw_breakpoint_disable(void)
+{
+ set_dabr(0);
+}
+
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+#endif /* __KERNEL__ */
+#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- /dev/null
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
@@ -0,0 +1,345 @@
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers. Derived from
+ * "arch/x86/kernel/hw_breakpoint.c"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright 2010 IBM Corporation
+ * Author: K.Prasad <prasad@linux.vnet.ibm.com>
+ *
+ */
+
+#include <linux/hw_breakpoint.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/percpu.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/hw_breakpoint.h>
+#include <asm/processor.h>
+#include <asm/sstep.h>
+
+/*
+ * Stores the breakpoints currently in use on each breakpoint address
+ * register for every cpu
+ */
+static DEFINE_PER_CPU(struct perf_event *, bp_per_reg);
+
+/*
+ * Install a perf counter breakpoint.
+ *
+ * We seek a free debug address register and use it for this
+ * breakpoint.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+ struct perf_event **slot = &__get_cpu_var(bp_per_reg);
+
+ *slot = bp;
+
+ /*
+ * Do not install DABR values if the instruction must be single-stepped.
+ * If so, DABR will be populated in single_step_dabr_instruction().
+ */
+ if (current->thread.last_hit_ubp != bp)
+ set_dabr(info->address | info->type | DABR_TRANSLATION);
+
+ return 0;
+}
+
+/*
+ * Uninstall the breakpoint contained in the given counter.
+ *
+ * First we search the debug address register it uses and then we disable
+ * it.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+ struct perf_event **slot = &__get_cpu_var(bp_per_reg);
+
+ if (*slot != bp) {
+ WARN_ONCE(1, "Can't find the breakpoint");
+ return;
+ }
+
+ *slot = NULL;
+ set_dabr(0);
+}
+
+/*
+ * Perform cleanup of arch-specific counters during unregistration
+ * of the perf-event
+ */
+void arch_unregister_hw_breakpoint(struct perf_event *bp)
+{
+ /*
+ * If the breakpoint is unregistered between a hw_breakpoint_handler()
+ * and the single_step_dabr_instruction(), then cleanup the breakpoint
+ * restoration variables to prevent dangling pointers.
+ */
+ if (bp->ctx->task)
+ bp->ctx->task->thread.last_hit_ubp = NULL;
+
+ put_cpu();
+}
+
+/*
+ * Check for virtual address in kernel space.
+ */
+int arch_check_bp_in_kernelspace(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+ return is_kernel_addr(info->address);
+}
+
+int arch_bp_generic_fields(int type, int *gen_bp_type)
+{
+ switch (type) {
+ case DABR_DATA_READ:
+ *gen_bp_type = HW_BREAKPOINT_R;
+ break;
+ case DABR_DATA_WRITE:
+ *gen_bp_type = HW_BREAKPOINT_W;
+ break;
+ case (DABR_DATA_WRITE | DABR_DATA_READ):
+ *gen_bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp)
+{
+ int ret = -EINVAL;
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+ if (!bp)
+ return ret;
+
+ switch (bp->attr.bp_type) {
+ case HW_BREAKPOINT_R:
+ info->type = DABR_DATA_READ;
+ break;
+ case HW_BREAKPOINT_W:
+ info->type = DABR_DATA_WRITE;
+ break;
+ case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
+ info->type = (DABR_DATA_READ | DABR_DATA_WRITE);
+ break;
+ default:
+ return ret;
+ }
+
+ info->address = bp->attr.bp_addr;
+ info->len = bp->attr.bp_len;
+
+ /*
+ * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
+ * and breakpoint addresses are aligned to nearest double-word
+ * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
+ * 'symbolsize' should satisfy the check below.
+ */
+ if (info->len >
+ (HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN)))
+ return -EINVAL;
+ return 0;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+ bool is_kernel, is_ptrace_bp = false;
+ int rc = NOTIFY_STOP;
+ struct perf_event *bp;
+ struct pt_regs *regs = args->regs;
+ unsigned long dar = regs->dar;
+ int stepped = 1;
+ struct arch_hw_breakpoint *info;
+
+ /* Disable breakpoints during exception handling */
+ set_dabr(0);
+ /*
+ * The counter may be concurrently released but that can only
+ * occur from a call_rcu() path. We can then safely fetch
+ * the breakpoint, use its callback, touch its counter
+ * while we are in an rcu_read_lock() path.
+ */
+ rcu_read_lock();
+
+ bp = __get_cpu_var(bp_per_reg);
+ if (!bp)
+ goto out;
+ info = counter_arch_bp(bp);
+ is_kernel = is_kernel_addr(bp->attr.bp_addr);
+ is_ptrace_bp = (bp->overflow_handler == ptrace_triggered) ?
+ true : false;
+
+ /*
+ * Verify if dar lies within the address range occupied by the symbol
+ * being watched to filter extraneous exceptions.
+ */
+ if (!((bp->attr.bp_addr <= dar) &&
+ (dar <= (bp->attr.bp_addr + bp->attr.bp_len))) &&
+ (!is_ptrace_bp))
+ /*
+ * This exception is triggered not because of a memory access on
+ * the monitored variable but in the double-word address range
+ * in which it is contained. We will consume this exception,
+ * considering it as 'noise'.
+ */
+ goto restore_bp;
+
+ /*
+ * Return early after invoking user-callback function without restoring
+ * DABR if the breakpoint is from ptrace which always operates in
+ * one-shot mode. The ptrace-ed process will receive the SIGTRAP signal
+ * generated in do_dabr().
+ */
+ if (is_ptrace_bp) {
+ perf_bp_event(bp, regs);
+ rc = NOTIFY_DONE;
+ goto out;
+ }
+
+ /*
+ * Do not emulate user-space instructions from kernel-space,
+ * instead single-step them.
+ */
+ if (!is_kernel) {
+ bp->ctx->task->thread.last_hit_ubp = bp;
+ regs->msr |= MSR_SE;
+ goto out;
+ }
+
+ stepped = emulate_step(regs, regs->nip);
+ /*
+ * emulate_step() could not execute it. We've failed in reliably
+ * handling the hw-breakpoint. Unregister it and throw a warning
+ * message to let the user know about it.
+ */
+ if (stepped == 0) {
+ WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
+ "0x%lx will be uninstalled.", info->address);
+ unregister_hw_breakpoint(bp);
+ goto out;
+ }
+ /*
+ * As a policy, the callback is invoked in a 'trigger-after-execute'
+ * fashion
+ */
+ perf_bp_event(bp, regs);
+
+restore_bp:
+ set_dabr(info->address | info->type | DABR_TRANSLATION);
+out:
+ rcu_read_unlock();
+ return rc;
+}
+
+/*
+ * Handle single-step exceptions following a DABR hit.
+ */
+int __kprobes single_step_dabr_instruction(struct die_args *args)
+{
+ struct pt_regs *regs = args->regs;
+ struct perf_event *bp = NULL;
+ struct arch_hw_breakpoint *bp_info;
+
+ bp = current->thread.last_hit_ubp;
+ /*
+ * Check if we are single-stepping as a result of a
+ * previous HW Breakpoint exception
+ */
+ if (!bp)
+ return NOTIFY_DONE;
+
+ bp_info = counter_arch_bp(bp);
+
+ /*
+ * We shall invoke the user-defined callback function in the single
+ * stepping handler to confirm to 'trigger-after-execute' semantics
+ */
+ perf_bp_event(bp, regs);
+
+ /*
+ * Do not disable MSR_SE if the process was already in
+ * single-stepping mode. We cannot reliable detect single-step mode
+ * for kernel-space breakpoints, so this cannot work along with other
+ * debuggers (like KGDB, xmon) which may be single-stepping kernel code.
+ */
+ if (!(!is_kernel_addr(bp->attr.bp_addr) &&
+ test_thread_flag(TIF_SINGLESTEP)))
+ regs->msr &= ~MSR_SE;
+
+ set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
+ return NOTIFY_STOP;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_exceptions_notify(
+ struct notifier_block *unused, unsigned long val, void *data)
+{
+ int ret = NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_DABR_MATCH:
+ ret = hw_breakpoint_handler(data);
+ break;
+ case DIE_SSTEP:
+ ret = single_step_dabr_instruction(data);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Release the user breakpoints used by ptrace
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+ struct thread_struct *t = &tsk->thread;
+
+ unregister_hw_breakpoint(t->ptrace_bps[0]);
+ t->ptrace_bps[0] = NULL;
+}
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+ /* TODO */
+}
+
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/Makefile
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/Makefile
@@ -34,6 +34,7 @@ obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
signal_64.o ptrace32.o \
paca.o nvram_64.o firmware.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o
obj64-$(CONFIG_RELOCATABLE) += reloc_64.o
obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o
Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/processor.h
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/include/asm/processor.h
+++ linux-2.6.ppc64_test/arch/powerpc/include/asm/processor.h
@@ -209,6 +209,14 @@ struct thread_struct {
#ifdef CONFIG_PPC64
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ struct perf_event *ptrace_bps[HBP_NUM];
+ /*
+ * Helps identify source of single-step exception and subsequent
+ * hw-breakpoint enablement
+ */
+ struct perf_event *last_hit_ubp;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif
unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/ptrace.c
@@ -32,6 +32,8 @@
#ifdef CONFIG_PPC32
#include <linux/module.h>
#endif
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -866,9 +868,34 @@ void user_disable_single_step(struct tas
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+void ptrace_triggered(struct perf_event *bp, int nmi,
+ struct perf_sample_data *data, struct pt_regs *regs)
+{
+ struct perf_event_attr attr;
+
+ /*
+ * Disable the breakpoint request here since ptrace has defined a
+ * one-shot behaviour for breakpoint exceptions in PPC64.
+ * The SIGTRAP signal is generated automatically for us in do_dabr().
+ * We don't have to do anything about that here
+ */
+ attr = bp->attr;
+ attr.disabled = true;
+ modify_user_hw_breakpoint(bp, &attr);
+}
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ int ret;
+ struct thread_struct *thread = &(task->thread);
+ struct perf_event *bp;
+ struct perf_event_attr attr;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
/* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
* For embedded processors we support one DAC and no IAC's at the
* moment.
@@ -896,6 +923,43 @@ int ptrace_set_debugreg(struct task_stru
/* Ensure breakpoint translation bit is set */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ bp = thread->ptrace_bps[0];
+ if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
+ if (bp) {
+ unregister_hw_breakpoint(bp);
+ thread->ptrace_bps[0] = NULL;
+ }
+ return 0;
+ }
+ if (bp) {
+ attr = bp->attr;
+ attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN;
+ arch_bp_generic_fields(data &
+ (DABR_DATA_WRITE | DABR_DATA_READ),
+ &attr.bp_type);
+ ret = modify_user_hw_breakpoint(bp, &attr);
+ if (ret)
+ return ret;
+ thread->ptrace_bps[0] = bp;
+ thread->dabr = data;
+ return 0;
+ }
+
+ /* Create a new breakpoint request if one doesn't exist already */
+ hw_breakpoint_init(&attr);
+ attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN;
+ arch_bp_generic_fields(data & (DABR_DATA_WRITE | DABR_DATA_READ),
+ &attr.bp_type);
+
+ thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
+ ptrace_triggered, task);
+ if (IS_ERR(bp)) {
+ thread->ptrace_bps[0] = NULL;
+ return PTR_ERR(bp);
+ }
+
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
/* Move contents to the DABR register */
task->thread.dabr = data;
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/process.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/process.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/process.c
@@ -462,8 +462,14 @@ struct task_struct *__switch_to(struct t
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
switch_booke_debug_regs(&new->thread);
#else
+/*
+ * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would
+ * schedule DABR
+ */
+#ifndef CONFIG_HAVE_HW_BREAKPOINT
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif
Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/cputable.h
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/include/asm/cputable.h
+++ linux-2.6.ppc64_test/arch/powerpc/include/asm/cputable.h
@@ -516,6 +516,10 @@ static inline int cpu_has_feature(unsign
& feature);
}
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+#define HBP_NUM 1
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/machine_kexec_64.c
@@ -15,6 +15,7 @@
#include <linux/thread_info.h>
#include <linux/init_task.h>
#include <linux/errno.h>
+#include <linux/hw_breakpoint.h>
#include <asm/page.h>
#include <asm/current.h>
@@ -165,6 +166,7 @@ static void kexec_smp_down(void *arg)
while(kexec_all_irq_disabled == 0)
cpu_relax();
mb(); /* make sure all irqs are disabled before this */
+ hw_breakpoint_disable();
/*
* Now every CPU has IRQs off, we can clear out any pending
* IPIs and be sure that no more will come in after this.
@@ -180,6 +182,7 @@ static void kexec_prepare_cpus_wait(int
{
int my_cpu, i, notified=-1;
+ hw_breakpoint_disable();
my_cpu = get_cpu();
/* Make sure each CPU has atleast made it to the state we need */
for (i=0; i < NR_CPUS; i++) {
Index: linux-2.6.ppc64_test/arch/powerpc/lib/Makefile
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/lib/Makefile
+++ linux-2.6.ppc64_test/arch/powerpc/lib/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PPC64) += copypage_64.o cop
memcpy_64.o usercopy_64.o mem_64.o string.o
obj-$(CONFIG_XMON) += sstep.o
obj-$(CONFIG_KPROBES) += sstep.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o
ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_SMP) += locks.o
Index: linux-2.6.ppc64_test/include/linux/hw_breakpoint.h
===================================================================
--- linux-2.6.ppc64_test.orig/include/linux/hw_breakpoint.h
+++ linux-2.6.ppc64_test/include/linux/hw_breakpoint.h
@@ -139,6 +139,7 @@ static inline struct arch_hw_breakpoint
{
return NULL;
}
+static inline void hw_breakpoint_disable(void) { }
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif /* __KERNEL__ */
Index: linux-2.6.ppc64_test/arch/powerpc/Kconfig
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/Kconfig
+++ linux-2.6.ppc64_test/arch/powerpc/Kconfig
@@ -141,6 +141,7 @@ config PPC
select GENERIC_ATOMIC64 if PPC32
select HAVE_PERF_EVENTS
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
config EARLY_PRINTK
bool
^ permalink raw reply
* [Patch 3/4] PPC64-HWBKPT: Handle concurrent alignment interrupts
From: K.Prasad @ 2010-05-24 10:33 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, K.Prasad,
Roland McGrath
In-Reply-To: <20100524102614.040177456@linux.vnet.ibm.com>
An alignment interrupt may intervene between a DSI/hw-breakpoint exception
and the single-step exception. Enable the alignment interrupt (through
modifications to emulate_single_step()) to notify the single-step exception
handler for proper restoration of hw-breakpoints.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/kernel/traps.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/traps.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/traps.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/traps.c
@@ -602,7 +602,7 @@ void RunModeException(struct pt_regs *re
void __kprobes single_step_exception(struct pt_regs *regs)
{
- regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
+ clear_single_step(regs);
if (notify_die(DIE_SSTEP, "single_step", regs, 5,
5, SIGTRAP) == NOTIFY_STOP)
@@ -621,10 +621,7 @@ void __kprobes single_step_exception(str
*/
static void emulate_single_step(struct pt_regs *regs)
{
- if (single_stepping(regs)) {
- clear_single_step(regs);
- _exception(SIGTRAP, regs, TRAP_TRACE, 0);
- }
+ single_step_exception(regs);
}
static inline int __parse_fpscr(unsigned long fpscr)
^ permalink raw reply
* Re: [Patch 4/4] PPC64-HWBKPT: Enable hw-breakpoints while handling intervening signals
From: Paul Mackerras @ 2010-05-24 12:24 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, linuxppc-dev@ozlabs.org,
Alan Stern, Roland McGrath
In-Reply-To: <20100524103419.GE8131@in.ibm.com>
On Mon, May 24, 2010 at 04:04:19PM +0530, K.Prasad wrote:
> A signal delivered between a hw_breakpoint_handler() and the
> single_step_dabr_instruction() will not have the breakpoint active during
> signal handling (since breakpoint will not be restored through single-stepping
> due to absence of MSR_SE bit on the signal frame). Enable breakpoints before
> signal delivery and clear them during sigreturn() syscall.
>
> Limitation: Nested hw-breakpoint exceptions (where second exception is raised
> inside signal context) will cause a 'double-hit' i.e. the first breakpoint
> exception will be taken twice.
I don't think this will actually cause a problem. In the case of a
perf_event breakpoint, the semantics are trigger-after-execute, so the
first hit won't cause a trigger, and perf_event won't double-count it.
In the case of ptrace-style breakpoints, we don't single-step (it's up
to the ptracer to do the single-stepping if needed) so the problem
doesn't arise.
In fact I don't think we even need to do anything on sigreturn. Yes,
we are changing the NIP but we are changing it to a previous value as
a result of an explicit action by the program, which is a bit
different to what signal delivery and ptrace do.
On signal delivery I was imagining that we would clear the MSR_SE bit
before saving the MSR value in the signal frame, and reinstall the
DABR value at the same time, and then essentially forget that we had
already hit the breakpoint once and just wait for it to hit again.
Paul.
^ permalink raw reply
* [Patch 4/4] PPC64-HWBKPT: Enable hw-breakpoints while handling intervening signals
From: K.Prasad @ 2010-05-24 10:34 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, K.Prasad,
Roland McGrath
In-Reply-To: <20100524102614.040177456@linux.vnet.ibm.com>
A signal delivered between a hw_breakpoint_handler() and the
single_step_dabr_instruction() will not have the breakpoint active during
signal handling (since breakpoint will not be restored through single-stepping
due to absence of MSR_SE bit on the signal frame). Enable breakpoints before
signal delivery and clear them during sigreturn() syscall.
Limitation: Nested hw-breakpoint exceptions (where second exception is raised
inside signal context) will cause a 'double-hit' i.e. the first breakpoint
exception will be taken twice.
Restore hw-breakpoints if the user-context is altered in the signal handler
(causing loss of MSR_SE). Side-effect: 'Double-hit' of breakpoint if the
instruction pointer is unaltered in the new context.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hw_breakpoint.h | 3 +++
arch/powerpc/kernel/hw_breakpoint.c | 28 ++++++++++++++++++++++++++++
arch/powerpc/kernel/signal.c | 8 ++++++++
arch/powerpc/kernel/signal_32.c | 10 ++++++++++
arch/powerpc/kernel/signal_64.c | 7 +++++++
5 files changed, 56 insertions(+)
Index: linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/include/asm/hw_breakpoint.h
+++ linux-2.6.ppc64_test/arch/powerpc/include/asm/hw_breakpoint.h
@@ -43,6 +43,9 @@ static inline void hw_breakpoint_disable
{
set_dabr(0);
}
+extern void sighandler_install_bp(struct task_struct *tsk);
+extern void sigreturn_uninstall_bp(struct task_struct *tsk);
+extern void thread_change_pc(struct task_struct *tsk, unsigned long msr);
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif /* __KERNEL__ */
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/hw_breakpoint.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/hw_breakpoint.c
@@ -175,6 +175,34 @@ int arch_validate_hwbkpt_settings(struct
return 0;
}
+void sighandler_install_bp(struct task_struct *tsk)
+{
+ struct arch_hw_breakpoint *info;
+
+ if (likely(!tsk->thread.last_hit_ubp))
+ return;
+
+ info = counter_arch_bp(tsk->thread.last_hit_ubp);
+ set_dabr(info->address | info->type | DABR_TRANSLATION);
+}
+
+void sigreturn_uninstall_bp(struct task_struct *tsk)
+{
+ if (unlikely(tsk->thread.last_hit_ubp))
+ set_dabr(0);
+}
+
+void thread_change_pc(struct task_struct *tsk, unsigned long new_msr)
+{
+ /*
+ * Do not bother to restore breakpoints if single-stepping is not
+ * cleared. single_step_dabr_instruction() will handle it if MSR_SE
+ * is set.
+ */
+ if (!(new_msr & MSR_SE))
+ sighandler_install_bp(tsk);
+}
+
/*
* Handle debug exception notifications.
*/
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/signal.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/signal.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/signal.c
@@ -11,6 +11,7 @@
#include <linux/tracehook.h>
#include <linux/signal.h>
+#include <asm/hw_breakpoint.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -149,6 +150,13 @@ static int do_signal_pending(sigset_t *o
if (current->thread.dabr)
set_dabr(current->thread.dabr);
#endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ /*
+ * Re-enable the breakpoints (if it was previously cleared in
+ * hw_breakpoint_handler()) for the signal stack.
+ */
+ sighandler_install_bp(current);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
if (is32) {
if (ka.sa.sa_flags & SA_SIGINFO)
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/signal_64.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/signal_64.c
@@ -33,6 +33,7 @@
#include <asm/cacheflush.h>
#include <asm/syscalls.h>
#include <asm/vdso.h>
+#include <asm/hw_breakpoint.h>
#include "signal.h"
@@ -312,6 +313,9 @@ int sys_swapcontext(struct ucontext __us
|| __copy_to_user(&old_ctx->uc_sigmask,
¤t->blocked, sizeof(sigset_t)))
return -EFAULT;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ thread_change_pc(current, new_msr);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
}
if (new_ctx == NULL)
return 0;
@@ -364,6 +368,9 @@ int sys_rt_sigreturn(unsigned long r3, u
if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
goto badframe;
restore_sigmask(&set);
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ sigreturn_uninstall_bp(current);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
goto badframe;
Index: linux-2.6.ppc64_test/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-2.6.ppc64_test.orig/arch/powerpc/kernel/signal_32.c
+++ linux-2.6.ppc64_test/arch/powerpc/kernel/signal_32.c
@@ -42,6 +42,7 @@
#include <asm/syscalls.h>
#include <asm/sigcontext.h>
#include <asm/vdso.h>
+#include <asm/hw_breakpoint.h>
#ifdef CONFIG_PPC64
#include "ppc32.h"
#include <asm/unistd.h>
@@ -996,6 +997,9 @@ long sys_swapcontext(struct ucontext __u
|| put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked)
|| __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
return -EFAULT;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ thread_change_pc(current, new_msr);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
}
if (new_ctx == NULL)
return 0;
@@ -1034,6 +1038,9 @@ long sys_rt_sigreturn(int r3, int r4, in
(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
goto bad;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ sigreturn_uninstall_bp(current);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
if (do_setcontext(&rt_sf->uc, regs, 1))
goto bad;
@@ -1279,6 +1286,9 @@ long sys_sigreturn(int r3, int r4, int r
#endif
restore_sigmask(&set);
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ sigreturn_uninstall_bp(current);
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
addr = sr;
if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
^ permalink raw reply
* [Patch 0/4] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver XX
From: K.Prasad @ 2010-05-24 10:31 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, Roland McGrath
Hi All,
Here's a quick release of the next version of the patchset with a
small, yet significant changelog.
Please let me know the comments, if any.
Changelog - ver XX
--------------------
(Version XIX: linuxppc-dev ref: 20100524040137.GA20873@in.ibm.com)
- Non task-bound breakpoints will only be emulated. Breakpoint will be
unregistered with a warning if emulation fails.
Thanks,
K.Prasad
Changelog - ver XIX
--------------------
(Version XVIII: linuxppc-dev ref: 20100512033055.GA6384@in.ibm.com)
- Increased coverage of breakpoints during concurrent alignment_exception
and signal handling (which previously had 'blind-spots').
- Support for kernel-thread breakpoints and kernel-space breakpoints inside the
context of a user-space process.
- Patches re-based to commit f4b87dee923342505e1ddba8d34ce9de33e75050, thereby
necessitating minor changes to arch_validate_hwbkpt_settings().
Changelog - ver XVIII
--------------------
(Version XVII: linuxppc-dev ref: 20100414034340.GA6571@in.ibm.com)
- hw-breakpoint restoration variables are cleaned-up before unregistration
through a new function hook arch_unregister_hw_breakpoint().
- emulate_single_step() now notifies DIE_SSTEP to registered handlers;
causes single_step_dabr_instruction() to be invoked after alignment_exception.
- SIGTRAP is no longer generated for non-ptrace user-space breakpoints.
- Slight code restructuring for brevity and style corrections.
Changelog - ver XVII
--------------------
(Version XVI: linuxppc-dev ref: 20100330095809.GA14403@in.ibm.com)
- CONFIG_HAVE_HW_BREAKPOINT is now used to define the scope of the new code
(in lieu of CONFIG_PPC_BOOK3S_64).
- CONFIG_HAVE_HW_BREAKPOINT is now dependant upon CONFIG_PERF_EVENTS and
CONFIG_PPC_BOOK3S_64 (to overcome build failures under certain configs).
- Included a target in arch/powerpc/lib/Makefile to build sstep.o when
HAVE_HW_BREAKPOINT.
- Added a dummy definition for hw_breakpoint_disable() when !HAVE_HW_BREAKPOINT.
- Tested builds under defconfigs for ppc64, cell and g5 (found no patch induced
failures).
Changelog - ver XVI
--------------------
(Version XV: linuxppc-dev ref: 20100323140639.GA21836@in.ibm.com)
- Used a new config option CONFIG_PPC_BOOK3S_64 (in lieu of
CONFIG_PPC64/CPU_FTR_HAS_DABR) to limit the scope of the new code.
- Disabled breakpoints before kexec of the machine using hw_breakpoint_disable().
- Minor optimisation in exception-64s.S to check for data breakpoint exceptions
in DSISR finally (after check for other causes) + changes in code comments and
representation of DSISR_DABRMATCH constant.
- Rebased to commit ae6be51ed01d6c4aaf249a207b4434bc7785853b of linux-2.6.
Changelog - ver XV
--------------------
(Version XIV: linuxppc-dev ref: 20100308181232.GA3406@in.ibm.com)
- Additional patch to disable interrupts during data breakpoint exception
handling.
- Moved HBP_NUM definition to cputable.h under a new CPU_FTR definition
(CPU_FTR_HAS_DABR).
- Filtering of extraneous exceptions (due to accesses outside symbol length) is
by-passed for ptrace requests.
- Removed flush_ptrace_hw_breakpoint() from __switch_to() due to incorrect
coding placement.
- Changes to code comments as per community reviews for previous version.
- Minor coding-style changes in hw_breakpoint.c as per review comments.
- Re-based to commit ae6be51ed01d6c4aaf249a207b4434bc7785853b of linux-2.6
Changelog - ver XIV
--------------------
(Version XIII: linuxppc-dev ref: 20100215055605.GB3670@in.ibm.com)
- Removed the 'name' field from 'struct arch_hw_breakpoint'.
- All callback invocations through bp->overflow_handler() are replaced with
perf_bp_event().
- Removed the check for pre-existing single-stepping mode in
hw_breakpoint_handler() as this check is unreliable while in kernel-space.
Side effect of this change is the non-triggering of hw-breakpoints while
single-stepping kernel through KGDB or Xmon.
- Minor code-cleanups and addition of comments in hw_breakpoint_handler() and
single_step_dabr_instruction().
- Re-based to commit 25cf84cf377c0aae5dbcf937ea89bc7893db5176 of linux-2.6
Changelog - ver XIII
--------------------
(Version XII: linuxppc-dev ref: 20100121084640.GA3252@in.ibm.com)
- Fixed a bug for user-space breakpoints (triggered following the failure of a
breakpoint request).
- Re-based on commit 724e6d3fe8003c3f60bf404bf22e4e331327c596 of linux-2.6
Changelog - ver XII
--------------------
(Version XI: linuxppc-dev ref: 20100119091234.GA9971@in.ibm.com)
- Unset MSR_SE only if kernel was not previously in single-step mode.
- Pre-emption is now enabled before returning from the hw-breakpoint exception
handler.
- Variables to track the source of single-step exception (breakpoint from kernel,
user-space vs single-stepping due to other requests) are added.
- Extraneous hw-breakpoint exceptions (due to memory accesses lying outside
monitored symbol length) is now done for both kernel and user-space
(previously only user-space).
- single_step_dabr_instruction() now returns NOTIFY_DONE if kernel was in
single-step mode even before the hw-breakpoint. This enables other users of
single-step mode to be notified of the exception.
- User-space instructions are not emulated from kernel-space, they are instead
single-stepped.
Changelog - ver XI
------------------
(Version X: linuxppc-dev ref: 20091211160144.GA23156@in.ibm.com)
- Conditionally unset MSR_SE in the single-step handler
- Added comments to explain the duration and need for pre-emption
disable following hw-breakpoint exception.
Changelog - ver X
------------------
- Re-write the PPC64 patches for the new implementation of hw-breakpoints that
uses the perf-layer.
- Rebased to commit 7622fc234190a37d4e9fe3ed944a2b61a63fca03 of -tip.
Changelog - ver IX
-------------------
- Invocation of user-defined callback will be 'trigger-after-execute' (except
for ptrace).
- Creation of a new global per-CPU breakpoint structure to help invocation of
user-defined callback from single-step handler.
(Changes made now)
- Validation before registration will fail only if the address does not match
the kernel symbol's (if specified) resolved address
(through kallsyms_lookup_name()).
- 'symbolsize' value is expected to within the range contained by the symbol's
starting address and the end of a double-word boundary (8 Bytes).
- PPC64's arch-dependant code is now aware of 'cpumask' in 'struct hw_breakpoint'
and can accomodate requests for a subset of CPUs in the system.
- Introduced arch_disable_hw_breakpoint() required for
<enable><disable>_hw_breakpoint() APIs.
Changelog - ver VIII
-------------------
- Reverting changes to allow one-shot breakpoints only for ptrace requests.
- Minor changes in sanity checking in arch_validate_hwbkpt_settings().
- put_cpu_no_resched() is no longer available. Converted to put_cpu().
Changelog - ver VII
-------------------
- Allow the one-shot behaviour for exception handlers to be defined by the user.
A new 'is_one_shot' flag is added to 'struct arch_hw_breakpoint'.
Changelog - ver VI
------------------
The task of identifying 'genuine' breakpoint exceptions from those caused by
'out-of-range' accesses turned out to be more tricky than originally thought.
Some changes to this effect were made in version IV of this patchset, but they
were not sufficient for user-space. Basically the breakpoint address received
through ptrace is always aligned to 8-bytes since ptrace receives an encoded
'data' (consisting of address | translation_enable | bkpt_type), and the size of
the symbol is not known. However for kernel-space addresses, the symbol-size can
be determined using kallsyms_lookup_size_offset() and this is used to check if
DAR (in the exception context) is
'bkpt_address <= DAR <= (bkpt_address + symbol_size)', failing which we conclude
it as a stray exception.
The following changes are made to enable check:
- Addition of a symbolsize field in 'struct arch_hw_breakpoint' field.
- Store the size of the 'watched' kernel symbol into 'symbolsize' field in
arch_store_info(0 routine.
- Verify if the above described condition is true when is_one_shot is FALSE in
hw_breakpoint_handler().
Changelog - ver V
------------------
- Breakpoint requests from ptrace (for user-space) are designed to be one-shot
in PPC64. The patch contains changes to retain this behaviour by returning early
in hw_breakpoint_handler() [without re-initialising DABR] and unregistering the
user-space request in ptrace_triggered(). It is safe to make a
unregister_user_hw_breakpoint() call from the breakpoint exception context
[through ptrace_triggered()] without giving rise to circular locking-dependancy.
This is because there can be no kernel code running on the CPU (which received
the exception) with the same spinlock held.
- Minor change in 'type' member of 'struct arch_hw_breakpoint' from u8 to 'int'.
Changelog - ver IV
------------------
- While DABR register requires double-word (8 bytes) aligned addresses, i.e.
the breakpoint is active over a range of 8 bytes, PPC64 allows byte-level
addressability. This may lead to stray exceptions which have to be ignored in
hw_breakpoint_handler(), when DAR != (Breakpoint request address). However DABR
will be populated with the requested breakpoint address aligned to the previous
double-word address. The code is now modified to store user-requested address
in 'bp->info.address' but update the DABR with a double-word aligned address.
- Please note that the Data Breakpoint facility in Xmon is broken as of 2.6.29
and the same has not been integrated into this facility as described in Ver I.
Changelog - ver III
------------------
- Patches are based on commit 08f16e060bf54bdc34f800ed8b5362cdeda75d8b of -tip
tree.
- The declarations in arch/powerpc/include/asm/hw_breakpoint.h are done only if
CONFIG_PPC64 is defined. This eliminates the need to conditionally include this
header file.
- load_debug_registers() is done in start_secondary() i.e. during CPU
initialisation.
- arch_check_va_<> routines in hw_breakpoint.c are now replaced with a much
simpler is_kernel_addr() check in arch_validate_hwbkpt_settings()
- Return code of hw_breakpoint_handler() when triggered due to Lazy debug
register switching is now changed to NOTIFY_STOP.
- The ptrace code no longer sets the TIF_DEBUG task flag as it is proposed to
be done in register_user_hw_breakpoint() routine.
- hw_breakpoint_handler() is now modified to use hbp_kernel_pos value to
determine if the trigger was a user/kernel space address. The DAR register
value is checked with the address stored in 'struct hw_breakpoint' to avoid
handling of exceptions that belong to kprobe/Xmon.
Changelog - ver II
------------------
- Split the monolithic patch into six logical patches
- Changed the signature of arch_check_va_in_<user><kernel>space functions. They
are now marked static.
- HB_NUM is now called as HBP_NUM (to preserve a consistent short-name
convention)
- Introduced hw_breakpoint_disable() and changes to kexec code to disable
breakpoints before a reboot.
- Minor changes in ptrace code to use macro-defined constants instead of
numbers.
- Introduced a new constant definition INSTRUCTION_LEN in reg.h
^ permalink raw reply
* [Patch 1/4] Allow arch-specific cleanup before breakpoint unregistration
From: K.Prasad @ 2010-05-24 10:32 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org, Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, Alan Stern, K.Prasad,
Roland McGrath
In-Reply-To: <20100524102614.040177456@linux.vnet.ibm.com>
Certain architectures (such as PowerPC Book III S) have a need to cleanup
data-structures before the breakpoint is unregistered. This patch introduces
an arch-specific hook in release_bp_slot() along with a weak definition in
the form of a stub funciton.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
kernel/hw_breakpoint.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
Index: linux-2.6.ppc64_test/kernel/hw_breakpoint.c
===================================================================
--- linux-2.6.ppc64_test.orig/kernel/hw_breakpoint.c
+++ linux-2.6.ppc64_test/kernel/hw_breakpoint.c
@@ -242,6 +242,17 @@ toggle_bp_slot(struct perf_event *bp, bo
}
/*
+ * Function to perform processor-specific cleanup during unregistration
+ */
+__weak void arch_unregister_hw_breakpoint(struct perf_event *bp)
+{
+ /*
+ * A weak stub function here for those archs that don't define
+ * it inside arch/.../kernel/hw_breakpoint.c
+ */
+}
+
+/*
* Contraints to check before allowing this new breakpoint counter:
*
* == Non-pinned counter == (Considered as pinned for now)
@@ -339,6 +350,7 @@ void release_bp_slot(struct perf_event *
{
mutex_lock(&nr_bp_mutex);
+ arch_unregister_hw_breakpoint(bp);
__release_bp_slot(bp);
mutex_unlock(&nr_bp_mutex);
^ permalink raw reply
* Re: [Patch 2/2] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: K.Prasad @ 2010-05-24 15:49 UTC (permalink / raw)
To: Paul Mackerras
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, linuxppc-dev@ozlabs.org,
Alan Stern, Roland McGrath
In-Reply-To: <20100520131003.GB29903@brick.ozlabs.ibm.com>
On Thu, May 20, 2010 at 11:10:03PM +1000, Paul Mackerras wrote:
> On Thu, May 20, 2010 at 09:36:03AM +0530, K.Prasad wrote:
>
(Had this mail composed along with the patchset...but mail server issues
caused delay in sending this...)
Hi Paul,
While we continue to discuss some of the design decisions, I
thought I'd ready up a patchset to capture the changes we agreed upon to
(lest we miss them). I have sent a new version of the patchset here:
linuxppc-dev message-id: 20100524040137.GA20873@in.ibm.com.
Please see more responses below.
> > > Right. However, the thread is running the signal handler without the
> > > DABR being set, which is unfortunate.
> > >
> >
> > In order to keep the breakpoint active during signal handling, a
> > PowerPC specific signal handling code, say do_signal_pending() in
> > arch/powerpc/kernel/signal.c, must be tapped to check for/restore
> > the breakpoint for the process (if it exists).
>
> What I would suggest is something slightly different: anything that
> causes the thread to change where it's executing -- signal delivery,
> modification of NIP with ptrace -- should cancel the single-step and
> reinstall the breakpoint in the DABR. In other words we just forget
> that we hit the breakpoint, and rely on hitting it again if we ever
> get back to that instruction. I think that is by far the most
> reliable approach.
>
> That means that the hw-breakpoint code needs to export a function
> called, say, thread_change_pc(), which is called whenever we're
> changing a thread's userspace PC (NIP) value. If the hw-breakpoint
> code has put that thread into single-step mode, we cancel the
> single-step and if the thread is current, set DABR.
>
I have made changes to signal-handling code on the suggested lines (as
seen here: linuxppc-dev message-id:20100524040342.GE20873@in.ibm.com)
wherein the debug registers are populated before signal-delivery and
cleaned during signal-return.
However handling of nested interrupts, where second exception is taken
inside the signal handler is still flimsy and the system would experience
two hw-breakpoint exceptions. To overcome the same, we will need a flag in
'struct thread_struct' or perhaps in 'struct arch_hw_breakpoint' to
indicate a breakpoint previously taken in signal-handling context. Given
that the repurcussions of a double-hit are not dangerous, and unsure of
how an addition to thread_struct might be received, I've skipped those
changes for now.
> > I'm afraid if this is more complexity than we want to handle in the
> > first patchset. I agree that this will create a 'blind-spot' of code
> > which cannot not be monitored using breakpoints and may limit debugging
> > efforts (specially for memory corruption); however suspecting that signal
> > handlers (especially those that don't return to original instruction)
> > would be rare, I feel that this could be a 'feature' that can be brought
> > later-in. What do you think?
>
> I think the thread_change_pc() approach is quite a bit simpler, and I
> think it's better to get this right at the outset rather than have it
> cause bugs later on, when we've all forgotten all the curly
> details. :)
Yes, the details are mostly captured in the latest patchset. Had to make
some 'bold' changes to overcome the issues though :-)
>
> > > Imagine this scenario: we get the DABR match, set MSR_SE and return to
> > > the task. In the meantime another higher-priority task has become
> > > runnable and our need_resched flag is set, so we call schedule() on
> > > the way back out to usermode. The other task runs and then blocks and
> > > our task gets scheduled again. As part of the context switch,
> > > arch_install_hw_breakpoint() will get called and will set DABR. So
> > > we'll return to usermode with both DABR and MSE_SE set.
> > >
> >
> > I didn't foresee such a possibility. I think this can be handled by
> > putting a check in arch_install_hw_breakpoint() as shown below:
> >
> > int arch_install_hw_breakpoint(struct perf_event *bp)
> > {
> > struct arch_hw_breakpoint *info = counter_arch_bp(bp);
> > struct perf_event **slot = &__get_cpu_var(bp_per_reg);
> >
> > *slot = bp;
> > if (!current->thread.last_hit_ubp)
> > set_dabr(info->address | info->type | DABR_TRANSLATION);
> > return 0;
> > }
>
> Yes, basically, but don't we need to handle per-cpu breakpoints as
> well? That is, we only want the extra check if this breakpoint is a
> per-task breakpoint. Or am I not seeing enough context here?
>
Until version XVIII of the patchset, the antiquated notion of user- and
kernel-space still existed to some extent. Through changes made here
(reference: linuxppc-dev message-id: 20100524040418.GF20873@in.ibm.com)
per-task (whose pid > 0) and per-cpu breakpoints are suitably identified.
Now, per-task breakpoints can be one of the following
- User-space breakpoints bound to a process 'struct task_struct'.
- Kernel-space breakpoints bound to a process 'struct task_struct'.
- Kernel-thread breakpoint registered through
register_user_hw_breakpoint() and still identified through 'struct
task_struct' after cpu-migration.
The above type of breakpoints may be restricted to a given cpu, yet they
are identifiable through the 'task_struct'.
I am unable to think of a case where a cpu-bound breakpoint request
(essentially a kernel-space address request) without a process context
(i.e. no identifiable 'task_struct') could be scheduled and migrated
across CPUs.
Moving to version XX, the emulation of instructions during non-pertask
breakpoints does not provide a scope for pre-emption at all. Hence the
above check should suffice in either case.
> Also, I have just posted extensions to emulate_single_step() to handle
> loads and stores. I think this should be enough to handle DABR
> interrupts that occur in kernel mode, so we should never need to
> actually single-step in that case -- if emulate_step fails we should
> just print a warning, uninstall the breakpoint, and continue. That
> way we don't have to worry about all the interrupts and other
> eventualities that could occur while single-stepping in the kernel.
>
It was beginning to respond to this section of the mail did I realise
that I failed to implement the suggestion to unregister breakpoint if
emulate_singlestep() failed; and hence the quick successive release of
version XX of the patchset :-)
It is true that if emulate_single_step() was powerful, it simplifies the
design to a large extent. However during my test (with the extensions to
emulate_single_step() applied), I found that the startup test for ftrace
(over ksym_tracer) failed as the breakpoint got unregistered (as a
consequence of emulate_single_step() failure).
I'm not sure if I missed something here...pasting the relevant disassembly
of code below.
0xc000000000138a2c <trace_selftest_startup_ksym+124>: mr r29,r3
0xc000000000138a30 <trace_selftest_startup_ksym+128>: blt cr7,0xc000000000138aac <trace_selftest_startup_ksym+252>
0xc000000000138a34 <trace_selftest_startup_ksym+132>: lwz r0,0(r28) <===== FAILED INSTRUCTION
0xc000000000138a38 <trace_selftest_startup_ksym+136>: cmpwi cr7,r0,0
0xc000000000138a3c <trace_selftest_startup_ksym+140>: bne cr7,0xc000000000138a48 <trace_selftest_startup_ksym+152>
> For DABR interrupts that occur in user mode, I think the approach of
> single-stepping together with calls to thread_change_pc() in the
> signal delivery and ptrace code should handle all the cases, at least
> for per-task breakpoints. Per-cpu breakpoints that get hit in user
> mode will be a bit trickier, but I assume we can restrict per-cpu
> breakpoints to kernel addresses for now. If you want help adding the
> thread_change_pc() calls to signal delivery and ptrace, let me know.
The newer patchsets should be taking care of such combinations i.e.
kernel-space address for a per-task/per-cpu breakpoint and user-space
breakpoint which is per-cpu. Implementations found in version XIX and
XX, handle the constraints in their own way (although version XX is much
simpler if emulate_single_step() mostly works).
In the absence of any adverse comments and given a powerful
emulate_single_step() which works for most instructions, I'd prefer to
push the version XX of the patchset for upstream integration.
Thanking you again for your help/review comments. Let me know your
thoughts on the newer patchset.
Thanks,
K.Prasad
^ permalink raw reply
* [PATCH v2] powerpc: Add i8042 keyboard and mouse irq parsing
From: Martyn Welch @ 2010-05-24 16:25 UTC (permalink / raw)
To: Grant Likely, benh; +Cc: linuxppc-dev, Dmitry Torokhov, linux-input
Currently the irqs for the i8042, which historically provides keyboard and
mouse (aux) support, is hardwired in the driver rather than parsing the
dts. This patch modifies the powerpc legacy IO code to attempt to parse
the device tree for this information, failing back to the hardcoded values
if it fails.
Signed-off-by: Martyn Welch <martyn.welch@ge.com>
---
v2: This patch no longer requires the DTS files to be modified, reading the
interrupts from the current location as suggested by Grant.
arch/powerpc/kernel/setup-common.c | 49 ++++++++++++++++++++++++++++++++++--
drivers/input/serio/i8042-io.h | 8 ++++++
2 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 48f0a00..7f1bb99 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -94,6 +94,10 @@ struct screen_info screen_info = {
.orig_video_points = 16
};
+/* Variables required to store legacy IO irq routing */
+int of_i8042_kbd_irq;
+int of_i8042_aux_irq;
+
#ifdef __DO_IRQ_CANON
/* XXX should go elsewhere eventually */
int ppc_do_canonicalize_irqs;
@@ -558,13 +562,52 @@ void probe_machine(void)
/* Match a class of boards, not a specific device configuration. */
int check_legacy_ioport(unsigned long base_port)
{
- struct device_node *parent, *np = NULL;
+ struct device_node *parent, *np = NULL, *np_aux = NULL;
int ret = -ENODEV;
switch(base_port) {
case I8042_DATA_REG:
- if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
- np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+ np = of_find_compatible_node(NULL, NULL, "pnpPNP,303");
+ if (np) {
+ /* Interrupt routing in parent node */
+ parent = of_get_parent(np);
+ if (parent) {
+ /*
+ * Attempt to parse DTS for keyboard irq,
+ * fallback to standard.
+ */
+ of_i8042_kbd_irq = irq_of_parse_and_map(parent,
+ 0);
+ if (!of_i8042_kbd_irq)
+ of_i8042_kbd_irq = 1;
+
+ of_node_put(parent);
+ }
+ }
+
+ np_aux = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+ if (np_aux) {
+ if (!np) {
+ of_node_put(np);
+ np = np_aux;
+ }
+
+ /* Interrupt routing in parent node */
+ parent = of_get_parent(np_aux);
+ if (parent) {
+ /*
+ * Attempt to parse DTS for mouse (aux) irq,
+ * fallback to standard.
+ */
+ of_i8042_aux_irq = irq_of_parse_and_map(parent,
+ 1);
+ if (!of_i8042_aux_irq)
+ of_i8042_aux_irq = 12;
+
+ of_node_put(parent);
+ }
+ }
+
if (np) {
parent = of_get_parent(np);
of_node_put(np);
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 847f4aa..8fc8753 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -19,6 +19,11 @@
* IRQs.
*/
+#if defined(CONFIG_PPC)
+extern int of_i8042_kbd_irq;
+extern int of_i8042_aux_irq;
+#endif
+
#ifdef __alpha__
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
@@ -27,6 +32,9 @@
#include <asm/irq.h>
#elif defined(CONFIG_SH_CAYMAN)
#include <asm/irq.h>
+#elif defined(CONFIG_PPC)
+#define I8042_KBD_IRQ of_i8042_kbd_irq
+#define I8042_AUX_IRQ of_i8042_aux_irq
#else
# define I8042_KBD_IRQ 1
# define I8042_AUX_IRQ 12
--
Martyn Welch (Principal Software Engineer) | Registered in England and
GE Intelligent Platforms | Wales (3828642) at 100
T +44(0)127322748 | Barbirolli Square, Manchester,
E martyn.welch@ge.com | M2 3AB VAT:GB 927559189
^ permalink raw reply related
* Re: [PATCH v2] powerpc: Add i8042 keyboard and mouse irq parsing
From: Grant Likely @ 2010-05-24 17:33 UTC (permalink / raw)
To: Martyn Welch; +Cc: Dmitry Torokhov, linux-input, linuxppc-dev
In-Reply-To: <20100524162325.11133.8579.stgit@ES-J7S4D2J.amer.consind.ge.com>
On Mon, May 24, 2010 at 10:25 AM, Martyn Welch <martyn.welch@ge.com> wrote:
> Currently the irqs for the i8042, which historically provides keyboard an=
d
> mouse (aux) support, is hardwired in the driver rather than parsing the
> dts. =A0This patch modifies the powerpc legacy IO code to attempt to pars=
e
> the device tree for this information, failing back to the hardcoded value=
s
> if it fails.
>
> Signed-off-by: Martyn Welch <martyn.welch@ge.com>
> ---
>
> v2: This patch no longer requires the DTS files to be modified, reading t=
he
> interrupts from the current location as suggested by Grant.
>
> =A0arch/powerpc/kernel/setup-common.c | =A0 49 ++++++++++++++++++++++++++=
++++++++--
> =A0drivers/input/serio/i8042-io.h =A0 =A0 | =A0 =A08 ++++++
> =A02 files changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/set=
up-common.c
> index 48f0a00..7f1bb99 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -94,6 +94,10 @@ struct screen_info screen_info =3D {
> =A0 =A0 =A0 =A0.orig_video_points =3D 16
> =A0};
>
> +/* Variables required to store legacy IO irq routing */
> +int of_i8042_kbd_irq;
> +int of_i8042_aux_irq;
> +
> =A0#ifdef __DO_IRQ_CANON
> =A0/* XXX should go elsewhere eventually */
> =A0int ppc_do_canonicalize_irqs;
> @@ -558,13 +562,52 @@ void probe_machine(void)
> =A0/* Match a class of boards, not a specific device configuration. */
> =A0int check_legacy_ioport(unsigned long base_port)
> =A0{
> - =A0 =A0 =A0 struct device_node *parent, *np =3D NULL;
> + =A0 =A0 =A0 struct device_node *parent, *np =3D NULL, *np_aux =3D NULL;
> =A0 =A0 =A0 =A0int ret =3D -ENODEV;
>
> =A0 =A0 =A0 =A0switch(base_port) {
> =A0 =A0 =A0 =A0case I8042_DATA_REG:
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(np =3D of_find_compatible_node(NULL, =
NULL, "pnpPNP,303")))
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_compatible_n=
ode(NULL, NULL, "pnpPNP,f03");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, =
"pnpPNP,303");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Interrupt routing in par=
ent node */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 parent =3D of_get_parent(np=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (parent) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Attemp=
t to parse DTS for keyboard irq,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* fallba=
ck to standard.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_i8042_kb=
d_irq =3D irq_of_parse_and_map(parent,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!of_i80=
42_kbd_irq)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 of_i8042_kbd_irq =3D 1;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put=
(parent);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np_aux =3D of_find_compatible_node(NULL, NU=
LL, "pnpPNP,f03");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (np_aux) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put=
(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D np_a=
ux;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Interrupt routing in par=
ent node */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 parent =3D of_get_parent(np=
_aux);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (parent) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Attemp=
t to parse DTS for mouse (aux) irq,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* fallba=
ck to standard.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_i8042_au=
x_irq =3D irq_of_parse_and_map(parent,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!of_i80=
42_aux_irq)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 of_i8042_aux_irq =3D 12;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put=
(parent);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
This seems to be a lot more code that you need. The existing code
already obtains a pointer to the parent node for you. All you really
should need to add is the two calls to irq_of_parse_and_map() for
obtaining the kbd and aux irq numbers.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (np) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0parent =3D of_get_parent(n=
p);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0of_node_put(np);
> diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-i=
o.h
> index 847f4aa..8fc8753 100644
> --- a/drivers/input/serio/i8042-io.h
> +++ b/drivers/input/serio/i8042-io.h
> @@ -19,6 +19,11 @@
> =A0* IRQs.
> =A0*/
>
> +#if defined(CONFIG_PPC)
> +extern int of_i8042_kbd_irq;
> +extern int of_i8042_aux_irq;
> +#endif
Please fold these two extern definitions into the #elif
defined(CONFIG_PPC) block below.
> +
> =A0#ifdef __alpha__
> =A0# define I8042_KBD_IRQ 1
> =A0# define I8042_AUX_IRQ (RTC_PORT(0) =3D=3D 0x170 ? 9 : 12) /* Jensen i=
s special */
> @@ -27,6 +32,9 @@
> =A0#include <asm/irq.h>
> =A0#elif defined(CONFIG_SH_CAYMAN)
> =A0#include <asm/irq.h>
> +#elif defined(CONFIG_PPC)
> +#define I8042_KBD_IRQ =A0of_i8042_kbd_irq
> +#define I8042_AUX_IRQ =A0of_i8042_aux_irq
> =A0#else
> =A0# define I8042_KBD_IRQ 1
> =A0# define I8042_AUX_IRQ 12
Cheers,
g.
^ permalink raw reply
* [PATCH] powerpc/fsl-booke: Fix InstructionTLBError execute permission check
From: Kumar Gala @ 2010-05-24 18:38 UTC (permalink / raw)
To: stable; +Cc: linuxppc-dev
In-Reply-To: <1274726319-4673-1-git-send-email-galak@kernel.crashing.org>
From: Li Yang <leoli@freescale.com>
In CONFIG_PTE_64BIT the PTE format has unique permission bits for user
and supervisor execute. However on !CONFIG_PTE_64BIT we overload the
supervisor bit to imply user execute with _PAGE_USER set. This allows
us to use the same permission check mask for user or supervisor code on
!CONFIG_PTE_64BIT.
However, on CONFIG_PTE_64BIT we map _PAGE_EXEC to _PAGE_BAP_UX so we
need a different permission mask based on the fault coming from a kernel
address or user space.
Without unique permission masks we see issues like the following with
modules:
Unable to handle kernel paging request for instruction fetch
Faulting instruction address: 0xf938d040
Oops: Kernel access of bad area, sig: 11 [#1]
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
For 2.6.34 stable commit 78e2e68a2b79f394b7cd61e07987a8a89af907f7
arch/powerpc/kernel/head_fsl_booke.S | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 7255265..edd4a57 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -639,6 +639,13 @@ interrupt_base:
rlwinm r12,r12,0,16,1
mtspr SPRN_MAS1,r12
+ /* Make up the required permissions for kernel code */
+#ifdef CONFIG_PTE_64BIT
+ li r13,_PAGE_PRESENT | _PAGE_BAP_SX
+ oris r13,r13,_PAGE_ACCESSED@h
+#else
+ li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
+#endif
b 4f
/* Get the PGD for the current thread */
@@ -646,15 +653,15 @@ interrupt_base:
mfspr r11,SPRN_SPRG_THREAD
lwz r11,PGDIR(r11)
-4:
- /* Make up the required permissions */
+ /* Make up the required permissions for user code */
#ifdef CONFIG_PTE_64BIT
- li r13,_PAGE_PRESENT | _PAGE_EXEC
+ li r13,_PAGE_PRESENT | _PAGE_BAP_UX
oris r13,r13,_PAGE_ACCESSED@h
#else
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
#endif
+4:
FIND_PTE
andc. r13,r13,r11 /* Check permission */
--
1.6.0.6
^ permalink raw reply related
* [PATCH] powerpc/fsl-booke: Move loadcam_entry back to asm code to fix SMP ftrace
From: Kumar Gala @ 2010-05-24 18:38 UTC (permalink / raw)
To: stable; +Cc: linuxppc-dev
In-Reply-To: <1274726319-4673-2-git-send-email-galak@kernel.crashing.org>
When we build with ftrace enabled its possible that loadcam_entry would
have used the stack pointer (even though the code doesn't need it). We
call loadcam_entry in __secondary_start before the stack is setup. To
ensure that loadcam_entry doesn't use the stack pointer the easiest
solution is to just have it in asm code.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
For 2.6.34 stable commit 78f622377f7d31d988db350a43c5689dd5f31876
arch/powerpc/kernel/asm-offsets.c | 8 ++++++++
arch/powerpc/mm/fsl_booke_mmu.c | 25 +++----------------------
arch/powerpc/mm/mmu_decl.h | 10 +++++++++-
arch/powerpc/mm/tlb_nohash_low.S | 28 ++++++++++++++++++++++++++++
4 files changed, 48 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 957ceb7..0271b58 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -448,6 +448,14 @@ int main(void)
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
#endif
+#ifdef CONFIG_FSL_BOOKE
+ DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
+ DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
+ DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
+ DEFINE(TLBCAM_MAS2, offsetof(struct tlbcam, MAS2));
+ DEFINE(TLBCAM_MAS3, offsetof(struct tlbcam, MAS3));
+ DEFINE(TLBCAM_MAS7, offsetof(struct tlbcam, MAS7));
+#endif
#ifdef CONFIG_KVM_EXIT_TIMING
DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 1ed6b52..cdc7526 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -2,7 +2,7 @@
* Modifications by Kumar Gala (galak@kernel.crashing.org) to support
* E500 Book E processors.
*
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright 2004,2010 Freescale Semiconductor, Inc.
*
* This file contains the routines for initializing the MMU
* on the 4xx series of chips.
@@ -56,19 +56,13 @@
unsigned int tlbcam_index;
-#define NUM_TLBCAMS (64)
#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
#endif
-struct tlbcam {
- u32 MAS0;
- u32 MAS1;
- unsigned long MAS2;
- u32 MAS3;
- u32 MAS7;
-} TLBCAM[NUM_TLBCAMS];
+#define NUM_TLBCAMS (64)
+struct tlbcam TLBCAM[NUM_TLBCAMS];
struct tlbcamrange {
unsigned long start;
@@ -109,19 +103,6 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
return 0;
}
-void loadcam_entry(int idx)
-{
- mtspr(SPRN_MAS0, TLBCAM[idx].MAS0);
- mtspr(SPRN_MAS1, TLBCAM[idx].MAS1);
- mtspr(SPRN_MAS2, TLBCAM[idx].MAS2);
- mtspr(SPRN_MAS3, TLBCAM[idx].MAS3);
-
- if (mmu_has_feature(MMU_FTR_BIG_PHYS))
- mtspr(SPRN_MAS7, TLBCAM[idx].MAS7);
-
- asm volatile("isync;tlbwe;isync" : : : "memory");
-}
-
/*
* Set up one of the I/D BAT (block address translation) register pairs.
* The parameters are not checked; in particular size must be a power
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index eb11d5d..63b84a0 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -144,7 +144,15 @@ extern unsigned long mmu_mapin_ram(unsigned long top);
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
extern void adjust_total_lowmem(void);
-
+extern void loadcam_entry(unsigned int index);
+
+struct tlbcam {
+ u32 MAS0;
+ u32 MAS1;
+ unsigned long MAS2;
+ u32 MAS3;
+ u32 MAS7;
+};
#elif defined(CONFIG_PPC32)
/* anything 32-bit except 4xx or 8xx */
extern void MMU_init_hw(void);
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index e925cb5..cfa7682 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -365,3 +365,31 @@ _GLOBAL(set_context)
#else
#error Unsupported processor type !
#endif
+
+#if defined(CONFIG_FSL_BOOKE)
+/*
+ * extern void loadcam_entry(unsigned int index)
+ *
+ * Load TLBCAM[index] entry in to the L2 CAM MMU
+ */
+_GLOBAL(loadcam_entry)
+ LOAD_REG_ADDR(r4, TLBCAM)
+ mulli r5,r3,TLBCAM_SIZE
+ add r3,r5,r4
+ lwz r4,TLBCAM_MAS0(r3)
+ mtspr SPRN_MAS0,r4
+ lwz r4,TLBCAM_MAS1(r3)
+ mtspr SPRN_MAS1,r4
+ PPC_LL r4,TLBCAM_MAS2(r3)
+ mtspr SPRN_MAS2,r4
+ lwz r4,TLBCAM_MAS3(r3)
+ mtspr SPRN_MAS3,r4
+BEGIN_MMU_FTR_SECTION
+ lwz r4,TLBCAM_MAS7(r3)
+ mtspr SPRN_MAS7,r4
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
+ isync
+ tlbwe
+ isync
+ blr
+#endif
--
1.6.0.6
^ permalink raw reply related
* [PATCH] powerpc: Fix ioremap_flags() with book3e pte definition
From: Kumar Gala @ 2010-05-24 18:38 UTC (permalink / raw)
To: stable; +Cc: linuxppc-dev
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
We can't just clear the user read permission in book3e pte, because
that will also clear supervisor read permission. This surely isn't
desired. Fix the problem by adding the supervisor read back.
BenH: Slightly simplified the ifdef and applied to ppc64 too
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
For 2.6.34 stable commit 55052eeca6d71d76f7c3f156c0501814d8e5e6d3
arch/powerpc/mm/pgtable_32.c | 8 ++++++++
arch/powerpc/mm/pgtable_64.c | 8 ++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index b9243e7..767b0cf 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -146,6 +146,14 @@ ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags)
/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
flags &= ~(_PAGE_USER | _PAGE_EXEC);
+#ifdef _PAGE_BAP_SR
+ /* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
+ * which means that we just cleared supervisor access... oops ;-) This
+ * restores it
+ */
+ flags |= _PAGE_BAP_SR;
+#endif
+
return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
}
EXPORT_SYMBOL(ioremap_flags);
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index d95679a..d050fc8 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -265,6 +265,14 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
flags &= ~(_PAGE_USER | _PAGE_EXEC);
+#ifdef _PAGE_BAP_SR
+ /* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
+ * which means that we just cleared supervisor access... oops ;-) This
+ * restores it
+ */
+ flags |= _PAGE_BAP_SR;
+#endif
+
if (ppc_md.ioremap)
return ppc_md.ioremap(addr, size, flags, caller);
return __ioremap_caller(addr, size, flags, caller);
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH 2/3] powerpc/fsl head: move the entry setup code into a seperate file
From: Kumar Gala @ 2010-05-24 19:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1270412343-19334-3-git-send-email-sebastian@breakpoint.cc>
On Apr 4, 2010, at 3:19 PM, Sebastian Andrzej Siewior wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>=20
> This patch only moves the initial entry code which setups the mapping
> from what ever to KERNELBASE into a seperate file. No code change has
> been made here.
>=20
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> arch/powerpc/kernel/fsl_booke_entry_mapping.S | 200 =
+++++++++++++++++++++++++
> arch/powerpc/kernel/head_fsl_booke.S | 199 =
+------------------------
> 2 files changed, 201 insertions(+), 198 deletions(-)
> create mode 100644 arch/powerpc/kernel/fsl_booke_entry_mapping.S
applied to next
- k=
^ permalink raw reply
* Re: [PATCH 1/3] powerpc/head fsl: fix the case where we are not in the first page
From: Kumar Gala @ 2010-05-24 19:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1270412343-19334-2-git-send-email-sebastian@breakpoint.cc>
On Apr 4, 2010, at 3:19 PM, Sebastian Andrzej Siewior wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> During boot we change the mapping a few times until we have a "defined"
> mapping. During this procedure a small 4KiB mapping is created and after
> that one a 64MiB. Currently the offset of the 4KiB page in that we run
> is zero because the complete startup up code is in first page which
> starts at RPN zero.
> If the code is recycled and moved to another location then its execution
> will fail because the start address in 64 MiB mapping is computed
> wrongly. It does not consider the offset to the page from the begin of
> the memory.
> This patch fixes this. Usually (system boot) r25 is zero so this does
> not change anything unless the code is recycled.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> arch/powerpc/kernel/head_fsl_booke.S | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH 3/3] powerpc/kexec: Add support for FSL-BookE
From: Kumar Gala @ 2010-05-24 19:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1270412343-19334-4-git-send-email-sebastian@breakpoint.cc>
On Apr 4, 2010, at 3:19 PM, Sebastian Andrzej Siewior wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>=20
> This adds support kexec on FSL-BookE where the MMU can not be simply
> switched off. The code borrows the initial MMU-setup code to create =
the
> identical mapping mapping. The only difference to the original boot =
code
> is the size of the mapping(s) and the executeable address.
> The kexec code maps the first 2 GiB of memory in 256 MiB steps. This
> should work also on e500v1 boxes.
> SMP support is still not available.
>=20
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> arch/powerpc/Kconfig | 2 +-
> arch/powerpc/include/asm/kexec.h | 13 +++++++++
> arch/powerpc/kernel/fsl_booke_entry_mapping.S | 37 =
+++++++++++++++++++++++++
> arch/powerpc/kernel/head_fsl_booke.S | 2 +
> arch/powerpc/kernel/misc_32.S | 17 +++++++++++
> 5 files changed, 70 insertions(+), 1 deletions(-)
applied to next
- k=
^ permalink raw reply
* Re: [PATCH v3 1/5] fsl_msi: fix the conflict of virt_msir's chip_data
From: Kumar Gala @ 2010-05-24 19:12 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, Zhao Chenhui
In-Reply-To: <1271925099-29100-1-git-send-email-leoli@freescale.com>
On Apr 22, 2010, at 3:31 AM, Li Yang wrote:
> In fsl_of_msi_probe(), the virt_msir's chip_data have been stored
> the pointer to struct mpic. We add a struct fsl_msi_cascade_data
> to store the pointer to struct fsl_msi and msir_index in hanler_data.
> Otherwise, the pointer to struct mpic will be over-written, and will
> cause problem when calling eoi() of the irq.
>
> Signed-off-by: Zhao Chenhui <b26998@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_msi.c | 33 +++++++++++++++++++++++++++------
> 1 files changed, 27 insertions(+), 6 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH v3 2/5] fsl_msi: enable msi allocation in all banks
From: Kumar Gala @ 2010-05-24 19:12 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, Zhao Chenhui
In-Reply-To: <1271925099-29100-2-git-send-email-leoli@freescale.com>
On Apr 22, 2010, at 3:31 AM, Li Yang wrote:
> Put all fsl_msi banks in a linked list. The list of banks then can be
> traversed when allocating new msi interrupts. Also fix failing path
> of fsl_setup_msi_irqs().
>
> Signed-off-by: Zhao Chenhui <b26998@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_msi.c | 14 +++++++++++---
> arch/powerpc/sysdev/fsl_msi.h | 2 ++
> 2 files changed, 13 insertions(+), 3 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH v3 3/5] fsl_msi: enable msi sharing through AMP OSes
From: Kumar Gala @ 2010-05-24 19:12 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, Zhao Chenhui
In-Reply-To: <1271925099-29100-3-git-send-email-leoli@freescale.com>
On Apr 22, 2010, at 3:31 AM, Li Yang wrote:
> Make a single PCIe MSI bank shareable through CAMP OSes. The number of
> MSI used by each core can be configured by dts file.
>
> Signed-off-by: Zhao Chenhui <b26998@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_msi.c | 8 +++++++-
> 1 files changed, 7 insertions(+), 1 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH v3 4/5] mpc8572ds: change camp dtses for MSI sharing
From: Kumar Gala @ 2010-05-24 19:12 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, Zhao Chenhui
In-Reply-To: <1271925099-29100-4-git-send-email-leoli@freescale.com>
On Apr 22, 2010, at 3:31 AM, Li Yang wrote:
> Enable the sharing of MSI interrupt through AMP OSes in the mpc8572ds
> dtses.
>
> Signed-off-by: Zhao Chenhui <b26998@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts | 15 +++++++++++++--
> arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts | 7 ++-----
> 2 files changed, 15 insertions(+), 7 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH v3 5/5] fsl_msi: add removal path and probe failing path
From: Kumar Gala @ 2010-05-24 19:13 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev
In-Reply-To: <1271925099-29100-5-git-send-email-leoli@freescale.com>
On Apr 22, 2010, at 3:31 AM, Li Yang wrote:
> Also cleanup the probe function.
>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_msi.c | 36 ++++++++++++++++++++++++++++++------
> arch/powerpc/sysdev/fsl_msi.h | 1 +
> 2 files changed, 31 insertions(+), 6 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH 2/2] powerpc, kdump: Fix race in kdump shutdown
From: Kumar Gala @ 2010-05-24 19:23 UTC (permalink / raw)
To: Michael Neuling; +Cc: jlarrew, kexec, Anton Blanchard, linuxppc-dev
In-Reply-To: <20100514054011.5E585D34AB@localhost.localdomain>
On May 14, 2010, at 12:40 AM, Michael Neuling wrote:
> When we are crashing, the crashing/primary CPU IPIs the secondaries to
> turn off IRQs, go into real mode and wait in kexec_wait. While this
> is happening, the primary tears down all the MMU maps. Unfortunately
> the primary doesn't check to make sure the secondaries have entered
> real mode before doing this.
>=20
> On PHYP machines, the secondaries can take a long time shutting down
> the IRQ controller as RTAS calls are need. These RTAS calls need to
> be serialised which resilts in the secondaries contending in
> lock_rtas() and hence taking a long time to shut down.
>=20
> We've hit this on large POWER7 machines, where some secondaries are
> still waiting in lock_rtas(), when the primary tears down the HPTEs.
>=20
> This patch makes sure all secondaries are in real mode before the
> primary tears down the MMU. It uses the new kexec_state entry in the
> paca. It times out if the secondaries don't reach real mode after
> 10sec.
>=20
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
>=20
> arch/powerpc/kernel/crash.c | 27 +++++++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
>=20
> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> @@ -162,6 +162,32 @@ static void crash_kexec_prepare_cpus(int
> /* Leave the IPI callback set */
> }
>=20
> +/* wait for all the CPUs to hit real mode but timeout if they don't =
come in */
> +static void crash_kexec_wait_realmode(int cpu)
> +{
> + unsigned int msecs;
> + int i;
> +
> + msecs =3D 10000;
> + for (i=3D0; i < NR_CPUS && msecs > 0; i++) {
> + if (i =3D=3D cpu)
> + continue;
> +
> + while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
> + barrier();
> + if (!cpu_possible(i)) {
> + break;
> + }
> + if (!cpu_online(i)) {
> + break;
> + }
> + msecs--;
> + mdelay(1);
> + }
> + }
> + mb();
> +}
> +
> /*
> * This function will be called by secondary cpus or by kexec cpu
> * if soft-reset is activated to stop some CPUs.
> @@ -412,6 +438,7 @@ void default_machine_crash_shutdown(stru
> crash_kexec_prepare_cpus(crashing_cpu);
> cpu_set(crashing_cpu, cpus_in_crash);
> crash_kexec_stop_spus();
should this be
#ifdef CONFIG_PPC_STD_MMU
> + crash_kexec_wait_realmode(crashing_cpu);
#endif
- k
^ permalink raw reply
* Re: [PATCH 2/2] powerpc, kdump: Fix race in kdump shutdown
From: Kumar Gala @ 2010-05-24 19:29 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Michael Neuling, kexec, jlarrew, Anton Blanchard
In-Reply-To: <E722EF44-A08B-41E1-8ECA-D5BE46009128@kernel.crashing.org>
On May 24, 2010, at 2:23 PM, Kumar Gala wrote:
>=20
> On May 14, 2010, at 12:40 AM, Michael Neuling wrote:
>=20
>> When we are crashing, the crashing/primary CPU IPIs the secondaries =
to
>> turn off IRQs, go into real mode and wait in kexec_wait. While this
>> is happening, the primary tears down all the MMU maps. Unfortunately
>> the primary doesn't check to make sure the secondaries have entered
>> real mode before doing this.
>>=20
>> On PHYP machines, the secondaries can take a long time shutting down
>> the IRQ controller as RTAS calls are need. These RTAS calls need to
>> be serialised which resilts in the secondaries contending in
>> lock_rtas() and hence taking a long time to shut down.
>>=20
>> We've hit this on large POWER7 machines, where some secondaries are
>> still waiting in lock_rtas(), when the primary tears down the HPTEs.
>>=20
>> This patch makes sure all secondaries are in real mode before the
>> primary tears down the MMU. It uses the new kexec_state entry in the
>> paca. It times out if the secondaries don't reach real mode after
>> 10sec.
>>=20
>> Signed-off-by: Michael Neuling <mikey@neuling.org>
>> ---
>>=20
>> arch/powerpc/kernel/crash.c | 27 +++++++++++++++++++++++++++
>> 1 file changed, 27 insertions(+)
>>=20
>> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
>> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
>> @@ -162,6 +162,32 @@ static void crash_kexec_prepare_cpus(int
>> /* Leave the IPI callback set */
>> }
>>=20
>> +/* wait for all the CPUs to hit real mode but timeout if they don't =
come in */
>> +static void crash_kexec_wait_realmode(int cpu)
>> +{
>> + unsigned int msecs;
>> + int i;
>> +
>> + msecs =3D 10000;
>> + for (i=3D0; i < NR_CPUS && msecs > 0; i++) {
>> + if (i =3D=3D cpu)
>> + continue;
>> +
>> + while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
>> + barrier();
>> + if (!cpu_possible(i)) {
>> + break;
>> + }
>> + if (!cpu_online(i)) {
>> + break;
>> + }
>> + msecs--;
>> + mdelay(1);
>> + }
>> + }
>> + mb();
>> +}
>> +
>> /*
>> * This function will be called by secondary cpus or by kexec cpu
>> * if soft-reset is activated to stop some CPUs.
>> @@ -412,6 +438,7 @@ void default_machine_crash_shutdown(stru
>> crash_kexec_prepare_cpus(crashing_cpu);
>> cpu_set(crashing_cpu, cpus_in_crash);
>> crash_kexec_stop_spus();
>=20
> should this be
>=20
> #ifdef CONFIG_PPC_STD_MMU
>=20
>> + crash_kexec_wait_realmode(crashing_cpu);
>=20
> #endif
I'm going to make it CONFIG_PPC_STD_MMU_64 as part of a Kexec book-e =
patch
- k=
^ permalink raw reply
* Re: [PATCH 2/2] powerpc, kdump: Fix race in kdump shutdown
From: Michael Neuling @ 2010-05-24 23:53 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, kexec, jlarrew, Anton Blanchard
In-Reply-To: <04AC722A-97CD-4451-B6AB-F4AC37EFAB1D@kernel.crashing.org>
In message <04AC722A-97CD-4451-B6AB-F4AC37EFAB1D@kernel.crashing.org> you wrote
:
>
> On May 24, 2010, at 2:23 PM, Kumar Gala wrote:
>
> >=20
> > On May 14, 2010, at 12:40 AM, Michael Neuling wrote:
> >=20
> >> When we are crashing, the crashing/primary CPU IPIs the secondaries =
> to
> >> turn off IRQs, go into real mode and wait in kexec_wait. While this
> >> is happening, the primary tears down all the MMU maps. Unfortunately
> >> the primary doesn't check to make sure the secondaries have entered
> >> real mode before doing this.
> >>=20
> >> On PHYP machines, the secondaries can take a long time shutting down
> >> the IRQ controller as RTAS calls are need. These RTAS calls need to
> >> be serialised which resilts in the secondaries contending in
> >> lock_rtas() and hence taking a long time to shut down.
> >>=20
> >> We've hit this on large POWER7 machines, where some secondaries are
> >> still waiting in lock_rtas(), when the primary tears down the HPTEs.
> >>=20
> >> This patch makes sure all secondaries are in real mode before the
> >> primary tears down the MMU. It uses the new kexec_state entry in the
> >> paca. It times out if the secondaries don't reach real mode after
> >> 10sec.
> >>=20
> >> Signed-off-by: Michael Neuling <mikey@neuling.org>
> >> ---
> >>=20
> >> arch/powerpc/kernel/crash.c | 27 +++++++++++++++++++++++++++
> >> 1 file changed, 27 insertions(+)
> >>=20
> >> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> >> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> >> @@ -162,6 +162,32 @@ static void crash_kexec_prepare_cpus(int
> >> /* Leave the IPI callback set */
> >> }
> >>=20
> >> +/* wait for all the CPUs to hit real mode but timeout if they don't =
> come in */
> >> +static void crash_kexec_wait_realmode(int cpu)
> >> +{
> >> + unsigned int msecs;
> >> + int i;
> >> +
> >> + msecs =3D 10000;
> >> + for (i=3D0; i < NR_CPUS && msecs > 0; i++) {
> >> + if (i =3D=3D cpu)
> >> + continue;
> >> +
> >> + while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
> >> + barrier();
> >> + if (!cpu_possible(i)) {
> >> + break;
> >> + }
> >> + if (!cpu_online(i)) {
> >> + break;
> >> + }
> >> + msecs--;
> >> + mdelay(1);
> >> + }
> >> + }
> >> + mb();
> >> +}
> >> +
> >> /*
> >> * This function will be called by secondary cpus or by kexec cpu
> >> * if soft-reset is activated to stop some CPUs.
> >> @@ -412,6 +438,7 @@ void default_machine_crash_shutdown(stru
> >> crash_kexec_prepare_cpus(crashing_cpu);
> >> cpu_set(crashing_cpu, cpus_in_crash);
> >> crash_kexec_stop_spus();
> >=20
> > should this be
> >=20
> > #ifdef CONFIG_PPC_STD_MMU
> >=20
> >> + crash_kexec_wait_realmode(crashing_cpu);
> >=20
> > #endif
>
> I'm going to make it CONFIG_PPC_STD_MMU_64 as part of a Kexec book-e =
> patch
Ok, thanks, I'll leave it up to you then
Mikey
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox