* [Patch 4/6] PPC64-HWBKPT: Modify process/processor code to recognise hardware debug registers
From: K.Prasad @ 2009-09-03 18:40 UTC (permalink / raw)
To: David Gibson, linuxppc-dev
Cc: Michael Neuling, Benjamin Herrenschmidt, paulus, Alan Stern,
K.Prasad, Roland McGrath
In-Reply-To: <20090903183306.875398457@xyz>
Modify process handling code to recognise hardware debug registers during copy
and flush operations. Introduce a new TIF_DEBUG task flag to indicate a
process's use of debug register. Load the debug register values into a
new CPU during initialisation.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/kernel/process.c | 15 +++++++++++++++
arch/powerpc/kernel/smp.c | 2 ++
2 files changed, 17 insertions(+)
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/process.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
@@ -50,6 +50,7 @@
#include <asm/syscalls.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
+#include <asm/hw_breakpoint.h>
#endif
#include <linux/kprobes.h>
#include <linux/kdebug.h>
@@ -254,8 +255,10 @@ void do_dabr(struct pt_regs *regs, unsig
11, SIGSEGV) == NOTIFY_STOP)
return;
+#ifndef CONFIG_PPC64
if (debugger_dabr_match(regs))
return;
+#endif
/* Clear the DAC and struct entries. One shot trigger */
#if defined(CONFIG_BOOKE)
@@ -372,8 +375,13 @@ struct task_struct *__switch_to(struct t
#endif /* CONFIG_SMP */
+#ifdef CONFIG_PPC64
+ if (unlikely(test_tsk_thread_flag(new, TIF_DEBUG)))
+ arch_install_thread_hw_breakpoint(new);
+#else
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr);
+#endif /* CONFIG_PPC64 */
#if defined(CONFIG_BOOKE)
/* If new thread DAC (HW breakpoint) is the same then leave it */
@@ -550,6 +558,10 @@ void show_regs(struct pt_regs * regs)
void exit_thread(void)
{
discard_lazy_cpu_state();
+#ifdef CONFIG_PPC64
+ if (unlikely(test_tsk_thread_flag(current, TIF_DEBUG)))
+ flush_thread_hw_breakpoint(current);
+#endif /* CONFIG_PPC64 */
}
void flush_thread(void)
@@ -672,6 +684,9 @@ int copy_thread(unsigned long clone_flag
* function.
*/
kregs->nip = *((unsigned long *)ret_from_fork);
+
+ if (unlikely(test_tsk_thread_flag(current, TIF_DEBUG)))
+ copy_thread_hw_breakpoint(current, p, clone_flags);
#else
kregs->nip = (unsigned long)ret_from_fork;
#endif
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/smp.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/smp.c
@@ -48,6 +48,7 @@
#include <asm/vdso_datapage.h>
#ifdef CONFIG_PPC64
#include <asm/paca.h>
+#include <asm/hw_breakpoint.h>
#endif
#ifdef DEBUG
@@ -537,6 +538,7 @@ int __devinit start_secondary(void *unus
local_irq_enable();
+ load_debug_registers();
cpu_idle();
return 0;
}
^ permalink raw reply
* [Patch 3/6] PPC64-HWBKPT: Modify ptrace code to use Hardware Breakpoint interfaces
From: K.Prasad @ 2009-09-03 18:40 UTC (permalink / raw)
To: David Gibson, linuxppc-dev
Cc: Michael Neuling, Benjamin Herrenschmidt, paulus, Alan Stern,
K.Prasad, Roland McGrath
In-Reply-To: <20090903183306.875398457@xyz>
Modify the ptrace code to use the hardware breakpoint interfaces for user-space.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/kernel/ptrace.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
@@ -37,6 +37,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
+#include <asm/hw_breakpoint.h>
/*
* does not yet catch signals sent when the child dies.
@@ -757,11 +758,24 @@ void user_disable_single_step(struct tas
void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
{
+ /*
+ * Unregister 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 here
+ */
+ unregister_user_hw_breakpoint(current, bp);
+ kfree(bp);
}
int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
+#ifdef CONFIG_PPC64
+ struct thread_struct *thread = &(task->thread);
+ struct hw_breakpoint *bp;
+ int ret;
+#endif
/* 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.
@@ -791,6 +805,35 @@ int ptrace_set_debugreg(struct task_stru
if (data && !(data & DABR_TRANSLATION))
return -EIO;
+#ifdef CONFIG_PPC64
+ bp = thread->hbp[0];
+ if (data == 0) {
+ if (bp) {
+ unregister_user_hw_breakpoint(task, bp);
+ kfree(bp);
+ }
+ return 0;
+ }
+
+ if (bp) {
+ bp->info.type = data & HW_BREAKPOINT_RW;
+ task->thread.dabr = bp->info.address = data;
+ return modify_user_hw_breakpoint(task, bp);
+ }
+ bp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL);
+ if (!bp)
+ return -ENOMEM;
+
+ /* Store the type of breakpoint */
+ bp->info.type = data & HW_BREAKPOINT_RW;
+ bp->triggered = ptrace_triggered;
+ task->thread.dabr = bp->info.address = data;
+
+ ret = register_user_hw_breakpoint(task, bp);
+ if (ret)
+ return ret;
+#endif /* CONFIG_PPC64 */
+
/* Move contents to the DABR register */
task->thread.dabr = data;
^ permalink raw reply
* [Patch 2/6] PPC64-HWBKPT: Introduce PPC64 specific Hardware Breakpoint interfaces
From: K.Prasad @ 2009-09-03 18:40 UTC (permalink / raw)
To: David Gibson, linuxppc-dev
Cc: Michael Neuling, Benjamin Herrenschmidt, paulus, Alan Stern,
K.Prasad, Roland McGrath
In-Reply-To: <20090903183306.875398457@xyz>
Introduce PPC64 implementation for the generic hardware breakpoint interfaces
defined in kernel/hw_breakpoint.c. Enable the HAVE_HW_BREAKPOINT flag and the
Makefile.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 1
arch/powerpc/kernel/Makefile | 2
arch/powerpc/kernel/hw_breakpoint.c | 342 ++++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/ptrace.c | 4
4 files changed, 348 insertions(+), 1 deletion(-)
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/Kconfig
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/Kconfig
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/Kconfig
@@ -126,6 +126,7 @@ config PPC
select HAVE_SYSCALL_WRAPPERS if PPC64
select GENERIC_ATOMIC64 if PPC32
select HAVE_PERF_COUNTERS
+ select HAVE_HW_BREAKPOINT if PPC64
config EARLY_PRINTK
bool
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/kernel/Makefile
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_p
signal_64.o ptrace32.o \
paca.o cpu_setup_ppc970.o \
cpu_setup_pa6t.o \
- firmware.o nvram_64.o
+ firmware.o nvram_64.o hw_breakpoint.o
obj64-$(CONFIG_RELOCATABLE) += reloc_64.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- /dev/null
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/hw_breakpoint.c
@@ -0,0 +1,342 @@
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ *
+ * 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 2009 IBM Corporation
+ */
+
+#include <linux/notifier.h>
+#include <linux/kallsyms.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>
+
+/* Store the kernel-space breakpoint address value */
+static unsigned long kdabr;
+
+/*
+ * Temporarily stores address for DABR before it is written by the
+ * single-step handler routine
+ */
+static DEFINE_PER_CPU(unsigned long, dabr_data);
+static DEFINE_PER_CPU(struct hw_breakpoint*, last_hit_bp);
+
+/* Disable breakpoints on the physical debug register */
+void arch_disable_hw_breakpoint(void)
+{
+ set_dabr(0);
+}
+
+void arch_update_kernel_hw_breakpoint(void *unused)
+{
+ struct hw_breakpoint *bp;
+
+ /* Check if there is nothing to update */
+ if (hbp_kernel_pos == HBP_NUM)
+ return;
+
+ bp = per_cpu(this_hbp_kernel[hbp_kernel_pos], get_cpu());
+ if (bp == NULL)
+ kdabr = 0;
+ else
+ kdabr = (bp->info.address & ~HW_BREAKPOINT_ALIGN) |
+ bp->info.type | DABR_TRANSLATION;
+ set_dabr(kdabr);
+ put_cpu();
+}
+
+/*
+ * Install the thread breakpoints in their debug registers.
+ */
+void arch_install_thread_hw_breakpoint(struct task_struct *tsk)
+{
+ set_dabr(tsk->thread.dabr);
+}
+
+/*
+ * Clear the DABR which contains the thread-specific breakpoint address
+ */
+void arch_uninstall_thread_hw_breakpoint()
+{
+ set_dabr(0);
+}
+
+/*
+ * Store a breakpoint's encoded address, length, and type.
+ */
+int arch_store_info(struct hw_breakpoint *bp, struct task_struct *tsk)
+{
+ unsigned long sym_addr;
+
+ /* Symbol names from user-space are rejected */
+ if (tsk) {
+ if (bp->info.name)
+ return -EINVAL;
+ return 0;
+ }
+ /*
+ * User-space requests will always have the address field populated
+ * For kernel-addresses, either the address or symbol name can be
+ * specified.
+ */
+ if (bp->info.name) {
+ sym_addr = (unsigned long)kallsyms_lookup_name(bp->info.name);
+ if (bp->info.address) {
+ if (bp->info.address != sym_addr)
+ return -EINVAL;
+ } else
+ bp->info.address = sym_addr;
+ }
+ if (!bp->info.address)
+ return -EINVAL;
+ /*
+ * Determine the symbolsize if not already specified.
+ * Reject the breakpoint request if symbolsize is found
+ * to be greater than HW_BREAKPOINT_LEN
+ */
+ if (!bp->info.symbolsize) {
+ if(!kallsyms_lookup_size_offset(bp->info.address,
+ &(bp->info.symbolsize), NULL))
+ return -EINVAL;
+ }
+ if (bp->info.symbolsize <= HW_BREAKPOINT_LEN)
+ return 0;
+ return -EINVAL;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
+ struct task_struct *tsk)
+{
+ int is_kernel, ret = -EINVAL;
+
+ /* User-space breakpoints cannot be restricted to a subset of CPUs */
+ if (tsk && bp->cpumask)
+ return ret;
+
+ if (!bp)
+ return ret;
+
+ switch (bp->info.type) {
+ case HW_BREAKPOINT_READ:
+ case HW_BREAKPOINT_WRITE:
+ case HW_BREAKPOINT_RW:
+ break;
+ default:
+ return ret;
+ }
+
+ if (!bp->triggered)
+ return -EINVAL;
+
+ ret = arch_store_info(bp, tsk);
+ is_kernel = is_kernel_addr(bp->info.address);
+ if ((tsk && is_kernel) || (!tsk && !is_kernel))
+ return -EINVAL;
+
+ /*
+ * 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 (bp->info.symbolsize >
+ (HW_BREAKPOINT_LEN - (bp->info.address & HW_BREAKPOINT_ALIGN)))
+ return -EINVAL;
+
+ return ret;
+}
+
+void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk)
+{
+ struct thread_struct *thread = &(tsk->thread);
+ struct hw_breakpoint *bp = thread->hbp[0];
+
+ if (bp)
+ thread->dabr = (bp->info.address & ~HW_BREAKPOINT_ALIGN) |
+ bp->info.type | DABR_TRANSLATION;
+ else
+ thread->dabr = 0;
+}
+
+void arch_flush_thread_hw_breakpoint(struct task_struct *tsk)
+{
+ struct thread_struct *thread = &(tsk->thread);
+
+ thread->dabr = 0;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+ int rc = NOTIFY_STOP;
+ struct hw_breakpoint *bp;
+ struct pt_regs *regs = args->regs;
+ unsigned long dar = regs->dar;
+ int cpu, is_kernel, stepped = 1;
+
+ is_kernel = (hbp_kernel_pos == HBP_NUM) ? 0 : 1;
+
+ /* Disable breakpoints during exception handling */
+ set_dabr(0);
+
+ cpu = get_cpu();
+ /* Determine whether kernel- or user-space address is the trigger */
+ bp = is_kernel ?
+ per_cpu(this_hbp_kernel[0], cpu) : current->thread.hbp[0];
+ /*
+ * bp can be NULL due to lazy debug register switching
+ * or due to the delay between updates of hbp_kernel_pos
+ * and this_hbp_kernel.
+ */
+ if (!bp)
+ goto out;
+
+ per_cpu(dabr_data, cpu) = is_kernel ? kdabr : current->thread.dabr;
+
+ /* Verify if dar lies within the address range occupied by the symbol
+ * being watched. Since we cannot get the symbol size for
+ * user-space requests we skip this check in that case
+ */
+ if (is_kernel &&
+ !((bp->info.address <= dar) &&
+ (dar <= (bp->info.address + bp->info.symbolsize))))
+ /*
+ * 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 out;
+
+ /*
+ * Return early after invoking user-callback function without restoring
+ * DABR if the breakpoint is from ptrace which always operates in
+ * one-shot mode
+ */
+ if (bp->triggered == ptrace_triggered) {
+ (bp->triggered)(bp, regs);
+ rc = NOTIFY_DONE;
+ goto out;
+ }
+
+ stepped = emulate_step(regs, regs->nip);
+ /*
+ * Single-step the causative instruction manually if
+ * emulate_step() could not execute it
+ */
+ if (stepped == 0) {
+ regs->msr |= MSR_SE;
+ per_cpu(last_hit_bp, cpu) = bp;
+ goto out;
+ }
+ (bp->triggered)(bp, regs);
+ set_dabr(per_cpu(dabr_data, cpu));
+
+out:
+ /* Enable pre-emption only if single-stepping is finished */
+ if (stepped) {
+ per_cpu(dabr_data, cpu) = 0;
+ put_cpu();
+ }
+ 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;
+ int cpu = get_cpu();
+ int ret = NOTIFY_DONE;
+ siginfo_t info;
+ unsigned long this_dabr_data = per_cpu(dabr_data, cpu);
+ struct hw_breakpoint *bp = per_cpu(last_hit_bp, cpu);
+
+ /*
+ * Check if we are single-stepping as a result of a
+ * previous HW Breakpoint exception
+ */
+ if (this_dabr_data == 0)
+ goto out;
+
+ regs->msr &= ~MSR_SE;
+ /*
+ * We shall invoke the user-defined callback function in the single
+ * stepping handler to confirm to 'trigger-after-execute' semantics
+ */
+ (bp->triggered)(bp, regs);
+
+ /* Deliver signal to user-space */
+ if (this_dabr_data < TASK_SIZE) {
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void __user *)(per_cpu(dabr_data, cpu));
+ force_sig_info(SIGTRAP, &info, current);
+ }
+
+ set_dabr(this_dabr_data);
+ per_cpu(dabr_data, cpu) = 0;
+ ret = NOTIFY_STOP;
+ /*
+ * If single-stepped after hw_breakpoint_handler(), pre-emption is
+ * already disabled.
+ */
+ put_cpu();
+
+out:
+ /*
+ * A put_cpu() call is required to complement the get_cpu()
+ * call used initially
+ */
+ put_cpu();
+ return ret;
+}
+
+/*
+ * 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;
+}
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/kernel/ptrace.c
@@ -755,6 +755,10 @@ void user_disable_single_step(struct tas
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
+void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
+{
+}
+
int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
^ permalink raw reply
* [Patch 1/6] PPC64-HWBKPT: Prepare the PowerPC platform for HW Breakpoint infrastructure
From: K.Prasad @ 2009-09-03 18:40 UTC (permalink / raw)
To: David Gibson, linuxppc-dev
Cc: Michael Neuling, Benjamin Herrenschmidt, paulus, Alan Stern,
K.Prasad, Roland McGrath
In-Reply-To: <20090903183306.875398457@xyz>
Prepare the PowerPC code for HW Breakpoint infrastructure patches by including
relevant constant definitions and function declarations.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hw_breakpoint.h | 61 +++++++++++++++++++++++++++++++
arch/powerpc/include/asm/processor.h | 1
arch/powerpc/include/asm/reg.h | 3 +
arch/powerpc/include/asm/thread_info.h | 2 +
4 files changed, 67 insertions(+)
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
===================================================================
--- /dev/null
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
@@ -0,0 +1,61 @@
+#ifndef _PPC64_HW_BREAKPOINT_H
+#define _PPC64_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+#define __ARCH_HW_BREAKPOINT_H
+#ifdef CONFIG_PPC64
+
+struct arch_hw_breakpoint {
+ int type;
+ char *name; /* Contains name of the symbol to set bkpt */
+ unsigned long address;
+ unsigned long symbolsize;
+};
+
+#include <linux/kdebug.h>
+#include <asm/reg.h>
+#include <asm-generic/hw_breakpoint.h>
+
+#define HW_BREAKPOINT_READ DABR_DATA_READ
+#define HW_BREAKPOINT_WRITE DABR_DATA_WRITE
+#define HW_BREAKPOINT_RW (DABR_DATA_READ | DABR_DATA_WRITE)
+
+#define HW_BREAKPOINT_ALIGN 0x7
+/* Maximum permissible length of any HW Breakpoint */
+#define HW_BREAKPOINT_LEN 0x8
+
+extern struct hw_breakpoint *hbp_kernel[HBP_NUM];
+DECLARE_PER_CPU(struct hw_breakpoint*, this_hbp_kernel[HBP_NUM]);
+extern unsigned int hbp_user_refcount[HBP_NUM];
+
+extern void arch_install_thread_hw_breakpoint(struct task_struct *tsk);
+extern void arch_uninstall_thread_hw_breakpoint(void);
+extern int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
+ struct task_struct *tsk);
+extern void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk);
+extern void arch_flush_thread_hw_breakpoint(struct task_struct *tsk);
+extern void arch_update_kernel_hw_breakpoint(void *);
+extern void arch_disable_hw_breakpoint(void);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+ unsigned long val, void *data);
+
+extern void flush_thread_hw_breakpoint(struct task_struct *tsk);
+extern int copy_thread_hw_breakpoint(struct task_struct *tsk,
+ struct task_struct *child, unsigned long clone_flags);
+extern void load_debug_registers(void);
+extern void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs);
+
+static inline void hw_breakpoint_disable(void)
+{
+ set_dabr(0);
+}
+
+#else
+static inline void hw_breakpoint_disable(void)
+{
+ /* Function is defined only on PPC64 for now */
+}
+#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
+#endif /* _PPC64_HW_BREAKPOINT_H */
+
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/processor.h
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/include/asm/processor.h
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/processor.h
@@ -177,6 +177,7 @@ 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 */
+ struct hw_breakpoint *hbp[HBP_NUM];
#endif
unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/reg.h
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/include/asm/reg.h
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/reg.h
@@ -26,6 +26,8 @@
#include <asm/reg_8xx.h>
#endif /* CONFIG_8xx */
+#define INSTRUCTION_LEN 4 /* Length of any instruction */
+
#define MSR_SF_LG 63 /* Enable 64 bit mode */
#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */
#define MSR_HV_LG 60 /* Hypervisor state */
@@ -184,6 +186,7 @@
#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#define HBP_NUM 1 /* Number of physical HW breakpoint registers */
#define DABR_TRANSLATION (1UL << 2)
#define DABR_DATA_WRITE (1UL << 1)
#define DABR_DATA_READ (1UL << 0)
Index: linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/thread_info.h
===================================================================
--- linux-2.6-tip.ppc64_hbkpt.orig/arch/powerpc/include/asm/thread_info.h
+++ linux-2.6-tip.ppc64_hbkpt/arch/powerpc/include/asm/thread_info.h
@@ -112,6 +112,7 @@ static inline struct thread_info *curren
#define TIF_FREEZE 14 /* Freezing for suspend */
#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */
#define TIF_ABI_PENDING 16 /* 32/64 bit switch needed */
+#define TIF_DEBUG 17 /* uses debug registers */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -130,6 +131,7 @@ static inline struct thread_info *curren
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
+#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
^ permalink raw reply
* [Patch 0/6] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver IX
From: K.Prasad @ 2009-09-03 18:39 UTC (permalink / raw)
To: David Gibson, linuxppc-dev
Cc: paulus, Michael Neuling, Benjamin Herrenschmidt, Alan Stern,
Roland McGrath
Hi All,
Please find a new set of patches with the changes as listed below.
These patches have to be applied over the set of patches sent to LKML here:
http://lkml.org/lkml/2009/8/28/272 that enable per-cpu breakpoint support and
a few new APIs.
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.
- 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.
Kindly let me know your comments on the same.
Thanks,
K.Prasad
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
* Re: [RFC] net/fs_enet: send a reset request to the PHY on init
From: Grant Likely @ 2009-09-03 16:48 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev, netdev, Vitaly Bordug
In-Reply-To: <20090902110410.GC15401@www.tglx.de>
On Wed, Sep 2, 2009 at 5:04 AM, Sebastian Andrzej
Siewior<bigeasy@linutronix.de> wrote:
> Usually u-boot sends a phy request in its network init routine. An uboot
> without network support doesn't do it and I endup without working
> network. I still can switch between 10/100Mbit (according to the LED on
> the hub and phy registers) but I can't send or receive any data.
>
> At this point I'm not sure if the PowerON Reset takes the PHY a few
> nsecs too early out of reset or if this reset is required and everyone
> relies on U-boot performing this reset.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> This is done on a custom mpc512x board. Unfortunately I don't have other
> boards to check. The PHY is a AMD Am79C874, phylib uses the generic one.
>
> =A0drivers/net/fs_enet/fs_enet-main.c | =A0 =A03 ++-
> =A01 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_=
enet-main.c
> index ee15402..a3c962b 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -823,7 +823,8 @@ static int fs_init_phy(struct net_device *dev)
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0fep->phydev =3D phydev;
> -
> + =A0 =A0 =A0 phy_write(phydev, MII_BMCR, BMCR_RESET);
> + =A0 =A0 =A0 udelay(1);
What version of the kernel are you using? The line numbers don't
match up with kernel mainline, so I wonder if this is before or after
the OF MDIO rework changes.
Regardless, this doesn't look right. It certainly isn't right for the
driver to do an unconditional PHY reset when it doesn't actually know
what phy is attached. For most boards I'm sure this is not desirable
because it will cause a delay while the PHY auto negotiates.
Depending on when the first network traffic begins, can cause several
seconds of boot delay.
Best would be to do this in U-Boot. Otherwise, I think I would rather
see it at phy_device probe time. At least then it would be on a
per-phy basis, or could be controlled by a property in the device tree
so that all boards don't get the same impact.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Josh Boyer @ 2009-09-03 16:21 UTC (permalink / raw)
To: Adam Zilkie; +Cc: Chris Pringle, Andrea Zypchen, linuxppc-dev, Tom Burns
In-Reply-To: <1251993890.2548.14.camel@Adam>
On Thu, Sep 03, 2009 at 12:04:50PM -0400, Adam Zilkie wrote:
>Ben,
>
>Thanks for your info.
>
>Are you sure there is L2 cache on the 440?
It depends on which 440 SoC you have. It also depends on that being
configured in the kernel even if it does exist.
>I am seeing this problem with our custom IDE driver which is based on
>pretty old code. Our driver uses pci_alloc_consistent() to allocate the
>physical DMA memory and alloc_pages() to allocate a virtual page. It
>then uses pci_map_sg() to map to a scatter/gather buffer. Perhaps I
>should convert these to the DMA API calls as you suggest.
I would suggest updating the code. I have no idea if that is the problem,
but it should probably be done anyway.
josh
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Adam Zilkie @ 2009-09-03 16:04 UTC (permalink / raw)
To: benh; +Cc: Tom Burns, Chris Pringle, Andrea Zypchen, linuxppc-dev
In-Reply-To: <1251971849.15089.28.camel@pasglop>
Ben,
Thanks for your info.
Are you sure there is L2 cache on the 440?
I am seeing this problem with our custom IDE driver which is based on
pretty old code. Our driver uses pci_alloc_consistent() to allocate the
physical DMA memory and alloc_pages() to allocate a virtual page. It
then uses pci_map_sg() to map to a scatter/gather buffer. Perhaps I
should convert these to the DMA API calls as you suggest.
Regards,
Adam
On Thu, 2009-09-03 at 19:57 +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2009-09-03 at 09:05 +0100, Chris Pringle wrote:
> > Hi Adam,
> >
> > If you have a look in include/asm-ppc/pgtable.h for the following section:
> > #ifdef CONFIG_44x
> > #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
> > #else
> > #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
> > #endif
> >
> > Try adding _PAGE_COHERENT to the appropriate line above and see if that
> > fixes your issue - this causes the 'M' bit to be set on the page which
> > sure enforce cache coherency. If it doesn't, you'll need to check the
> > 'M' bit isn't being masked out in head_44x.S (it was originally masked
> > out on arch/powerpc, but was fixed in later kernels when the cache
> > coherency issues with non-SMP systems were resolved).
>
> I have some doubts about the usefulness of doing that for 4xx. AFAIK,
> the 440 core just ignores M.
>
> The problem lies probably elsewhere. Maybe the L2 cache coherency isn't
> enabled or not working ?
>
> The L1 cache on 440 is simply not coherent, so drivers have to make sure
> they use the appropriate DMA APIs which will do cache flushing when
> needed.
>
> Adam, what driver is causing you that sort of problems ?
>
> Cheers,
> Ben.
>
>
--
Adam Zilkie
Software Designer,
International Datacasting Corp.
This message and the documents attached hereto are intended only for the addressee and may contain privileged or confidential information. Any unauthorized disclosure is strictly prohibited. If you have received this message in error, please notify us immediately so that we may correct our internal records. Please then delete the original message. Thank you.
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Adam Zilkie @ 2009-09-03 15:54 UTC (permalink / raw)
To: chris.pringle; +Cc: Tom Burns, Andrea Zypchen, linuxppc-dev
In-Reply-To: <4A9F78AF.4010206@oxtel.com>
Chris,
I noticed the following comment in pgtable.h:
* - CACHE COHERENT bit (M) has no effect on PPC440 core, because it
* doesn't support SMP. So we can use this as software bit, like
* DIRTY.
And _PAGE_COHERENT is not defined for the 44x (giving a compile error
when I add it the _PAGE_BASE line as you suggested). This would confirm
that the M bit is meaningless for the PPC440
Regards,
Adam
On Thu, 2009-09-03 at 09:05 +0100, Chris Pringle wrote:
> Hi Adam,
>
> If you have a look in include/asm-ppc/pgtable.h for the following section:
> #ifdef CONFIG_44x
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
> #else
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
> #endif
>
> Try adding _PAGE_COHERENT to the appropriate line above and see if that
> fixes your issue - this causes the 'M' bit to be set on the page which
> sure enforce cache coherency. If it doesn't, you'll need to check the
> 'M' bit isn't being masked out in head_44x.S (it was originally masked
> out on arch/powerpc, but was fixed in later kernels when the cache
> coherency issues with non-SMP systems were resolved).
>
> The patch I had fixed two problems on 2.6.26 for 'powerpc':
> 1) It stopped the 'M' bit being masked out (head_32.S)
> 2) It set the cache coherency ('M' bit) flag on each page table entry
> (pgtable-ppc32.h)
>
> Hope this helps!
>
> Cheers,
> Chris
>
> Adam Zilkie wrote:
> > Hi Chris,
> >
> > I am having a problem similar to what you described in this discussion.
> > We are using the ppc arch with 2.6.24 with CONFIG_SEQUOIA with compiles
> > arch/ppc/kernel/head_44x.c (quite different
> > from /arch/powerpc/kernel/head_32.S). I would like to apply your
> > backporting patch to this architecture. Any help would be appreciated.
> >
> > Regards,
> > Adam
> >
> >
>
>
--
Adam Zilkie
Software Designer,
International Datacasting Corp.
This message and the documents attached hereto are intended only for the addressee and may contain privileged or confidential information. Any unauthorized disclosure is strictly prohibited. If you have received this message in error, please notify us immediately so that we may correct our internal records. Please then delete the original message. Thank you.
^ permalink raw reply
* [PATCH] powerpc: Fix i8259 interrupt driver kernel crash on ML510
From: Grant Likely @ 2009-09-03 15:57 UTC (permalink / raw)
To: linuxppc-dev, benh, linux-kernel, torvalds; +Cc: Roderick Colenbrander
From: Roderick Colenbrander <thunderbird2k@gmail.com>
This patch fixes a null pointer exception caused by removal of
'ack()' for level interrupts in the Xilinx interrupt driver. A recent
change to the xilinx interrupt controller removed the ack hook for
level irqs.
Signed-off-by: Roderick Colenbrander <thunderbird2k@gmail.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
Hi Ben & Linus,
This is a last minute bug fix must go into 2.6.31. This patch
is needed to prevent a kernel panic on Xilinx ml510 boards.
I've also pushed the patch out to my git tree if you'd prefer to pull:
The following changes since commit 326ba5010a5429a5a528b268b36a5900d4ab0eba:
Linus Torvalds (1):
Linux 2.6.31-rc8
are available in the git repository at:
git://git.secretlab.ca/git/linux-2.6 merge
Roderick Colenbrander (1):
powerpc: Fix i8259 interrupt driver kernel crash on ML510
arch/powerpc/sysdev/xilinx_intc.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 3ee1fd3..40edad5 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -234,7 +234,6 @@ static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
generic_handle_irq(cascade_irq);
/* Let xilinx_intc end the interrupt */
- desc->chip->ack(irq);
desc->chip->unmask(irq);
}
^ permalink raw reply related
* Fix i8259 kernel crash on ML510
From: Roderick Colenbrander @ 2009-09-03 13:14 UTC (permalink / raw)
To: grant.likely, linuxppc-dev
>From 11a2072b285c2eb0f19980ad729229d4ebf22291 Mon Sep 17 00:00:00 2001
From: Roderick Colenbrander <colenbrander@CE202.(none)>
Date: Thu, 3 Sep 2009 15:11:08 +0200
Subject: [PATCH] This patch fixes a null pointer exception caused by
removal of 'ack()' for level interrupts in the Xilinx interrupt driver.
---
arch/powerpc/sysdev/xilinx_intc.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/xilinx_intc.c
b/arch/powerpc/sysdev/xilinx_intc.c
index 3ee1fd3..40edad5 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -234,7 +234,6 @@ static void xilinx_i8259_cascade(unsigned int irq,
struct irq_desc *desc)
generic_handle_irq(cascade_irq);
/* Let xilinx_intc end the interrupt */
- desc->chip->ack(irq);
desc->chip->unmask(irq);
}
--
1.6.0.4
^ permalink raw reply related
* Fix i8259 kernel crash on ML510 [with signed-off]
From: Roderick Colenbrander @ 2009-09-03 13:18 UTC (permalink / raw)
To: grant.likely, linuxppc-dev
Hi,
This is the same patch but with a signed-off message which I forgot.
Regards,
Roderick Colenbrander
Signed-off-by: Roderick Colenbrander <thunderbird2k@gmail.com>
>From 11a2072b285c2eb0f19980ad729229d4ebf22291 Mon Sep 17 00:00:00 2001
From: Roderick Colenbrander <colenbrander@CE202.(none)>
Date: Thu, 3 Sep 2009 15:11:08 +0200
Subject: [PATCH] This patch fixes a null pointer exception caused by
removal of 'ack()' for level interrupts in the Xilinx interrupt driver.
---
arch/powerpc/sysdev/xilinx_intc.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/xilinx_intc.c
b/arch/powerpc/sysdev/xilinx_intc.c
index 3ee1fd3..40edad5 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -234,7 +234,6 @@ static void xilinx_i8259_cascade(unsigned int irq,
struct irq_desc *desc)
generic_handle_irq(cascade_irq);
/* Let xilinx_intc end the interrupt */
- desc->chip->ack(irq);
desc->chip->unmask(irq);
}
--
1.6.0.4
^ permalink raw reply related
* Re: time jumps forward/backwards
From: Ben Gamsa @ 2009-09-03 12:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras, Sean MacLennan
In-Reply-To: <4A9D038F.90605@somanetworks.com>
Benjamin Gamsa wrote:
> Benjamin Herrenschmidt wrote:
>> On Mon, 2009-08-31 at 23:57 -0400, Benjamin Gamsa wrote:
>>> Sean MacLennan wrote:
>>>> On Mon, 31 Aug 2009 22:20:00 -0400
>>>> Benjamin Gamsa <ben@somanetworks.com> wrote:
>>>>
>>>>> For what it's worth, the problem occurs even when ntp is not even
>>>>> started.
>>>> This is grasping, but could it have anything to do with the jiffies
>>>> wrapping near startup?
>>>>
>>> I don't know how to test it, but I don't think so, since there are
>>> multiple of these glitches over an extended period of time.
>>
>> I'm not familiar with all the FSL processor variants, but is this
>> an UP or an SMP platform ? In the later case, are all the core timebases
>> properly synchronized ?
>>
>
> This a UP with a single e500 core.
>
I take it from the lack of follow-ups that no one has any good ideas as
to what might be going wrong?
Since the problem seems to be confined to situations where the date is
around the epoch, I guess I'll just work-around the problem by setting
the date to a more recent date on startup.
--
Ben Gamsa ben@somanetworks.com
SOMA Networks 312 Adelaide St. W. Suite 600 Toronto, Ontario, M5V1R2
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Chris Pringle @ 2009-09-03 12:43 UTC (permalink / raw)
To: Wrobel Heinz-R39252; +Cc: Tom Burns, Andrea Zypchen, linuxppc-dev, azilkie
In-Reply-To: <AAE514D00E55E6438B7F5186462A545202750F9B@zuk35exm20.fsl.freescale.net>
In our case, we were suffering coherency issues on an 8260 when using
DMA with PCI. Setting the 'M' bit cured all of our DMA coherency issues.
There is a comment in "pgtable-ppc32.h" on 2.6.29.6 that says:
"We always set _PAGE_COHERENT when SMP is enabled *or* the processor
might need it for DMA coherency". Freescale had also suggested setting
the 'M' bit when we submitted a support request.
I've no idea how this bit affects other PowerPC chips. Looking briefly
through some of the header files, it looks as if the 'M' bit should not
be set for 44x, so the issue is probably not the same as the one I had.
Cheers,
Chris
Wrobel Heinz-R39252 wrote:
> Hi,
>
> This doesn't seem right. If we are talking about a single CPU core chip,
> i.e., just one data cache, then setting M is typically a) useless and
> could even b) cause a performance penalty depending on a chip's
> implementation.
> The M bit is required if *other* cores with caches need to see changes
> for coherency of their caches. You wouldn't set it for one core only
> because your own core knows about its own cache.
> The possible performance penalty could happen because you need some way
> to tell the others that they better intercept a transaction. And that
> could, depending on the chip, by a clock extra or so per transaction.
> Now, in theory, a DMA engine could have caches, read from cache content
> first, and could snoop the bus on global transactions like another core,
> but I have never heard of such a beast.
>
> Hope this helps,
>
> Heinz
>
> -----Original Message-----
> From: linuxppc-dev-bounces+heinz.wrobel=freescale.com@lists.ozlabs.org
> [mailto:linuxppc-dev-bounces+heinz.wrobel=freescale.com@lists.ozlabs.org
> ] On Behalf Of Chris Pringle
> Sent: Donnerstag, 3. September 2009 10:05
> To: azilkie@datacast.com
> Cc: Tom Burns; Andrea Zypchen; linuxppc-dev@lists.ozlabs.org
> Subject: Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
>
> Hi Adam,
>
> If you have a look in include/asm-ppc/pgtable.h for the following
> section:
> #ifdef CONFIG_44x
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
> #else
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
> #endif
>
> Try adding _PAGE_COHERENT to the appropriate line above and see if that
> fixes your issue - this causes the 'M' bit to be set on the page which
> sure enforce cache coherency. If it doesn't, you'll need to check the
> 'M' bit isn't being masked out in head_44x.S (it was originally masked
> out on arch/powerpc, but was fixed in later kernels when the cache
> coherency issues with non-SMP systems were resolved).
>
> The patch I had fixed two problems on 2.6.26 for 'powerpc':
> 1) It stopped the 'M' bit being masked out (head_32.S)
> 2) It set the cache coherency ('M' bit) flag on each page table entry
> (pgtable-ppc32.h)
>
> Hope this helps!
>
> Cheers,
> Chris
>
> Adam Zilkie wrote:
>
>> Hi Chris,
>>
>> I am having a problem similar to what you described in this
>>
> discussion.
>
>> We are using the ppc arch with 2.6.24 with CONFIG_SEQUOIA with
>> compiles arch/ppc/kernel/head_44x.c (quite different from
>> /arch/powerpc/kernel/head_32.S). I would like to apply your
>> backporting patch to this architecture. Any help would be appreciated.
>>
>> Regards,
>> Adam
>>
>>
>>
>
>
>
____________________________
Miranda Technologies Limited
Registered in England and Wales CN 02017053
Registered Office: James House, Mere Park, Dedmere Road, Marlow, Bucks, SL7 1FJ
^ permalink raw reply
* RE: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Wrobel Heinz-R39252 @ 2009-09-03 12:20 UTC (permalink / raw)
To: Chris Pringle, linuxppc-dev; +Cc: Tom Burns, Andrea Zypchen, azilkie
In-Reply-To: <4A9F78AF.4010206@oxtel.com>
Hi,
This doesn't seem right. If we are talking about a single CPU core chip,
i.e., just one data cache, then setting M is typically a) useless and
could even b) cause a performance penalty depending on a chip's
implementation.
The M bit is required if *other* cores with caches need to see changes
for coherency of their caches. You wouldn't set it for one core only
because your own core knows about its own cache.
The possible performance penalty could happen because you need some way
to tell the others that they better intercept a transaction. And that
could, depending on the chip, by a clock extra or so per transaction.
Now, in theory, a DMA engine could have caches, read from cache content
first, and could snoop the bus on global transactions like another core,
but I have never heard of such a beast.=20
Hope this helps,
Heinz
-----Original Message-----
From: linuxppc-dev-bounces+heinz.wrobel=3Dfreescale.com@lists.ozlabs.org
[mailto:linuxppc-dev-bounces+heinz.wrobel=3Dfreescale.com@lists.ozlabs.or=
g
] On Behalf Of Chris Pringle
Sent: Donnerstag, 3. September 2009 10:05
To: azilkie@datacast.com
Cc: Tom Burns; Andrea Zypchen; linuxppc-dev@lists.ozlabs.org
Subject: Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
Hi Adam,
If you have a look in include/asm-ppc/pgtable.h for the following
section:
#ifdef CONFIG_44x
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
#else
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
#endif
Try adding _PAGE_COHERENT to the appropriate line above and see if that
fixes your issue - this causes the 'M' bit to be set on the page which
sure enforce cache coherency. If it doesn't, you'll need to check the
'M' bit isn't being masked out in head_44x.S (it was originally masked
out on arch/powerpc, but was fixed in later kernels when the cache
coherency issues with non-SMP systems were resolved).
The patch I had fixed two problems on 2.6.26 for 'powerpc':
1) It stopped the 'M' bit being masked out (head_32.S)
2) It set the cache coherency ('M' bit) flag on each page table entry
(pgtable-ppc32.h)
Hope this helps!
Cheers,
Chris
Adam Zilkie wrote:
> Hi Chris,
>
> I am having a problem similar to what you described in this
discussion.
> We are using the ppc arch with 2.6.24 with CONFIG_SEQUOIA with=20
> compiles arch/ppc/kernel/head_44x.c (quite different from=20
> /arch/powerpc/kernel/head_32.S). I would like to apply your=20
> backporting patch to this architecture. Any help would be appreciated.
>
> Regards,
> Adam
>
> =20
--=20
______________________________
Chris Pringle
Software Design Engineer
Miranda Technologies Ltd.
Hithercroft Road
Wallingford
Oxfordshire OX10 9DG
UK
Tel. +44 1491 820206
Fax. +44 1491 820001
www.miranda.com
____________________________
Miranda Technologies Limited
Registered in England and Wales CN 02017053 Registered Office: James
House, Mere Park, Dedmere Road, Marlow, Bucks, SL7 1FJ
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* powerpc test branch build failure with 6xx defconfig + PERF_CTRS
From: Michael Ellerman @ 2009-09-03 12:10 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev list
[-- Attachment #1: Type: text/plain, Size: 295 bytes --]
With benh's test branch, I'm seeing this trying to build a 6xx defconfig
with CONFIG_PPC_PERF_CTRS=y:
arch/powerpc/kernel/perf_counter.c: In function 'power_check_constraints':
arch/powerpc/kernel/perf_counter.c:352: error: the frame size of 1152 bytes is larger than 1024 bytes
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: PPC PCI bus registers
From: Benjamin Herrenschmidt @ 2009-09-03 10:00 UTC (permalink / raw)
To: Eddie Dawydiuk; +Cc: linuxppc-dev
In-Reply-To: <4A9F0377.1070606@embeddedarm.com>
On Wed, 2009-09-02 at 16:44 -0700, Eddie Dawydiuk wrote:
> Hello,
>
> I have a question regarding reading PCI bus registers from a user space
> application running on a PPC SBC. Seeing as though the PCI bus is little endian
> and PPC is big endian is it typical that one must perform a byte swap on all 16
> and 32 bit register reads?
>
> I've found this is true on a custom board I am working on(with an FPGA connected
> via the PCI bus) and as a result I've added a byte swap command in busybox to
> accommodate this feature...
Note that powerpc has efficient load/store reverse instructions that
perform the byteswap for you. We use them for IOs in the kernel for
example.
Also, if you're going to access a PCI device directly, beware of other
issues such as ordering. PPC is an out of order architecture, you need
to ensure you add the appropriate memory barriers if you want to ensure
you accesses are done in the order you write them in your program.
For "standard" stuff that doesn't involve DMA or locks, an eieio after
both MMIO loads and stores should do the trick.
If you need to order vs. DMA and/or locks, you may want to look at what
the kernel does in io.h
Cheers,
Ben.
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Benjamin Herrenschmidt @ 2009-09-03 9:57 UTC (permalink / raw)
To: Chris Pringle; +Cc: Tom Burns, Andrea Zypchen, linuxppc-dev, azilkie
In-Reply-To: <4A9F78AF.4010206@oxtel.com>
On Thu, 2009-09-03 at 09:05 +0100, Chris Pringle wrote:
> Hi Adam,
>
> If you have a look in include/asm-ppc/pgtable.h for the following section:
> #ifdef CONFIG_44x
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
> #else
> #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
> #endif
>
> Try adding _PAGE_COHERENT to the appropriate line above and see if that
> fixes your issue - this causes the 'M' bit to be set on the page which
> sure enforce cache coherency. If it doesn't, you'll need to check the
> 'M' bit isn't being masked out in head_44x.S (it was originally masked
> out on arch/powerpc, but was fixed in later kernels when the cache
> coherency issues with non-SMP systems were resolved).
I have some doubts about the usefulness of doing that for 4xx. AFAIK,
the 440 core just ignores M.
The problem lies probably elsewhere. Maybe the L2 cache coherency isn't
enabled or not working ?
The L1 cache on 440 is simply not coherent, so drivers have to make sure
they use the appropriate DMA APIs which will do cache flushing when
needed.
Adam, what driver is causing you that sort of problems ?
Cheers,
Ben.
^ permalink raw reply
* Re: [v4 PATCH 1/5]: cpuidle: Cleanup drivers/cpuidle/cpuidle.c
From: Peter Zijlstra @ 2009-09-03 9:40 UTC (permalink / raw)
To: arun
Cc: Gautham R Shenoy, linux-kernel, Paul Mackerras, Ingo Molnar,
linuxppc-dev
In-Reply-To: <20090903044253.GA31928@linux.vnet.ibm.com>
On Thu, 2009-09-03 at 10:12 +0530, Arun R Bharadwaj wrote:
> > OK, that's a start I guess. Best would be to replace all of pm_idle with
> > cpuidle, which is what should have been done from the very start.
> >
> > If cpuidle cannot fully replace the pm_idle functionality, then it needs
> > to fix that. But having two layers of idle functions is just silly.
> >
> > Looking at patch 2 and 3, you're making the same mistake on power, after
> > those patches there are multiple ways of registering idle functions, one
> > through some native interface and one through cpuidle, this strikes me
> > as undesirable.
> >
> > If cpuidle is a good idle function manager, then it should be good
> > enough to be the sole one, if its not, then why bother with it at all.
> >
>
> Okay, I'm giving this approach a shot now. i.e. trying to make cpuidle
> as _the_ sole idle function manager. This would mean doing away with
> pm_idle and ppc_md.power_save. And, cpuidle_idle_call() which is the
> main idle loop of cpuidle, present in drivers/cpuidle/cpuidle.c will
> have to be called from arch specific code of cpu_idle()
>
> Also this would mean enabling cpuidle for all platforms, even if the
> platform doesn't have multiple idle states. So suppose a platform doesnt
> have multiple states, it wouldn't want the bloated code of cpuidle
> governors, and would want just a simple cpuidle loop.
Do talk to the powerpc maintainers about this. But yes, something like
that should be doable.
AFAICT the whole governor thing is optional and cpuidle provides a
spinning idle loop by default, and platforms can always register a
simple alternative when they set up bits -- the only thing to be careful
about is not creating a chicken-egg problem where the platform setup
runs before cpuidle is able to register a new handler or something.
I'd be delighted to see the end of pm_idle on x86.
^ permalink raw reply
* ucc_geth.c - NETDEV WATCHDOG: eth2 Tx transmit timeout
From: Shailesh Panchal @ 2009-09-03 9:13 UTC (permalink / raw)
To: linuxppc-dev; +Cc: 'Ronak Shah', 'Shailesh Panchal'
Dear All,
Currently we are using the MPC8360E processor, for that we face the problem
with Ethernet port (UCC) port, which one configures as RMII mode. We get the
error like "NETDEV WATCHDOG: eth2 tx transmit timeout", When applied more
load on port. Can u give me any solution for this problem; I will see the
entire patch related it but not found solution of this problem. Any one has
any idea about it how to resolve it.
Wait for Replay
Regards,
Shailesh
^ permalink raw reply
* Re: AW: PowerPC PCI DMA issues (prefetch/coherency?)
From: Chris Pringle @ 2009-09-03 8:05 UTC (permalink / raw)
To: azilkie; +Cc: Tom Burns, Andrea Zypchen, linuxppc-dev
In-Reply-To: <1251926572.10090.17.camel@Adam>
Hi Adam,
If you have a look in include/asm-ppc/pgtable.h for the following section:
#ifdef CONFIG_44x
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_GUARDED)
#else
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
#endif
Try adding _PAGE_COHERENT to the appropriate line above and see if that
fixes your issue - this causes the 'M' bit to be set on the page which
sure enforce cache coherency. If it doesn't, you'll need to check the
'M' bit isn't being masked out in head_44x.S (it was originally masked
out on arch/powerpc, but was fixed in later kernels when the cache
coherency issues with non-SMP systems were resolved).
The patch I had fixed two problems on 2.6.26 for 'powerpc':
1) It stopped the 'M' bit being masked out (head_32.S)
2) It set the cache coherency ('M' bit) flag on each page table entry
(pgtable-ppc32.h)
Hope this helps!
Cheers,
Chris
Adam Zilkie wrote:
> Hi Chris,
>
> I am having a problem similar to what you described in this discussion.
> We are using the ppc arch with 2.6.24 with CONFIG_SEQUOIA with compiles
> arch/ppc/kernel/head_44x.c (quite different
> from /arch/powerpc/kernel/head_32.S). I would like to apply your
> backporting patch to this architecture. Any help would be appreciated.
>
> Regards,
> Adam
>
>
--
______________________________
Chris Pringle
Software Design Engineer
Miranda Technologies Ltd.
Hithercroft Road
Wallingford
Oxfordshire OX10 9DG
UK
Tel. +44 1491 820206
Fax. +44 1491 820001
www.miranda.com
____________________________
Miranda Technologies Limited
Registered in England and Wales CN 02017053
Registered Office: James House, Mere Park, Dedmere Road, Marlow, Bucks, SL7 1FJ
^ permalink raw reply
* Re: MPC866 FEC's Receive processing thru pre allocated buffers
From: Joakim Tjernlund @ 2009-09-03 7:21 UTC (permalink / raw)
To: Ganesh Kumar; +Cc: linuxppc-dev
In-Reply-To: <200909031015.15080.ganeshkumar@signal-networks.com>
Ganesh Kumar <ganeshkumar@signal-networks.com> wrote on 03/09/2009 06:45:14:
>
> Hi Tjernlund,
>
> Thanks a lot for the reply.
>
> I checked in my code regarding to the invalidate/flushing of the
> data cache. In the fec_init its been done by calling the sequence
>
> /* Make it uncached.
> */
> pte = va_to_pte(mem_addr);
> pte_val(*pte) |= _PAGE_NO_CACHE;
> flush_tlb_page(init_mm.mmap, mem_addr);
> So I did the same thing whenever I allocated new skb, but the
> problems still showed up, then I saw one comment in FEC code where
> it says
>
> /* This does 16 byte alignment, exactly what we need.
> * The packet length includes FCS, but we don't want to
> * include that when passing upstream as it messes up
> * bridging applications.
> */
> while receiving the frames, I checked my modified code w.r.t the length,
> since I was not knowing the receive lengthn while allocating for the
> RX ring, I did with a maximum of 2048 bytes length and called the skb_put
> to reserve 2048 bytes for data, calling of the skb_put also updated the
> skb->len field with 2048, this was causing the problem, the bridge module
> was trying to send the frame with 2048 bytes even though the actual length
> was less number of bytes, so even after sending it to the FEC, the frame was
> getting transmitted successfully. So I updated the actual length to the
> skb->len field in the rx ISR, the problem is solved now.
>
> But I'm facing problems during load time in bridge mode
> PC-1 ---->eth0 [Bridge machine] eth1 ----> PC-2
> With the above setup I initiate 1500 pings each of 1400 bytes
> from PC1 to PC2, then the ping sequence starts, but after some time
> say some 25-35(all 1500 instances) sequences all of a sudden no
> ping reply is received for any request.
> At that time if I observe in the Bridge machine cat /proc/interrupts
> the fec interrupts will not get updated there(initially it used to)
> again it resumes after some 45-60 seconds and the sequence repeats.
> Dunno what's happening with in the FEC if configured in bridge mode
> any clue on this, Thanks a lakh in advance.
If I remember correctly, this is what you get when the invalidation
of the skb buffers isn't working properly.
Guessing again, but you seem to split up the page into two buffers of len 2048,
but you flush/invalidate the whole page. That won't work.
You are much better off by just using plain skb allocation and invalidate
the buffer before passing it to the CPM/FEC. Just make sure that the allocated
buffer has a cache aligned length. This is what I did long time ago and it worked
out perfectly.
Jocke
^ permalink raw reply
* Re: [v4 PATCH 1/5]: cpuidle: Cleanup drivers/cpuidle/cpuidle.c
From: Arun R Bharadwaj @ 2009-09-03 4:42 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Gautham R Shenoy, linux-kernel, Paul Mackerras, Arun Bharadwaj,
Ingo Molnar, linuxppc-dev
In-Reply-To: <1251870144.7547.48.camel@twins>
* Peter Zijlstra <a.p.zijlstra@chello.nl> [2009-09-02 07:42:24]:
> On Tue, 2009-09-01 at 17:08 +0530, Arun R Bharadwaj wrote:
> > * Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-09-01 17:07:04]:
> >
> > Cleanup drivers/cpuidle/cpuidle.c
> >
> > Cpuidle maintains a pm_idle_old void pointer because, currently in x86
> > there is no clean way of registering and unregistering a idle function.
>
> Right, and instead of fixing that, they build this cpuidle crap on top,
> instead of replacing the current crap with it.
>
> > So remove pm_idle_old and leave the responsibility of maintaining the
> > list of registered idle loops to the architecture specific code. If the
> > architecture registers cpuidle_idle_call as its idle loop, only then
> > this loop is called.
>
> OK, that's a start I guess. Best would be to replace all of pm_idle with
> cpuidle, which is what should have been done from the very start.
>
> If cpuidle cannot fully replace the pm_idle functionality, then it needs
> to fix that. But having two layers of idle functions is just silly.
>
> Looking at patch 2 and 3, you're making the same mistake on power, after
> those patches there are multiple ways of registering idle functions, one
> through some native interface and one through cpuidle, this strikes me
> as undesirable.
>
> If cpuidle is a good idle function manager, then it should be good
> enough to be the sole one, if its not, then why bother with it at all.
>
Okay, I'm giving this approach a shot now. i.e. trying to make cpuidle
as _the_ sole idle function manager. This would mean doing away with
pm_idle and ppc_md.power_save. And, cpuidle_idle_call() which is the
main idle loop of cpuidle, present in drivers/cpuidle/cpuidle.c will
have to be called from arch specific code of cpu_idle()
Also this would mean enabling cpuidle for all platforms, even if the
platform doesn't have multiple idle states. So suppose a platform doesnt
have multiple states, it wouldn't want the bloated code of cpuidle
governors, and would want just a simple cpuidle loop.
--arun
>
^ permalink raw reply
* Re: MPC866 FEC's Receive processing thru pre allocated buffers
From: Ganesh Kumar @ 2009-09-03 4:45 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: linuxppc-dev
In-Reply-To: <OF0B184DAC.3E68F19C-ONC1257620.0044C588-C1257620.00466F8B@transmode.se>
Hi Tjernlund,
Thanks a lot for the reply.
I checked in my code regarding to the invalidate/flushing of the=20
data cache. In the fec_init its been done by calling the sequence
/* Make it uncached.
*/
pte =3D va_to_pte(mem_addr);
pte_val(*pte) |=3D _PAGE_NO_CACHE;
flush_tlb_page(init_mm.mmap, mem_addr);
So I did the same thing whenever I allocated new skb, but the=20
problems still showed up, then I saw one comment in FEC code where=20
it says
/* This does 16 byte alignment, exactly what we need.
* The packet length includes FCS, but we don't want to
* include that when passing upstream as it messes up
* bridging applications.
*/
while receiving the frames, I checked my modified code w.r.t the length,
since I was not knowing the receive lengthn while allocating for the
RX ring, I did with a maximum of 2048 bytes length and called the skb_put
to reserve 2048 bytes for data, calling of the skb_put also updated the
skb->len field with 2048, this was causing the problem, the bridge module=20
was trying to send the frame with 2048 bytes even though the actual length
was less number of bytes, so even after sending it to the FEC, the frame was
getting transmitted successfully. So I updated the actual length to the
skb->len field in the rx ISR, the problem is solved now.
But I'm facing problems during load time in bridge mode
PC-1 ---->eth0 [Bridge machine] eth1 ----> PC-2
With the above setup I initiate 1500 pings each of 1400 bytes
from PC1 to PC2, then the ping sequence starts, but after some time
say some 25-35(all 1500 instances) sequences all of a sudden no=20
ping reply is received for any request.
At that time if I observe in the Bridge machine cat /proc/interrupts
the fec interrupts will not get updated there(initially it used to)
again it resumes after some 45-60 seconds and the sequence repeats.
Dunno what's happening with in the FEC if configured in bridge mode
any clue on this, Thanks a lakh in advance.
=2D-Ganesh
On Friday 28 August 2009 18:19, you wrote:
> > Hi All,
> >
> > I've already sent this almost before 6-7 hours, but the
> > mail did not appear on the Aug 2009 archives, So I'm sending
> > it again. Sorry for this!!. Thanks in advance.
> >
> > =A0 =A0 =A0 =A0 I'm working on MPC860 with Linux Kernel 2.4.18.
> > As I'm fine tuning the FEC(Fast Ethernet Controller) driver,
> > I came across the receive side processing of the ethernet frames
> > where in the Rx BD rings are preallocated with the buffers and each time
> > a new frame is received, the whole frame will get copied from the Buffer
> > Descriptors to the external memory by allocating the skb.
> > Is this the right way to do that ?, as memcpy is not efficient inside t=
he
> > ISRs.
> > So I did some changes in the RX BDs initialization, like allocate the s=
kb
> > and initialize the BD's address pointer with the skb->data(using __pa)
> > and then on reception of the frame I take out the skb from theBD and
> > allocate a new skb and reinit the BD address with the newly allocated
> > skb->data.
> >
> > It works for normal conditions, but if I load the driver then
> > I receive lots of corrupted frames, So I tried increasing the
> > RX_RING_SIZE(16) and also enabling the receive dscriptor active only
> > after I come out of the while loop (inside fec_enet_rx)
> > Increasing the Rx ring eliminated the frame corruption and runs fine on
> > load test.
> >
> > But if I configure my Linux box in bridge mode then it doesn't work,
> > i.e., the bridging doesn't happen,
> >
> > =A0 =A0PC-1 ---->eth0 =A0[Bridge machine] eth1 ----> PC-2
> > What I mean here is if we initiate a ping from the
> > PC-1 to PC-2, I don't get any response,
> > it continously try to resole the ARP.
> >
> > What may be the reason??
> > Thanks in advance
>
> A guess, you are missing invalidating the dcache when handing a skb to
> the CPM:
>
> #define CPM_ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE) /* This is
> needed so that invalidate_xxx wont invalidate too much */
>
> static inline void invalidate_dcache_region(void *adr, unsigned long len)
> {
> /* if(len =3D=3D 0) return; len will never be zero */
> len =3D ((len-1) >> LG_L1_CACHE_LINE_SIZE) +1;
> do {
> asm ("dcbi 0,%0" : : "r" (adr) : "memory");
> adr +=3D L1_CACHE_LINE_SIZE;
> } while(--len);
> }
> then:
> invalidate_dcache_region(skb->data, CPM_ENET_RX_FRSIZE);
> bdp->cbd_bufaddr =3D __pa(skb->data);
^ permalink raw reply
* Re: why do we need reloc_offset ??
From: Michael Ellerman @ 2009-09-03 2:19 UTC (permalink / raw)
To: HongWoo Lee; +Cc: linuxppc-dev
In-Reply-To: <5e2889710909012333q69874b24qf6e3c0abfceb8dfd@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1902 bytes --]
On Wed, 2009-09-02 at 15:33 +0900, HongWoo Lee wrote:
> Hi everyone~
>
> In ther linux kernel code, I found the reloc_offset.
>
> {{{
> // file : misc.S
> /* Returns (address we are running at) - (address we were linked at)
> * for use before the text and data are mapped to KERNELBASE.
> */
> _GLOBAL(reloc_offset)
> }}}
>
> I couldn't understand the comment saying "Returns (address we are
> running at) - (address we were linked at)".
> For now, I'm studying each instruction.
>
> And below is best comment I can explain for each instruction.
>
> _GLOBAL(reloc_offset)
> mflr r0 // move from link register, save the return address
> bl 1f // bl 1f
> 1: mflr r3 // move from link register, r3 is just return address pointing itself
At this point r3 contains the value of LR based on the branch we just
did. So it's the address of the current instruction, based on where the
code is _running_.
> LOAD_REG_IMMEDIATE(r4,1b) // get the 1b address, r4 is the address
Here we load into r4 the address of the previous instruction, but based
on the label "1b". The address of the label is calculated by the linker,
so r4 contains the address the instruction was linked at.
> subf r3,r4,r3 // r3 = r3 – r4
So here we calculate any difference between the address the code was
linked at and the address it's running at.
> mtlr r0 // restore return address
> blr
>
> After this, I still don't know why "r3-r4" is the offset.
> And what does it mean ??
The offset is just the difference between the address the code was
linked at and the address it's running it. It's used in places where the
code might be (or is always) running at an address other than the
address it was linked at.
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ 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