* [PATCH v5 3/3] powerpc: Uprobes port to powerpc
From: Ananth N Mavinakayanahalli @ 2012-08-24 7:31 UTC (permalink / raw)
To: ppcdev, lkml
Cc: Srikar Dronamraju, peterz, oleg, Paul Mackerras, Anton Blanchard,
Ingo Molnar
In-Reply-To: <20120824072602.GA32031@in.ibm.com>
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
This is the port of uprobes to powerpc. Usage is similar to x86.
[root@xxxx ~]# ./bin/perf probe -x /lib64/libc.so.6 malloc
Added new event:
probe_libc:malloc (on 0xb4860)
You can now use it in all perf tools, such as:
perf record -e probe_libc:malloc -aR sleep 1
[root@xxxx ~]# ./bin/perf record -e probe_libc:malloc -aR sleep 20
[ perf record: Woken up 22 times to write data ]
[ perf record: Captured and wrote 5.843 MB perf.data (~255302 samples) ]
[root@xxxx ~]# ./bin/perf report --stdio
...
# Samples: 83K of event 'probe_libc:malloc'
# Event count (approx.): 83484
#
# Overhead Command Shared Object Symbol
# ........ ............ ............. ..........
#
69.05% tar libc-2.12.so [.] malloc
28.57% rm libc-2.12.so [.] malloc
1.32% avahi-daemon libc-2.12.so [.] malloc
0.58% bash libc-2.12.so [.] malloc
0.28% sshd libc-2.12.so [.] malloc
0.08% irqbalance libc-2.12.so [.] malloc
0.05% bzip2 libc-2.12.so [.] malloc
0.04% sleep libc-2.12.so [.] malloc
0.03% multipathd libc-2.12.so [.] malloc
0.01% sendmail libc-2.12.so [.] malloc
0.01% automount libc-2.12.so [.] malloc
The trap_nr addition patch is a prereq.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
---
Tested on POWER6; I don't see anything here that should stop it from
working on a ppc32; since I don't have access to a ppc32 machine, it
would be good if somoene could verify that part.
TODO:
Testsuite for uprobes (Not powerpc specific).
V5:
a. Incorporated Oleg's suggestion to make arch_uprobe a union for
easier deref of u32 on powerpc.
b. Incorporated various review comments by Michael Ellerman and
Benjamin Herrenschmidt.
V4:
Enhance arch_analyze_uprobe_insn() to reject uprobes on trap variants.
V3:
Added abort_xol() logic for powerpc, using thread_struct.trap_nr to
determine if the stepped instruction caused an exception.
V2:
a. arch_uprobe_analyze_insn() now gets unsigned long addr.
b. Verified that mtmsr[d] and rfi[d] are handled correctly by
emulate_step() (no changes to this patch).
arch/powerpc/Kconfig | 3
arch/powerpc/include/asm/thread_info.h | 4
arch/powerpc/include/asm/uprobes.h | 55 +++++++++
arch/powerpc/kernel/Makefile | 1
arch/powerpc/kernel/signal.c | 6 +
arch/powerpc/kernel/uprobes.c | 184 +++++++++++++++++++++++++++++++++
6 files changed, 252 insertions(+), 1 deletion(-)
Index: linux-tip-23aug/arch/powerpc/include/asm/thread_info.h
===================================================================
--- linux-tip-23aug.orig/arch/powerpc/include/asm/thread_info.h
+++ linux-tip-23aug/arch/powerpc/include/asm/thread_info.h
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
#define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */
#define TIF_NOERROR 12 /* Force successful syscall return */
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
+#define TIF_UPROBE 14 /* breakpointed or single-stepping */
#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
/* as above, but as bit values */
@@ -118,12 +119,13 @@ static inline struct thread_info *curren
#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE (1<<TIF_UPROBE)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
- _TIF_NOTIFY_RESUME)
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
Index: linux-tip-23aug/arch/powerpc/include/asm/uprobes.h
===================================================================
--- /dev/null
+++ linux-tip-23aug/arch/powerpc/include/asm/uprobes.h
@@ -0,0 +1,55 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * 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 IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+
+#include <linux/notifier.h>
+#include <asm/probes.h>
+
+typedef opcode_t uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES 4
+#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
+
+/* The following alias is needed for reference from arch-agnostic code */
+#define UPROBE_SWBP_INSN BREAKPOINT_INSTRUCTION
+#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */
+
+struct arch_uprobe {
+ union {
+ u8 insn[MAX_UINSN_BYTES];
+ u32 ainsn;
+ };
+};
+
+struct arch_uprobe_task {
+ unsigned long saved_trap_nr;
+};
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+#endif /* _ASM_UPROBES_H */
Index: linux-tip-23aug/arch/powerpc/kernel/Makefile
===================================================================
--- linux-tip-23aug.orig/arch/powerpc/kernel/Makefile
+++ linux-tip-23aug/arch/powerpc/kernel/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_UPROBES) += uprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
Index: linux-tip-23aug/arch/powerpc/kernel/signal.c
===================================================================
--- linux-tip-23aug.orig/arch/powerpc/kernel/signal.c
+++ linux-tip-23aug/arch/powerpc/kernel/signal.c
@@ -11,6 +11,7 @@
#include <linux/tracehook.h>
#include <linux/signal.h>
+#include <linux/uprobes.h>
#include <linux/key.h>
#include <asm/hw_breakpoint.h>
#include <asm/uaccess.h>
@@ -157,6 +158,11 @@ static int do_signal(struct pt_regs *reg
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
{
+ if (thread_info_flags & _TIF_UPROBE) {
+ clear_thread_flag(TIF_UPROBE);
+ uprobe_notify_resume(regs);
+ }
+
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
Index: linux-tip-23aug/arch/powerpc/kernel/uprobes.c
===================================================================
--- /dev/null
+++ linux-tip-23aug/arch/powerpc/kernel/uprobes.c
@@ -0,0 +1,184 @@
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * 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 IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+#include <linux/kdebug.h>
+
+#include <asm/sstep.h>
+
+#define UPROBE_TRAP_NR UINT_MAX
+
+/**
+ * arch_uprobe_analyze_insn
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: vaddr to probe.
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
+ struct mm_struct *mm, unsigned long addr)
+{
+ if (addr & 0x03)
+ return -EINVAL;
+
+ /*
+ * We currently don't support a uprobe on an already
+ * existing breakpoint instruction underneath
+ */
+ if (is_trap(auprobe->ainsn))
+ return -ENOTSUPP;
+ return 0;
+}
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct arch_uprobe_task *autask = ¤t->utask->autask;
+
+ autask->saved_trap_nr = current->thread.trap_nr;
+ current->thread.trap_nr = UPROBE_TRAP_NR;
+ regs->nip = current->utask->xol_vaddr;
+ return 0;
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+ return instruction_pointer(regs);
+}
+
+/*
+ * If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc),
+ * then detect the case where a singlestepped instruction jumps back to its
+ * own address. It is assumed that anything like do_page_fault/do_trap/etc
+ * sets thread.trap_nr != UINT_MAX.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == UINT_MAX set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+ if (t->thread.trap_nr != UPROBE_TRAP_NR)
+ return true;
+
+ return false;
+}
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
+
+ current->thread.trap_nr = utask->autask.saved_trap_nr;
+
+ /*
+ * On powerpc, except for loads and stores, most instructions
+ * including ones that alter code flow (branches, calls, returns)
+ * are emulated in the kernel. We get here only if the emulation
+ * support doesn't exist and have to fix-up the next instruction
+ * to be executed.
+ */
+ regs->nip = utask->vaddr + MAX_UINSN_BYTES;
+ return 0;
+}
+
+/* callback routine for handling exceptions. */
+int arch_uprobe_exception_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = data;
+ struct pt_regs *regs = args->regs;
+
+ /* regs == NULL is a kernel bug */
+ if (WARN_ON(!regs))
+ return NOTIFY_DONE;
+
+ /* We are only interested in userspace traps */
+ if (!user_mode(regs))
+ return NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BPT:
+ if (uprobe_pre_sstep_notifier(regs))
+ return NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (uprobe_post_sstep_notifier(regs))
+ return NOTIFY_STOP;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal, so reset the instruction pointer to its
+ * probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ current->thread.trap_nr = utask->autask.saved_trap_nr;
+ instruction_pointer_set(regs, utask->vaddr);
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ int ret;
+
+ /*
+ * emulate_step() returns 1 if the insn was successfully emulated.
+ * For all other cases, we need to single-step in hardware.
+ */
+ ret = emulate_step(regs, auprobe->ainsn);
+ if (ret > 0)
+ return true;
+
+ return false;
+}
Index: linux-tip-23aug/arch/powerpc/Kconfig
===================================================================
--- linux-tip-23aug.orig/arch/powerpc/Kconfig
+++ linux-tip-23aug/arch/powerpc/Kconfig
@@ -239,6 +239,9 @@ config PPC_OF_PLATFORM_PCI
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y
+config ARCH_SUPPORTS_UPROBES
+ def_bool y
+
config PPC_ADV_DEBUG_REGS
bool
depends on 40x || BOOKE
^ permalink raw reply
* [PATCH 2/3] powerpc: Add trap_nr to thread_struct
From: Ananth N Mavinakayanahalli @ 2012-08-24 7:27 UTC (permalink / raw)
To: ppcdev, lkml
Cc: Srikar Dronamraju, peterz, oleg, Paul Mackerras, Anton Blanchard,
Ingo Molnar
In-Reply-To: <20120824072602.GA32031@in.ibm.com>
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Add thread_struct.trap_nr and use it to store the last exception
the thread experienced. In this patch, we populate the field at
various places where we force_sig_info() to the process.
This is also used in uprobes to determine if the probed instruction
caused an exception.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
---
arch/powerpc/include/asm/processor.h | 1 +
arch/powerpc/kernel/process.c | 2 ++
arch/powerpc/kernel/traps.c | 1 +
arch/powerpc/mm/fault.c | 1 +
4 files changed, 5 insertions(+)
Index: linux-26jul/arch/powerpc/include/asm/processor.h
===================================================================
--- linux-26jul.orig/arch/powerpc/include/asm/processor.h
+++ linux-26jul/arch/powerpc/include/asm/processor.h
@@ -219,6 +219,7 @@ struct thread_struct {
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif
unsigned long dabr; /* Data address breakpoint register */
+ unsigned long trap_nr; /* last trap # on this thread */
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
vector128 vr[32] __attribute__((aligned(16)));
Index: linux-26jul/arch/powerpc/kernel/process.c
===================================================================
--- linux-26jul.orig/arch/powerpc/kernel/process.c
+++ linux-26jul/arch/powerpc/kernel/process.c
@@ -258,6 +258,7 @@ void do_send_trap(struct pt_regs *regs,
{
siginfo_t info;
+ current->thread.trap_nr = signal_code;
if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
11, SIGSEGV) == NOTIFY_STOP)
return;
@@ -275,6 +276,7 @@ void do_dabr(struct pt_regs *regs, unsig
{
siginfo_t info;
+ current->thread.trap_nr = TRAP_HWBKPT;
if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
11, SIGSEGV) == NOTIFY_STOP)
return;
Index: linux-26jul/arch/powerpc/kernel/traps.c
===================================================================
--- linux-26jul.orig/arch/powerpc/kernel/traps.c
+++ linux-26jul/arch/powerpc/kernel/traps.c
@@ -251,6 +251,7 @@ void _exception(int signr, struct pt_reg
if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
local_irq_enable();
+ current->thread.trap_nr = code;
memset(&info, 0, sizeof(info));
info.si_signo = signr;
info.si_code = code;
Index: linux-26jul/arch/powerpc/mm/fault.c
===================================================================
--- linux-26jul.orig/arch/powerpc/mm/fault.c
+++ linux-26jul/arch/powerpc/mm/fault.c
@@ -133,6 +133,7 @@ static int do_sigbus(struct pt_regs *reg
up_read(¤t->mm->mmap_sem);
if (user_mode(regs)) {
+ current->thread.trap_nr = BUS_ADRERR;
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRERR;
^ permalink raw reply
* [PATCH 1/3] powerpc: Consolidate *probe definitions
From: Ananth N Mavinakayanahalli @ 2012-08-24 7:26 UTC (permalink / raw)
To: ppcdev, lkml
Cc: Srikar Dronamraju, peterz, oleg, Paul Mackerras, Anton Blanchard,
Ingo Molnar
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Move is_trap() and relatives to a common file to be shared between *probes.
Code movement only; no change in functionality.
Suggested by Michael Ellerman.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
---
arch/powerpc/include/asm/kprobes.h | 15 +------------
arch/powerpc/include/asm/probes.h | 42 +++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 13 deletions(-)
Index: linux-tip-23aug/arch/powerpc/include/asm/kprobes.h
===================================================================
--- linux-tip-23aug.orig/arch/powerpc/include/asm/kprobes.h
+++ linux-tip-23aug/arch/powerpc/include/asm/kprobes.h
@@ -29,21 +29,16 @@
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/percpu.h>
+#include <asm/probes.h>
#define __ARCH_WANT_KPROBES_INSN_SLOT
struct pt_regs;
struct kprobe;
-typedef unsigned int kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
+typedef opcode_t kprobe_opcode_t;
#define MAX_INSN_SIZE 1
-#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
-#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
-#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
-#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
-
#ifdef CONFIG_PPC64
/*
* 64bit powerpc uses function descriptors.
@@ -72,12 +67,6 @@ typedef unsigned int kprobe_opcode_t;
addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
} \
}
-
-#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
- IS_TWI(instr) || IS_TDI(instr))
-#else
-/* Use stock kprobe_lookup_name since ppc32 doesn't use function descriptors */
-#define is_trap(instr) (IS_TW(instr) || IS_TWI(instr))
#endif
#define flush_insn_slot(p) do { } while (0)
Index: linux-tip-23aug/arch/powerpc/include/asm/probes.h
===================================================================
--- /dev/null
+++ linux-tip-23aug/arch/powerpc/include/asm/probes.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_POWERPC_PROBES_H
+#define _ASM_POWERPC_PROBES_H
+#ifdef __KERNEL__
+/*
+ * Definitions common to probes files
+ *
+ * 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 IBM Corporation, 2012
+ */
+#include <linux/types.h>
+
+typedef u32 opcode_t;
+#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
+
+/* Trap definitions per ISA */
+#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
+#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
+#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
+
+#ifdef CONFIG_PPC64
+#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
+ IS_TWI(instr) || IS_TDI(instr))
+#else
+#define is_trap(instr) (IS_TW(instr) || IS_TWI(instr))
+#endif /* CONFIG_PPC64 */
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_PROBES_H */
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Benjamin Herrenschmidt @ 2012-08-24 7:07 UTC (permalink / raw)
To: Michael Ellerman
Cc: peterz, lkml, oleg, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev, Srikar Dronamraju
In-Reply-To: <1345770803.13865.10.camel@concordia>
On Fri, 2012-08-24 at 11:13 +1000, Michael Ellerman wrote:
>
> Yeah. A NULL regs here is a kernel bug, so I think it's actually
> preferable to crash than silently return.
Or best, if you think there's a remote chance that the bug might hit:
if (WARN(!regs))
return
Cheers,
Ben.
^ permalink raw reply
* RE: [PATCH V9] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Jia Hongtao-B38951 @ 2012-08-24 2:34 UTC (permalink / raw)
To: Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org, Li Yang-R58472
In-Reply-To: <5036C7AE.9020500@freescale.com>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogV29vZCBTY290dC1CMDc0
MjENCj4gU2VudDogRnJpZGF5LCBBdWd1c3QgMjQsIDIwMTIgODoxNiBBTQ0KPiBUbzogSmlhIEhv
bmd0YW8tQjM4OTUxDQo+IENjOiBsaW51eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZzsgZ2FsYWtA
a2VybmVsLmNyYXNoaW5nLm9yZzsgTGkgWWFuZy0NCj4gUjU4NDcyOyBXb29kIFNjb3R0LUIwNzQy
MQ0KPiBTdWJqZWN0OiBSZTogW1BBVENIIFY5XSBwb3dlcnBjL2ZzbC1wY2k6IFVuaWZ5IHBjaS9w
Y2llIGluaXRpYWxpemF0aW9uDQo+IGNvZGUNCj4gDQo+IE9uIDA4LzIzLzIwMTIgMDQ6MzEgQU0s
IEppYSBIb25ndGFvIHdyb3RlOg0KPiA+ICtzdGF0aWMgdm9pZCBtcGM4NXh4X2Nkc19wY2lfYXNz
aWduX3ByaW1hcnkodm9pZCkNCj4gPiArew0KPiA+ICsjaWZkZWYgQ09ORklHX1BDSQ0KPiA+ICsJ
c3RydWN0IGRldmljZV9ub2RlICpucDsNCj4gPiArDQo+ID4gKwlpZiAoZnNsX3BjaV9wcmltYXJ5
KQ0KPiA+ICsJCXJldHVybjsNCj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJICogTVBDODV4eF9DRFMg
aGFzIElTQSBicmlkZ2UgYnV0IHVuZm9ydHVuYXRlbHkgdGhlcmUgaXMgbm8NCj4gPiArCSAqIGlz
YSBub2RlIGluIGRldmljZSB0cmVlLiBXZSBub3cgbG9va2luZyBmb3IgaTgyNTkgbm9kZSBhcw0K
PiA+ICsJICogYSB0ZW1wb3Jhcnkgd29ya2Fyb3VuZCBmb3Igc3VjaCBhIGJyb2tlbiBkZXZpY2Ug
dHJlZS4NCj4gPiArCSAqIFRoaXMgY2FuIGdvIGF3YXkgb25jZSB0aGUgZGV2aWNlIHRyZWUgaXMg
dXBkYXRlZC4NCj4gPiArCSAqLw0KPiANCj4gSXQgY2Fubm90IGdvIGF3YXkgb25jZSB0aGUgZGV2
aWNlIHRyZWUgaXMgdXBkYXRlZCwgYmVjYXVzZSB3ZSBtYWludGFpbg0KPiBzdXBwb3J0IGZvciBv
bGQgZGV2aWNlIHRyZWVzIHdpdGhpbiByZWFzb24uICBJdCdzIG5vdCBsaWtlIHRoaXMgaXMgY29y
ZQ0KPiBrZXJuZWwgY29kZTsgdGhlIGNvc3Qgb2YgaGF2aW5nIHRoaXMgY29tcGF0aWJpbGl0eSBo
ZXJlIGlzIG1pbmltYWwsIGV2ZW4NCj4gaWYgdGhlIGRldmljZSB0cmVlcyB3ZSdyZSBzdGF5aW5n
IGNvbXBhdGlibGUgd2l0aCBhcmUgdGVjaG5pY2FsbHkgYnJva2VuLg0KPiBDb21wYXJlIHRoYXQg
dG8gY3VzdG9tZXIgc3VwcG9ydCBlZmZvcnQgaWYgdGhpcyBicmVha3Mgc29tZW9uZSdzIGN1c3Rv
bQ0KPiBib2FyZCB3aXRoIGEgZm9ya2VkIGRldmljZSB0cmVlLCBvciBpZiB1cGdyYWRpbmcgdGhl
IGRldmljZSB0cmVlIGJyZWFrcw0KPiBzb21lb25lJ3Mgb2xkIFUtQm9vdC4NCj4gDQo+IC1TY290
dA0KDQoNCkhvdyBhYm91dCBjaGFuZ2luZyB0aGUgY29tbWVudHMgdG8gdGhpczoNCg0KLyoNCiAq
IE1QQzg1eHhfQ0RTIGhhcyBJU0EgYnJpZGdlIGJ1dCB1bmZvcnR1bmF0ZWx5IHRoZXJlIGlzIG5v
DQogKiBpc2Egbm9kZSBpbiBkZXZpY2UgdHJlZS4gV2Ugbm93IGxvb2tpbmcgZm9yIGk4MjU5IG5v
ZGUgYXMNCiAqIGEgd29ya2Fyb3VuZCBmb3Igc3VjaCBhIGJyb2tlbiBkZXZpY2UgdHJlZS4gVGhp
cyByb3V0aW5lDQogKiBpcyBmb3IgY29tcGx5aW5nIHRvIGFsbCBkZXZpY2UgdHJlZXMuDQogKi8N
Cg0KQW5kIGFueSBvdGhlciBjb21tZW50cz8NCg0KVGhhbmtzLg0KLUhvbmd0YW8uDQo=
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Michael Ellerman @ 2012-08-24 1:33 UTC (permalink / raw)
To: Srikar Dronamraju
Cc: peterz, lkml, oleg, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev
In-Reply-To: <20120823053234.GE25338@linux.vnet.ibm.com>
On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> >
> > These seem to be duplicated in kprobes.h, can we consolidate them.
> >
> > > +struct arch_uprobe {
> > > + u8 insn[MAX_UINSN_BYTES];
> > > +};
> >
> > Why not uprobe_opcode_t insn ?
> >
>
> insn is updated/accessed in the arch independent code. Size of
> uprobe_opcode_t could be different for different archs. uprobe_opcode_t
> represents the size of the smallest breakpoint instruction for an arch.
>
> Hence u8 works out the best. I know we could still use uprobe_opcode_t
> and achieve the same. In which case, we would have to interpret
> MAX_UINSN_BYTES differently. Do you see any advantages of using
> uprobe_opcode_t instead of u8 across archs?
It's not a big deal, just a bit of a nit.
It just feels a bit messy to have uprobe_opcode_t and also expect the
arch code to use an array.
It seems like if we need uprobe_opcode_t then the generic code should
expect to use that everywhere.
Or, we should get ride of uprobe_opcode_t and use u8 (or void *).
> > > void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
> > > {
> > > + if (thread_info_flags & _TIF_UPROBE) {
> > > + clear_thread_flag(TIF_UPROBE);
> > > + uprobe_notify_resume(regs);
> > > + }
> >
> > Presumably this ordering is crucial, ie. uprobes before signals.
> >
>
> Yes, we would want uprobes to have a say before do_signal can take a
> look.
A comment would be good IMHO, so in 10 years we don't forget.
> > I am probably missing something, but why do we need to execute out of
> > line?
>
> The other alternative to execute out of line is the current inline
> singlestepping. In inline singlestepping, we would have to guard other
> tasks from executing the same instruction.
>
> Executing out of line solves this problem.
Yeah ignore that, I was forgetting that the original trap is caused by a
patched instruction.
> > > +/**
> > > + * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
> > > + * @regs: Reflects the saved state of the task after it has hit a breakpoint
> > > + * instruction.
> > > + * Return the address of the breakpoint instruction.
> > > + */
> > > +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
> > > +{
> > > + return instruction_pointer(regs);
> > > +}
> >
> > This seems like it would be better in asm/uprobes.h as a static inline,
> > but that's not your fault.
> >
>
> We want archs to override uprobe_get_swbp_addr() if the default
> uprobe_get_swbp_addr() doesnt suite for a particular arch. Do you have
> better ways to achieve this. Initially we were using arch specific
> callbacks from which we moved to using weak functions based on reviews.
OK, having a default that is weak makes sense if there is one behaviour
that is common across arches, but a few arches need to override it. A
static inline in the arch header is simpler if the behaviour is actually
different across all arches.
The current default implements the x86 behaviour, where the instruction
pointer has moved past the breakpoint instruction.
What does ARM do? ie. is this behaviour actually the right default?
> > > + /*
> > > + * emulate_step() returns 1 if the insn was successfully emulated.
> > > + * For all other cases, we need to single-step in hardware.
> > > + */
> > > + ret = emulate_step(regs, insn);
> > > + if (ret > 0)
> > > + return true;
> >
> > This actually emulates the instruction, ie. the contents of regs are
> > changed based on the instruction.
> >
> > That seems to differ vs x86, where arch_uprobe_skip_sstep() just checks
> > the instruction and returns true/false. Is that because on x86 they are
> > only returning true for nops? ie. there is no emulation to be done?
> >
>
> Yes, In x86, we currently support skip for nop instructions, Once we add
> code for skipping other instructions in x86, we could enhance them to
> skip them too.
(and emulating them right?)
> > It's a little surprising that can_skip_sstep() actually emulates the
> > instruction, but again that's not your fault.
>
> Are you saying its doing more than what the name suggests or to the fact
> that can_skip_step should ideally be called just once?
Yeah just that the name suggests it is just a "checker" function, but it
actually emulates the instruction and changes the task state!
cheers
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Michael Ellerman @ 2012-08-24 1:13 UTC (permalink / raw)
To: ananth
Cc: Srikar Dronamraju, peterz, lkml, oleg, Paul Mackerras,
Anton Blanchard, Ingo Molnar, ppcdev
In-Reply-To: <20120823055820.GA14603@in.ibm.com>
On Thu, 2012-08-23 at 11:28 +0530, Ananth N Mavinakayanahalli wrote:
> On Thu, Aug 23, 2012 at 02:28:20PM +1000, Michael Ellerman wrote:
> > On Wed, 2012-08-22 at 13:57 +0530, Ananth N Mavinakayanahalli wrote:
> > > From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
> > >
> > > This is the port of uprobes to powerpc. Usage is similar to x86.
> >
> > Hi Ananth,
> >
> > Excuse my ignorance of uprobes, some comments inline ...
>
> Thanks for the review Michael!
>
> > > [root@xxxx ~]# ./bin/perf probe -x /lib64/libc.so.6 malloc
> > > Added new event:
> > > probe_libc:malloc (on 0xb4860)
> > >
> > > You can now use it in all perf tools, such as:
> > >
> > > perf record -e probe_libc:malloc -aR sleep 1
> >
> > Is there a test suite for any of this?
>
> We don't have a formal testsuite yet, but the usual way of testing it is
> to run kernbench while registering/unregistering a bunch of probes
> periodically.
OK. Someone should put that on their TODO list, otherwise in a year or
two it'll be broken and we won't notice :)
> > It would be nice if someone could consolidate this with kprobe_opcode_t.
>
> Thats on the TODO after the uprobes code stabilizes further.
>
> I am wondering which file would be appropriate? We could either
> consolidate a bunch of these into asm/kdebug.h or asm/ptrace.h. Any
> preference/suggestion?
Add a new one :)
> > > +#define MAX_UINSN_BYTES 4
> > > +#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> > > +
> > > +#define UPROBE_SWBP_INSN 0x7fe00008
> >
> > This is just "trap" ?
>
> Yes. But since its referred to in arch agnostic code too, we'd have to alias
> it thus.
Yep I was just checking, I think it's probably worth a comment.
> > > +#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */
> > > +
> > > +#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
> > > +#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
> > > +#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
> > > +#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
> > > +
> > > +#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
> > > + IS_TWI(instr) || IS_TDI(instr))
> >
> > These seem to be duplicated in kprobes.h, can we consolidate them.
>
> Yes, similar to the opcode_t types above.
Hmm, OK. Any reason you can't include kprobes.h to get those?
> > > +struct arch_uprobe {
> > > + u8 insn[MAX_UINSN_BYTES];
> > > +};
> >
> > Why not uprobe_opcode_t insn ?
>
> I had a similar discussion with Srikar while doing the port, but he has
> reasons for this...
OK, will argue with him :D
> > > +/**
> > > + * arch_uprobe_analyze_insn
> >
> > Analyze what about the instruction?
>
+ /*
> Depends on the architecture. On x86, we need to verify if the address is
> at an instruction boundary, and if the instruction can be probed at all.
> On powerpc, we have an easier time. We just validate the address is
> aligned at instruction boundary and flag if the instruction at the
> address is a trap variant.
+ */
:)
> > > + * @mm: the probed address space.
> > > + * @arch_uprobe: the probepoint information.
> > > + * @addr: vaddr to probe.
> > > + * Return 0 on success or a -ve number on error.
> > > + */
> > > +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
> > > +{
> > > + unsigned int insn;
> > > +
> > > + if (addr & 0x03)
> > > + return -EINVAL;
> > > +
> > > + memcpy(&insn, auprobe->insn, MAX_UINSN_BYTES);
> >
> > We shouldn't need to use memcpy, we know it's a u32.
>
> OK. Right now, its u8 insn[4], so I did this to be 'correct'. But I
> agree we can just do an assignment.
Yeah, at least in the arch code I think we should just use u32 and
assign directly.
> > > +/* callback routine for handling exceptions. */
> > > +int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data)
> > > +{
> > > + struct die_args *args = data;
> > > + struct pt_regs *regs = args->regs;
> > > +
> > > + /* We are only interested in userspace traps */
> > > + if (regs && !user_mode(regs))
> > > + return NOTIFY_DONE;
> >
> > Do we ever get here with a NULL regs?
>
> I don't think so. Its just a paranoid check. Do you prefer it to be
> removed?
Yeah. A NULL regs here is a kernel bug, so I think it's actually
preferable to crash than silently return.
cheers
^ permalink raw reply
* Re: [PATCH V9] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Scott Wood @ 2012-08-24 0:15 UTC (permalink / raw)
To: Jia Hongtao; +Cc: B07421, linuxppc-dev
In-Reply-To: <1345714301-13027-1-git-send-email-B38951@freescale.com>
On 08/23/2012 04:31 AM, Jia Hongtao wrote:
> +static void mpc85xx_cds_pci_assign_primary(void)
> +{
> +#ifdef CONFIG_PCI
> + struct device_node *np;
> +
> + if (fsl_pci_primary)
> + return;
> +
> + /*
> + * MPC85xx_CDS has ISA bridge but unfortunately there is no
> + * isa node in device tree. We now looking for i8259 node as
> + * a temporary workaround for such a broken device tree.
> + * This can go away once the device tree is updated.
> + */
It cannot go away once the device tree is updated, because we maintain
support for old device trees within reason. It's not like this is core
kernel code; the cost of having this compatibility here is minimal, even
if the device trees we're staying compatible with are technically
broken. Compare that to customer support effort if this breaks
someone's custom board with a forked device tree, or if upgrading the
device tree breaks someone's old U-Boot.
-Scott
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Benjamin Herrenschmidt @ 2012-08-23 21:57 UTC (permalink / raw)
To: Srikar Dronamraju
Cc: peterz, lkml, oleg, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev
In-Reply-To: <20120823161737.GG25338@linux.vnet.ibm.com>
On Thu, 2012-08-23 at 21:47 +0530, Srikar Dronamraju wrote:
> * Benjamin Herrenschmidt <benh@kernel.crashing.org> [2012-08-23 20:06:18]:
>
> > On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> > > >
> > >
> > > insn is updated/accessed in the arch independent code. Size of
> > > uprobe_opcode_t could be different for different archs.
> > > uprobe_opcode_t
> > > represents the size of the smallest breakpoint instruction for an
> > > arch.
> > >
> > > Hence u8 works out the best. I know we could still use uprobe_opcode_t
> > > and achieve the same. In which case, we would have to interpret
> > > MAX_UINSN_BYTES differently. Do you see any advantages of using
> > > uprobe_opcode_t instead of u8 across archs?
> >
> > But don't you actively rely on the fact that on powerpc, unlike x86, you
> > -can- atomically replace an instruction with a single 32-bit store ?
> >
>
> We are not doing a replace here, we are only copying from the ->vm_file
> for the largest size instruction possible for that instruction. For
> powerpc, this is easy because of fixed size instructions.
>
> On other archs, at this point, we dont even know the length of the
> underlying instruction.
>
> Now there are 3 ways to handle this:
> 1. use arch independent copy_insn() (current.) (handles if the
> instruction spreads across multiple pages on non fixed instruction
> archs).
>
> 2. make the copy_insn() arch specific, that would mean every arch will
> have to do read_mapping_page etc.
>
> 3. have a arch specific hook in arch independent copy_insn code that
> either does a memcpy for non fixed instruction archs or does an
> assignment in archs like powerpc.
>
> I think you are suggesting option 3.
> But instead of adding another call that does the arch specific stuff, we
> are probably be better of doing a memcpy. Right?
>
> For all powerpc references to insn we could refer to it as u32 as
> suggested by Oleg.
Ok, doens't matter much either way, it's just odd and inefficient.
Cheers,
Ben.
^ permalink raw reply
* Re: Build regressions/improvements in v3.6-rc3
From: Geert Uytterhoeven @ 2012-08-23 20:50 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-xtensa, the arch/x86 maintainers, linuxppc-dev
In-Reply-To: <1345754768-4634-1-git-send-email-geert@linux-m68k.org>
On Thu, Aug 23, 2012 at 10:46 PM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> JFYI, when comparing v3.6-rc3 to v3.6-rc2[3], the summaries are:
> - build errors: +13/-9
+ arch/x86/include/asm/uaccess_32.h: error: call to
'copy_from_user_overflow' declared with attribute error:
copy_from_user() buffer size is not provably correct: => 211:26
i386_defconfig, i386-randconfig, x86_64_defconfig
+ drivers/extcon/extcon_gpio.c: error: implicit declaration of
function 'devm_gpio_request_one'
[-Werror=implicit-function-declaration]: => 110:2
xtensa-allmodconfig
+ error: No rule to make target drivers/scsi/aic7xxx/aicasm/*.[chyl]: => N/A
i386-randconfig
+ error: eni.c: relocation truncated to fit: R_PPC64_REL24 against
symbol `._raw_read_lock' defined in .spinlock.text section in
kernel/built-in.o: => (.text+0x1ff91bc)
+ error: eni.c: relocation truncated to fit: R_PPC64_REL24 against
symbol `.sprintf' defined in .text section in lib/lib.a(vsprintf.o):
=> (.text+0x1ff940c)
+ error: eni.c: relocation truncated to fit: R_PPC64_REL24 against
symbol `_restgpr0_16' defined in .text.save.restore section in
arch/powerpc/lib/built-in.o: => (.text+0x1ffa6e8)
+ error: eni.c: relocation truncated to fit: R_PPC64_REL24 against
symbol `_savegpr0_27' defined in .text.save.restore section in
arch/powerpc/lib/built-in.o: => (.text+0x1ff9854)
+ error: eni.c: relocation truncated to fit: R_PPC64_REL24 against
symbol `_savegpr0_30' defined in .text.save.restore section in
arch/powerpc/lib/built-in.o: => (.text+0x1ff8eb4), (.text+0x1ff8e80)
+ error: fore200e.c: relocation truncated to fit: R_PPC64_REL24
against symbol `._raw_spin_unlock_irqrestore' defined in
.spinlock.text section in kernel/built-in.o: => (.text+0x1ff82cc),
(.text+0x1ff8278)
+ error: fore200e.c: relocation truncated to fit: R_PPC64_REL24
against symbol `.mutex_unlock' defined in .sched.text section in
kernel/built-in.o: => (.text+0x1ff83fc), (.text+0x1ff83a8)
powerpc-allyesconfig
+ error: via-pmu-event.c: undefined reference to
`.input_allocate_device': => .init.text+0xdfbc)
+ error: via-pmu-event.c: undefined reference to
`.input_free_device': => .init.text+0xe084)
+ error: via-pmu-event.c: undefined reference to
`.input_register_device': => .init.text+0xe06c)
powerpc-randconfig
> [1] http://kisskb.ellerman.id.au/kisskb/head/5359/ (all 116 configs)
> [3] http://kisskb.ellerman.id.au/kisskb/head/5338/ (all 116 configs)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 1/2] PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too
From: Olof Johansson @ 2012-08-23 18:20 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Jacob Pan, linux-pci, linux-kernel, Jesse Barnes, Ivan Kokshaysky,
Matthew Wilcox, Greg Kroah-Hartman, linuxppc-dev, Robert Hancock
In-Reply-To: <20120823180213.GA31462@google.com>
Hi,
On Thu, Aug 23, 2012 at 11:02 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Thu, Aug 23, 2012 at 12:28:23AM -0700, Olof Johansson wrote:
>> Hi,
>>
>> On Mon, Jul 9, 2012 at 11:20 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> > After 253d2e5498, we disable MEM and IO decoding for most devices while we
>> > size 32-bit BARs. However, we restore the original COMMAND register before
>> > we size the upper 32 bits of 64-bit BARs, so we can still cause a conflict.
>> >
>> > This patch waits to restore the original COMMAND register until we're
>> > completely finished sizing the BAR.
>> >
>> > Reference: https://lkml.org/lkml/2007/8/25/154
>> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>>
>> This patch causes boot lockup on PA Semi hardware, since it disables
>> the bar on the UART that is used for console, and it has printks
>> between the old and the new re-enable location. If I boot with 'debug'
>> level for printk, I hit this. If I boot with just regular console
>> args, I don't.
>>
>> I'm guessing any other platform that uses MMIO-based UART on PCI for
>> console will have similar issues. I can verify on Chrome OS x86
>> hardware tomorrow if legacy powerpc isn't important enough to care
>> about. :-)
>>
>> I have no proposal for a fix for this. Can you please consider
>> reverting for 3.6 unless someone has a better idea?
>
> Thanks a lot for finding and debugging this!
>
> Can you try the patch below?
>
>
> commit cfc29ece86d648e63fb46de81b2bf8e3e107672c
> Author: Bjorn Helgaas <bhelgaas@google.com>
> Date: Thu Aug 23 10:53:08 2012 -0600
>
> PCI: Don't print anything while decoding is disabled
>
> If we try to print to the console device while its decoding is disabled,
> the system will hang.
>
> Reported-by: Olof Johansson <olof@lixom.net>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Ah yes, of course. Teaches me to try to do anything productive late at
night. Tested fine here.
Acked-by: Olof Johansson <olof@lixom.net>
Thanks!
-Olof
^ permalink raw reply
* Re: [PATCH 1/2] PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too
From: Bjorn Helgaas @ 2012-08-23 18:02 UTC (permalink / raw)
To: Olof Johansson
Cc: Jacob Pan, linux-pci, linux-kernel, Jesse Barnes, Ivan Kokshaysky,
Matthew Wilcox, Greg Kroah-Hartman, linuxppc-dev, Robert Hancock
In-Reply-To: <CAOesGMgUGUG9Z=x6ssumVkAxN6fHoeyAJ3-P8CoaNTGas7-vmg@mail.gmail.com>
On Thu, Aug 23, 2012 at 12:28:23AM -0700, Olof Johansson wrote:
> Hi,
>
> On Mon, Jul 9, 2012 at 11:20 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> > After 253d2e5498, we disable MEM and IO decoding for most devices while we
> > size 32-bit BARs. However, we restore the original COMMAND register before
> > we size the upper 32 bits of 64-bit BARs, so we can still cause a conflict.
> >
> > This patch waits to restore the original COMMAND register until we're
> > completely finished sizing the BAR.
> >
> > Reference: https://lkml.org/lkml/2007/8/25/154
> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
>
> This patch causes boot lockup on PA Semi hardware, since it disables
> the bar on the UART that is used for console, and it has printks
> between the old and the new re-enable location. If I boot with 'debug'
> level for printk, I hit this. If I boot with just regular console
> args, I don't.
>
> I'm guessing any other platform that uses MMIO-based UART on PCI for
> console will have similar issues. I can verify on Chrome OS x86
> hardware tomorrow if legacy powerpc isn't important enough to care
> about. :-)
>
> I have no proposal for a fix for this. Can you please consider
> reverting for 3.6 unless someone has a better idea?
Thanks a lot for finding and debugging this!
Can you try the patch below?
commit cfc29ece86d648e63fb46de81b2bf8e3e107672c
Author: Bjorn Helgaas <bhelgaas@google.com>
Date: Thu Aug 23 10:53:08 2012 -0600
PCI: Don't print anything while decoding is disabled
If we try to print to the console device while its decoding is disabled,
the system will hang.
Reported-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6c143b4..9f8a6b7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
case PCI_BASE_ADDRESS_MEM_TYPE_32:
break;
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
- dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+ /* 1M mem BAR treated as 32-bit BAR */
break;
case PCI_BASE_ADDRESS_MEM_TYPE_64:
flags |= IORESOURCE_MEM_64;
break;
default:
- dev_warn(&dev->dev,
- "mem unknown type %x treated as 32-bit BAR\n",
- mem_type);
+ /* mem unknown type treated as 32-bit BAR */
break;
}
return flags;
@@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u32 l, sz, mask;
u16 orig_cmd;
struct pci_bus_region region;
+ bool bar_too_big = false, bar_disabled = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
+ /* No printks while decoding is disabled! */
if (!dev->mmio_always_on) {
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
pci_write_config_word(dev, PCI_COMMAND,
@@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
- dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
- pos);
+ bar_too_big = true;
goto fail;
}
@@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = 0;
region.end = sz64;
pcibios_bus_to_resource(dev, res, ®ion);
+ bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
pcibios_bus_to_resource(dev, res, ®ion);
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
- pos, res);
}
} else {
sz = pci_size(l, sz, mask);
@@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = l;
region.end = l + sz;
pcibios_bus_to_resource(dev, res, ®ion);
-
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
}
- out:
+ goto out;
+
+
+fail:
+ res->flags = 0;
+out:
if (!dev->mmio_always_on)
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
+ if (bar_too_big)
+ dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+ if (res->flags && !bar_disabled)
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
- fail:
- res->flags = 0;
- goto out;
}
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
^ permalink raw reply related
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Srikar Dronamraju @ 2012-08-23 16:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: peterz, lkml, oleg, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev
In-Reply-To: <1345716378.29170.4.camel@pasglop>
* Benjamin Herrenschmidt <benh@kernel.crashing.org> [2012-08-23 20:06:18]:
> On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> > >
> >
> > insn is updated/accessed in the arch independent code. Size of
> > uprobe_opcode_t could be different for different archs.
> > uprobe_opcode_t
> > represents the size of the smallest breakpoint instruction for an
> > arch.
> >
> > Hence u8 works out the best. I know we could still use uprobe_opcode_t
> > and achieve the same. In which case, we would have to interpret
> > MAX_UINSN_BYTES differently. Do you see any advantages of using
> > uprobe_opcode_t instead of u8 across archs?
>
> But don't you actively rely on the fact that on powerpc, unlike x86, you
> -can- atomically replace an instruction with a single 32-bit store ?
>
We are not doing a replace here, we are only copying from the ->vm_file
for the largest size instruction possible for that instruction. For
powerpc, this is easy because of fixed size instructions.
On other archs, at this point, we dont even know the length of the
underlying instruction.
Now there are 3 ways to handle this:
1. use arch independent copy_insn() (current.) (handles if the
instruction spreads across multiple pages on non fixed instruction
archs).
2. make the copy_insn() arch specific, that would mean every arch will
have to do read_mapping_page etc.
3. have a arch specific hook in arch independent copy_insn code that
either does a memcpy for non fixed instruction archs or does an
assignment in archs like powerpc.
I think you are suggesting option 3.
But instead of adding another call that does the arch specific stuff, we
are probably be better of doing a memcpy. Right?
For all powerpc references to insn we could refer to it as u32 as
suggested by Oleg.
--
Thanks and Regards
Srikar
> If you don't you should consider it, and that makes defining this as a
> u8 array non-sensical (as is using memcpy)
>
> Ben.
>
>
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Srikar Dronamraju @ 2012-08-23 16:02 UTC (permalink / raw)
To: Oleg Nesterov
Cc: peterz, lkml, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev
In-Reply-To: <20120823090209.GA4630@redhat.com>
* Oleg Nesterov <oleg@redhat.com> [2012-08-23 11:02:09]:
> On 08/23, Benjamin Herrenschmidt wrote:
> >
> > On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> > > >
> > >
> > > insn is updated/accessed in the arch independent code. Size of
> > > uprobe_opcode_t could be different for different archs.
> > > uprobe_opcode_t
> > > represents the size of the smallest breakpoint instruction for an
> > > arch.
> > >
> > > Hence u8 works out the best. I know we could still use uprobe_opcode_t
> > > and achieve the same. In which case, we would have to interpret
> > > MAX_UINSN_BYTES differently. Do you see any advantages of using
> > > uprobe_opcode_t instead of u8 across archs?
> >
> > But don't you actively rely on the fact that on powerpc, unlike x86, you
> > -can- atomically replace an instruction with a single 32-bit store ?
>
> I must have missed something...
>
> But powerpc does not replace an instruction, the arch independent code
> does this and it assumes that uprobe->arch.insn is u8[MAX_UINSN_BYTES].
>
> Perhaps you meant that on powerpc it is "safe" to replace the insn
> even if this can race with some CPU executing this code? But uprobes
> has to replace the original page anyway, we should not write to
> ->vm_file.
I think Ben is referring to the fact that because we use an array we
endup using memcpy to copy the original instruction from the ->vm_file.
>
> I agree that memcpy() in arch_uprobe_analyze_insn() and
> arch_uprobe_skip_sstep() looks a bit strange. May be powerpc can do
>
> struct arch_uprobe {
> union {
> u8 insn[MAX_UINSN_BYTES];
> u32 ainsn;
> };
> };
>
> and use auprobe->ainsn directly, I dunno.
I think this should work.
Ben would this suffice?
^ permalink raw reply
* Re: [git pull] Please pull powerpc.git merge branch (updated)
From: Kumar Gala @ 2012-08-23 16:00 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1208171256150.26104@right.am.freescale.net>
[ Added defconfig updates from Kim to fix NFS boot on yocto ]
The following changes since commit 0d7614f09c1ebdbaa1599a5aba7593f147bf96ee:
Linux 3.6-rc1 (2012-08-02 16:38:10 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git merge
for you to fetch changes up to 1267643dc311e860e728dbd09a97c2e0a773bfdb:
powerpc/fsl: fix "Failed to mount /dev: No such device" errors (2012-08-23 10:46:20 -0500)
----------------------------------------------------------------
Jia Hongtao (1):
powerpc/fsl-pci: Only scan PCI bus if configured as a host
Kim Phillips (2):
powerpc/fsl: update defconfigs
powerpc/fsl: fix "Failed to mount /dev: No such device" errors
Shengzhou Liu (1):
powerpc/p4080ds: dts - add usb controller version info and port0
Tiejun Chen (1):
booke/wdt: some ioctls do not return values properly
Zhao Chenhui (1):
powerpc/85xx: mpc85xx_defconfig - add VIA PATA support for MPC85xxCDS
arch/powerpc/boot/dts/fsl/p4080si-post.dtsi | 7 ++++++
arch/powerpc/configs/85xx/p1023rds_defconfig | 31 ++++++++----------------
arch/powerpc/configs/corenet32_smp_defconfig | 29 +++++++---------------
arch/powerpc/configs/corenet64_smp_defconfig | 1 +
arch/powerpc/configs/mpc83xx_defconfig | 18 ++++----------
arch/powerpc/configs/mpc85xx_defconfig | 33 +++++++-------------------
arch/powerpc/configs/mpc85xx_smp_defconfig | 32 +++++++------------------
arch/powerpc/sysdev/fsl_pci.c | 13 ++++++----
drivers/watchdog/booke_wdt.c | 7 +++---
9 files changed, 60 insertions(+), 111 deletions(-)
^ permalink raw reply
* Re: [PATCH] powerpc: dts: 52xx: drop critical IRQ from dts files
From: Grant Likely @ 2012-08-23 15:59 UTC (permalink / raw)
To: Wolfram Sang; +Cc: John Bonesio, linuxppc-dev, Anatolij Gustschin
In-Reply-To: <1345735866-10001-1-git-send-email-w.sang@pengutronix.de>
On Thu, Aug 23, 2012 at 4:31 PM, Wolfram Sang <w.sang@pengutronix.de> wrote:
> The wakeup-gpios have been assigned a critical IRQ in current
> devicetrees. The PIC driver does not support critical IRQs, though, which
> leads to the following error when booting (a PCM030 in this case):
>
> mpc52xx_irqhost_map: invalid irq: virq=16, l1=0, l2=3
> irq: irq-16==>hwirq-0x3 mapping failed: -22
> [WARNing skipped]
>
> Remove these entries until they are supported, if ever.
The warning is a bug since the irq specifier is valid. Removing the
irqs from the .dts files isn't the solution.
g.
>
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> Cc: John Bonesio <bones@secretlab.ca>
> Cc: Anatolij Gustschin <agust@denx.de>
> ---
> arch/powerpc/boot/dts/lite5200.dts | 2 +-
> arch/powerpc/boot/dts/mpc5200b.dtsi | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
> index 179a178..25adace 100644
> --- a/arch/powerpc/boot/dts/lite5200.dts
> +++ b/arch/powerpc/boot/dts/lite5200.dts
> @@ -141,7 +141,7 @@
> gpio@c00 {
> compatible = "fsl,mpc5200-gpio-wkup";
> reg = <0xc00 0x40>;
> - interrupts = <1 8 0 0 3 0>;
> + interrupts = <1 8 0>;
> gpio-controller;
> #gpio-cells = <2>;
> };
> diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi
> index 7ab286a..e610d68 100644
> --- a/arch/powerpc/boot/dts/mpc5200b.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5200b.dtsi
> @@ -141,7 +141,7 @@
> gpio_wkup: gpio@c00 {
> compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
> reg = <0xc00 0x40>;
> - interrupts = <1 8 0 0 3 0>;
> + interrupts = <1 8 0>;
> gpio-controller;
> #gpio-cells = <2>;
> };
> --
> 1.7.10.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/fsl: update defconfigs
From: Kumar Gala @ 2012-08-23 15:58 UTC (permalink / raw)
To: Kim Phillips; +Cc: linuxppc-dev
In-Reply-To: <20120822134324.c504462a553c7a861f3e9865@freescale.com>
On Aug 22, 2012, at 1:43 PM, Kim Phillips wrote:
> run make savedefconfig on fsl defconfigs.
>=20
> Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
> ---
> arch/powerpc/configs/85xx/p1023rds_defconfig | 30 =
++++++++-------------------
> arch/powerpc/configs/corenet32_smp_defconfig | 28 =
+++++++------------------
> arch/powerpc/configs/mpc83xx_defconfig | 17 ++++-----------
> arch/powerpc/configs/mpc85xx_defconfig | 31 =
+++++++---------------------
> arch/powerpc/configs/mpc85xx_smp_defconfig | 31 =
+++++++---------------------
> 5 files changed, 35 insertions(+), 102 deletions(-)
applied to merge
- k=
^ permalink raw reply
* Re: [PATCH 2/2 v2] powerpc/fsl: fix "Failed to mount /dev: No such device" errors
From: Kumar Gala @ 2012-08-23 15:58 UTC (permalink / raw)
To: Kim Phillips; +Cc: linuxppc-dev
In-Reply-To: <20120822134330.288990f2699569868923c23c@freescale.com>
On Aug 22, 2012, at 1:43 PM, Kim Phillips wrote:
> Yocto (Built by Poky 7.0) 1.2 root filesystems fail to boot,
> at least over nfs, with:
>
> Failed to mount /dev: No such device
>
> Configuring DEVTMPFS fixes it.
>
> Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
> ---
> v2: separated savedefconfig updates, rebased on merge branch
>
> arch/powerpc/configs/85xx/p1023rds_defconfig | 1 +
> arch/powerpc/configs/corenet32_smp_defconfig | 1 +
> arch/powerpc/configs/corenet64_smp_defconfig | 1 +
> arch/powerpc/configs/mpc83xx_defconfig | 1 +
> arch/powerpc/configs/mpc85xx_defconfig | 1 +
> arch/powerpc/configs/mpc85xx_smp_defconfig | 1 +
> 6 files changed, 6 insertions(+)
applied to merge
- k
^ permalink raw reply
* [PATCH] powerpc: dts: 52xx: drop critical IRQ from dts files
From: Wolfram Sang @ 2012-08-23 15:31 UTC (permalink / raw)
To: linuxppc-dev; +Cc: John Bonesio, Anatolij Gustschin, Wolfram Sang
The wakeup-gpios have been assigned a critical IRQ in current
devicetrees. The PIC driver does not support critical IRQs, though, which
leads to the following error when booting (a PCM030 in this case):
mpc52xx_irqhost_map: invalid irq: virq=16, l1=0, l2=3
irq: irq-16==>hwirq-0x3 mapping failed: -22
[WARNing skipped]
Remove these entries until they are supported, if ever.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: John Bonesio <bones@secretlab.ca>
Cc: Anatolij Gustschin <agust@denx.de>
---
arch/powerpc/boot/dts/lite5200.dts | 2 +-
arch/powerpc/boot/dts/mpc5200b.dtsi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 179a178..25adace 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -141,7 +141,7 @@
gpio@c00 {
compatible = "fsl,mpc5200-gpio-wkup";
reg = <0xc00 0x40>;
- interrupts = <1 8 0 0 3 0>;
+ interrupts = <1 8 0>;
gpio-controller;
#gpio-cells = <2>;
};
diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi
index 7ab286a..e610d68 100644
--- a/arch/powerpc/boot/dts/mpc5200b.dtsi
+++ b/arch/powerpc/boot/dts/mpc5200b.dtsi
@@ -141,7 +141,7 @@
gpio_wkup: gpio@c00 {
compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
reg = <0xc00 0x40>;
- interrupts = <1 8 0 0 3 0>;
+ interrupts = <1 8 0>;
gpio-controller;
#gpio-cells = <2>;
};
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Oleg Nesterov @ 2012-08-23 9:02 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Srikar Dronamraju, peterz, lkml, Paul Mackerras, Anton Blanchard,
Ingo Molnar, ppcdev
In-Reply-To: <1345716378.29170.4.camel@pasglop>
On 08/23, Benjamin Herrenschmidt wrote:
>
> On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> > >
> >
> > insn is updated/accessed in the arch independent code. Size of
> > uprobe_opcode_t could be different for different archs.
> > uprobe_opcode_t
> > represents the size of the smallest breakpoint instruction for an
> > arch.
> >
> > Hence u8 works out the best. I know we could still use uprobe_opcode_t
> > and achieve the same. In which case, we would have to interpret
> > MAX_UINSN_BYTES differently. Do you see any advantages of using
> > uprobe_opcode_t instead of u8 across archs?
>
> But don't you actively rely on the fact that on powerpc, unlike x86, you
> -can- atomically replace an instruction with a single 32-bit store ?
I must have missed something...
But powerpc does not replace an instruction, the arch independent code
does this and it assumes that uprobe->arch.insn is u8[MAX_UINSN_BYTES].
Perhaps you meant that on powerpc it is "safe" to replace the insn
even if this can race with some CPU executing this code? But uprobes
has to replace the original page anyway, we should not write to
->vm_file.
I agree that memcpy() in arch_uprobe_analyze_insn() and
arch_uprobe_skip_sstep() looks a bit strange. May be powerpc can do
struct arch_uprobe {
union {
u8 insn[MAX_UINSN_BYTES];
u32 ainsn;
};
};
and use auprobe->ainsn directly, I dunno.
But probably I misunderstood you.
Oleg.
^ permalink raw reply
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Benjamin Herrenschmidt @ 2012-08-23 10:06 UTC (permalink / raw)
To: Srikar Dronamraju
Cc: peterz, lkml, oleg, Paul Mackerras, Anton Blanchard, Ingo Molnar,
ppcdev
In-Reply-To: <20120823053234.GE25338@linux.vnet.ibm.com>
On Thu, 2012-08-23 at 11:02 +0530, Srikar Dronamraju wrote:
> >
>
> insn is updated/accessed in the arch independent code. Size of
> uprobe_opcode_t could be different for different archs.
> uprobe_opcode_t
> represents the size of the smallest breakpoint instruction for an
> arch.
>
> Hence u8 works out the best. I know we could still use uprobe_opcode_t
> and achieve the same. In which case, we would have to interpret
> MAX_UINSN_BYTES differently. Do you see any advantages of using
> uprobe_opcode_t instead of u8 across archs?
But don't you actively rely on the fact that on powerpc, unlike x86, you
-can- atomically replace an instruction with a single 32-bit store ?
If you don't you should consider it, and that makes defining this as a
u8 array non-sensical (as is using memcpy)
Ben.
^ permalink raw reply
* [PATCH V9] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Jia Hongtao @ 2012-08-23 9:31 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: B07421, b38951
We unified the Freescale pci/pcie initialization by changing the fsl_pci
to a platform driver. In previous PCI code architecture the initialization
routine is called at board_setup_arch stage. Now the initialization is done
in probe function which is architectural better. Also It's convenient for
adding PM support for PCI controller in later patch.
Now we registered pci controllers as platform devices. So we combine two
initialization code as one platform driver.
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
---
Changes for V9:
* Add of_device_is_available() for primary determination.
* Add i8259 check for MPC85xx_CDS primary determination.
* The maintainer of STx GP3-SSA MPC8555 board could not be contacted.
So we do not add i8259 check for it.
arch/powerpc/platforms/85xx/common.c | 10 +++
arch/powerpc/platforms/85xx/corenet_ds.c | 34 ++--------
arch/powerpc/platforms/85xx/ge_imp3a.c | 62 ++++++-----------
arch/powerpc/platforms/85xx/mpc8536_ds.c | 36 +---------
arch/powerpc/platforms/85xx/mpc85xx_ads.c | 11 +--
arch/powerpc/platforms/85xx/mpc85xx_cds.c | 44 +++++++++----
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 14 ++--
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 40 ++---------
arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 30 +++-----
arch/powerpc/platforms/85xx/p1010rdb.c | 14 +---
arch/powerpc/platforms/85xx/p1022_ds.c | 36 +---------
arch/powerpc/platforms/85xx/p1022_rdk.c | 36 +---------
arch/powerpc/platforms/85xx/p1023_rds.c | 9 +--
arch/powerpc/platforms/85xx/p2041_rdb.c | 2 +-
arch/powerpc/platforms/85xx/p3041_ds.c | 2 +-
arch/powerpc/platforms/85xx/p4080_ds.c | 2 +-
arch/powerpc/platforms/85xx/p5020_ds.c | 2 +-
arch/powerpc/platforms/85xx/p5040_ds.c | 2 +-
arch/powerpc/platforms/85xx/qemu_e500.c | 4 +-
arch/powerpc/platforms/85xx/sbc8548.c | 21 +-----
arch/powerpc/platforms/85xx/socrates.c | 11 +---
arch/powerpc/platforms/85xx/stx_gp3.c | 13 +---
arch/powerpc/platforms/85xx/tqm85xx.c | 21 +-----
arch/powerpc/platforms/85xx/xes_mpc85xx.c | 56 ++-------------
arch/powerpc/platforms/86xx/gef_ppc9a.c | 12 +--
arch/powerpc/platforms/86xx/gef_sbc310.c | 13 +---
arch/powerpc/platforms/86xx/gef_sbc610.c | 12 +--
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 21 ++----
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 42 ++----------
arch/powerpc/platforms/86xx/sbc8641d.c | 14 +---
arch/powerpc/sysdev/fsl_pci.c | 102 +++++++++++++++++-----------
arch/powerpc/sysdev/fsl_pci.h | 15 +++-
drivers/edac/mpc85xx_edac.c | 43 +++---------
33 files changed, 249 insertions(+), 537 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 67dac22..d0861a0 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -27,6 +27,16 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
{ .compatible = "fsl,mpc8548-guts", },
/* Probably unnecessary? */
{ .compatible = "gpio-leds", },
+ /* For all PCI controllers */
+ { .compatible = "fsl,mpc8540-pci", },
+ { .compatible = "fsl,mpc8548-pcie", },
+ { .compatible = "fsl,p1022-pcie", },
+ { .compatible = "fsl,p1010-pcie", },
+ { .compatible = "fsl,p1023-pcie", },
+ { .compatible = "fsl,p4080-pcie", },
+ { .compatible = "fsl,qoriq-pcie-v2.4", },
+ { .compatible = "fsl,qoriq-pcie-v2.3", },
+ { .compatible = "fsl,qoriq-pcie-v2.2", },
{},
};
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 473d573..ed69c92 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -16,7 +16,6 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/memblock.h>
#include <asm/time.h>
#include <asm/machdep.h>
@@ -52,39 +51,16 @@ void __init corenet_ds_pic_init(void)
*/
void __init corenet_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
mpc85xx_smp_init();
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
- of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2") ||
- of_device_is_compatible(np, "fsl,qoriq-pcie-v2.3") ||
- of_device_is_compatible(np, "fsl,qoriq-pcie-v2.4")) {
- fsl_add_bridge(np, 0);
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PCI) && defined(CONFIG_PPC64)
pci_devs_phb_init();
#endif
-#endif
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
+
pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
}
diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c
index b6a728b..e6285ae 100644
--- a/arch/powerpc/platforms/85xx/ge_imp3a.c
+++ b/arch/powerpc/platforms/85xx/ge_imp3a.c
@@ -22,7 +22,6 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/time.h>
#include <asm/machdep.h>
@@ -84,53 +83,39 @@ void __init ge_imp3a_pic_init(void)
of_node_put(cascade_node);
}
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif /* CONFIG_PCI */
-
-/*
- * Setup the architecture
- */
-static void __init ge_imp3a_setup_arch(void)
+static void ge_imp3a_pci_assign_primary(void)
{
- struct device_node *regs;
#ifdef CONFIG_PCI
struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
+ struct resource rsrc;
- if (ppc_md.progress)
- ppc_md.progress("ge_imp3a_setup_arch()", 0);
-
-#ifdef CONFIG_PCI
for_each_node_by_type(np, "pci") {
if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
of_device_is_compatible(np, "fsl,p2020-pcie")) {
- struct resource rsrc;
of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
+ if ((rsrc.start & 0xfffff) == 0x9000)
+ fsl_pci_primary = np;
}
}
#endif
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init ge_imp3a_setup_arch(void)
+{
+ struct device_node *regs;
+
+ if (ppc_md.progress)
+ ppc_md.progress("ge_imp3a_setup_arch()", 0);
mpc85xx_smp_init();
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ ge_imp3a_pci_assign_primary();
+
+ swiotlb_detect_4g();
/* Remap basic board registers */
regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs");
@@ -215,17 +200,10 @@ static int __init ge_imp3a_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "ge,IMP3A")) {
-#ifdef CONFIG_PCI
- primary_phb_addr = 0x9000;
-#endif
- return 1;
- }
-
- return 0;
+ return of_flat_dt_is_compatible(root, "ge,IMP3A");
}
-machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices);
+machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index 767c7cf..15ce4b5 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -17,7 +17,6 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/time.h>
#include <asm/machdep.h>
@@ -46,46 +45,17 @@ void __init mpc8536_ds_pic_init(void)
*/
static void __init mpc8536_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc8536_ds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-
-#endif
+ fsl_pci_assign_primary();
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ swiotlb_detect_4g();
printk("MPC8536 DS board from Freescale Semiconductor\n");
}
-machine_device_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 29ee8fc..7d12a19 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -137,10 +137,6 @@ static void __init init_ioports(void)
static void __init mpc85xx_ads_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
@@ -150,11 +146,10 @@ static void __init mpc85xx_ads_setup_arch(void)
#endif
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
+
+ fsl_pci_assign_primary();
}
static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -173,7 +168,7 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
-machine_device_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 11156fb..dc02d60 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -276,6 +276,33 @@ machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
#endif /* CONFIG_PPC_I8259 */
+static void mpc85xx_cds_pci_assign_primary(void)
+{
+#ifdef CONFIG_PCI
+ struct device_node *np;
+
+ if (fsl_pci_primary)
+ return;
+
+ /*
+ * MPC85xx_CDS has ISA bridge but unfortunately there is no
+ * isa node in device tree. We now looking for i8259 node as
+ * a temporary workaround for such a broken device tree.
+ * This can go away once the device tree is updated.
+ */
+ np = of_find_node_by_name(NULL, "i8259");
+ while ((fsl_pci_primary = of_get_parent(np))) {
+ of_node_put(np);
+ np = fsl_pci_primary;
+
+ if ((of_device_is_compatible(np, "fsl,mpc8540-pci") ||
+ of_device_is_compatible(np, "fsl,mpc8548-pcie")) &&
+ of_device_is_available(np))
+ return;
+ }
+#endif
+}
+
/*
* Setup the architecture
*/
@@ -309,21 +336,12 @@ static void __init mpc85xx_cds_setup_arch(void)
}
#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-
ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
+
+ mpc85xx_cds_pci_assign_primary();
+ fsl_pci_assign_primary();
}
static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -355,7 +373,7 @@ static int __init mpc85xx_cds_probe(void)
return of_flat_dt_is_compatible(root, "MPC85xxCDS");
}
-machine_device_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
define_machine(mpc85xx_cds) {
.name = "MPC85xx CDS",
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 56f8c8f..9ebb91e 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -20,7 +20,6 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/time.h>
#include <asm/machdep.h>
@@ -129,13 +128,11 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
}
#endif /* CONFIG_PCI */
-static void __init mpc85xx_ds_pci_init(void)
+static void __init mpc85xx_ds_uli_init(void)
{
#ifdef CONFIG_PCI
struct device_node *node;
- fsl_pci_init();
-
/* See if we have a ULI under the primary */
node = of_find_node_by_name(NULL, "uli1575");
@@ -160,7 +157,8 @@ static void __init mpc85xx_ds_setup_arch(void)
ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
swiotlb_detect_4g();
- mpc85xx_ds_pci_init();
+ fsl_pci_assign_primary();
+ mpc85xx_ds_uli_init();
mpc85xx_smp_init();
printk("MPC85xx DS board from Freescale Semiconductor\n");
@@ -176,9 +174,9 @@ static int __init mpc8544_ds_probe(void)
return !!of_flat_dt_is_compatible(root, "MPC8544DS");
}
-machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 8e4b094..8498f73 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -327,44 +327,16 @@ static void __init mpc85xx_mds_qeic_init(void) { }
static void __init mpc85xx_mds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct pci_controller *hose;
- struct device_node *np;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
- }
-#endif
-
mpc85xx_smp_init();
mpc85xx_mds_qe_init();
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
}
@@ -409,9 +381,9 @@ static int __init mpc85xx_publish_devices(void)
return mpc85xx_common_publish_devices();
}
-machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
-machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
-machine_device_initcall(p1021_mds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8568_mds, mpc85xx_publish_devices);
+machine_arch_initcall(mpc8569_mds, mpc85xx_publish_devices);
+machine_arch_initcall(p1021_mds, mpc85xx_common_publish_devices);
machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 1910fdc..ede8771 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -86,23 +86,17 @@ void __init mpc85xx_rdb_pic_init(void)
*/
static void __init mpc85xx_rdb_setup_arch(void)
{
-#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
+#ifdef CONFIG_QUICC_ENGINE
struct device_node *np;
#endif
if (ppc_md.progress)
ppc_md.progress("mpc85xx_rdb_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8548-pcie"))
- fsl_add_bridge(np, 0);
- }
-
-#endif
-
mpc85xx_smp_init();
+ fsl_pci_assign_primary();
+
#ifdef CONFIG_QUICC_ENGINE
np = of_find_compatible_node(NULL, NULL, "fsl,qe");
if (!np) {
@@ -161,15 +155,15 @@ qe_fail:
printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
}
-machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1024_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1025_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1024_rdb, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index dbaf443..0252961 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -46,25 +46,15 @@ void __init p1010_rdb_pic_init(void)
*/
static void __init p1010_rdb_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("p1010_rdb_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,p1010-pcie"))
- fsl_add_bridge(np, 0);
- }
-
-#endif
+ fsl_pci_assign_primary();
printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
}
-machine_device_initcall(p1010_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1010_rdb, mpc85xx_common_publish_devices);
machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
/*
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 3c732ac..848a3e9 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -18,7 +18,6 @@
#include <linux/pci.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/div64.h>
#include <asm/mpic.h>
#include <asm/swiotlb.h>
@@ -507,32 +506,9 @@ early_param("video", early_video_setup);
*/
static void __init p1022_ds_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("p1022_ds_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
- struct resource rsrc;
- struct pci_controller *hose;
-
- of_address_to_resource(np, 0, &rsrc);
-
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
-#endif
-
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
diu_ops.get_pixel_format = p1022ds_get_pixel_format;
diu_ops.set_gamma_table = p1022ds_set_gamma_table;
@@ -601,18 +577,14 @@ static void __init p1022_ds_setup_arch(void)
mpc85xx_smp_init();
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
pr_info("Freescale P1022 DS reference board\n");
}
-machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index b3cf11b..55ffa1c 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -14,7 +14,6 @@
#include <linux/pci.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/div64.h>
#include <asm/mpic.h>
#include <asm/swiotlb.h>
@@ -121,32 +120,9 @@ void __init p1022_rdk_pic_init(void)
*/
static void __init p1022_rdk_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("p1022_rdk_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
- struct resource rsrc;
- struct pci_controller *hose;
-
- of_address_to_resource(np, 0, &rsrc);
-
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
-
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
-#endif
-
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
diu_ops.set_monitor_port = p1022rdk_set_monitor_port;
diu_ops.set_pixel_clock = p1022rdk_set_pixel_clock;
@@ -155,18 +131,14 @@ static void __init p1022_rdk_setup_arch(void)
mpc85xx_smp_init();
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
pr_info("Freescale / iVeia P1022 RDK reference board\n");
}
-machine_device_initcall(p1022_rdk, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices);
machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
index 2990e8b..9cc60a7 100644
--- a/arch/powerpc/platforms/85xx/p1023_rds.c
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -80,15 +80,12 @@ static void __init mpc85xx_rds_setup_arch(void)
}
}
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
- fsl_add_bridge(np, 0);
-#endif
-
mpc85xx_smp_init();
+
+ fsl_pci_assign_primary();
}
-machine_device_initcall(p1023_rds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1023_rds, mpc85xx_common_publish_devices);
static void __init mpc85xx_rds_pic_init(void)
{
diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c
index 6541fa2..000c089 100644
--- a/arch/powerpc/platforms/85xx/p2041_rdb.c
+++ b/arch/powerpc/platforms/85xx/p2041_rdb.c
@@ -80,7 +80,7 @@ define_machine(p2041_rdb) {
.power_save = e500_idle,
};
-machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
+machine_arch_initcall(p2041_rdb, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
index f238efa..b3edc20 100644
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -82,7 +82,7 @@ define_machine(p3041_ds) {
.power_save = e500_idle,
};
-machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p3041_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
index c92417d..54df106 100644
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ b/arch/powerpc/platforms/85xx/p4080_ds.c
@@ -81,7 +81,7 @@ define_machine(p4080_ds) {
.power_save = e500_idle,
};
-machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p4080_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
index 17bef15..753a42c 100644
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -91,7 +91,7 @@ define_machine(p5020_ds) {
#endif
};
-machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p5020_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p5040_ds.c b/arch/powerpc/platforms/85xx/p5040_ds.c
index 8e22a34..1138185 100644
--- a/arch/powerpc/platforms/85xx/p5040_ds.c
+++ b/arch/powerpc/platforms/85xx/p5040_ds.c
@@ -82,7 +82,7 @@ define_machine(p5040_ds) {
#endif
};
-machine_device_initcall(p5040_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p5040_ds, corenet_ds_publish_devices);
#ifdef CONFIG_SWIOTLB
machine_arch_initcall(p5040_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c
index 3c5490c..f6ea561 100644
--- a/arch/powerpc/platforms/85xx/qemu_e500.c
+++ b/arch/powerpc/platforms/85xx/qemu_e500.c
@@ -41,7 +41,7 @@ static void __init qemu_e500_setup_arch(void)
{
ppc_md.progress("qemu_e500_setup_arch()", 0);
- fsl_pci_init();
+ fsl_pci_assign_primary();
swiotlb_detect_4g();
mpc85xx_smp_init();
}
@@ -56,7 +56,7 @@ static int __init qemu_e500_probe(void)
return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500");
}
-machine_device_initcall(qemu_e500, mpc85xx_common_publish_devices);
+machine_arch_initcall(qemu_e500, mpc85xx_common_publish_devices);
define_machine(qemu_e500) {
.name = "QEMU e500",
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index cd3a66b..f621218 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -88,26 +88,11 @@ static int __init sbc8548_hw_rev(void)
*/
static void __init sbc8548_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("sbc8548_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
+ fsl_pci_assign_primary();
+
sbc_rev = sbc8548_hw_rev();
}
@@ -128,7 +113,7 @@ static void sbc8548_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
-machine_device_initcall(sbc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index b9c6daa..ae368e0 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -66,20 +66,13 @@ static void __init socrates_pic_init(void)
*/
static void __init socrates_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("socrates_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-#endif
+ fsl_pci_assign_primary();
}
-machine_device_initcall(socrates, mpc85xx_common_publish_devices);
+machine_arch_initcall(socrates, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index e050800..6f4939b 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -60,21 +60,14 @@ static void __init stx_gp3_pic_init(void)
*/
static void __init stx_gp3_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("stx_gp3_setup_arch()", 0);
+ fsl_pci_assign_primary();
+
#ifdef CONFIG_CPM2
cpm2_reset();
#endif
-
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
- fsl_add_bridge(np, 1);
-#endif
}
static void stx_gp3_show_cpuinfo(struct seq_file *m)
@@ -93,7 +86,7 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m)
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
}
-machine_device_initcall(stx_gp3, mpc85xx_common_publish_devices);
+machine_arch_initcall(stx_gp3, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 4d786c2..942870f 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -59,10 +59,6 @@ static void __init tqm85xx_pic_init(void)
*/
static void __init tqm85xx_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("tqm85xx_setup_arch()", 0);
@@ -70,20 +66,7 @@ static void __init tqm85xx_setup_arch(void)
cpm2_reset();
#endif
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- if (!of_address_to_resource(np, 0, &rsrc)) {
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
- }
-#endif
+ fsl_pci_assign_primary();
}
static void tqm85xx_show_cpuinfo(struct seq_file *m)
@@ -123,7 +106,7 @@ static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520,
tqm85xx_ti1520_fixup);
-machine_device_initcall(tqm85xx, mpc85xx_common_publish_devices);
+machine_arch_initcall(tqm85xx, mpc85xx_common_publish_devices);
static const char *board[] __initdata = {
"tqc,tqm8540",
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 41c6875..dcbf7e4 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -111,18 +111,11 @@ static void xes_mpc85xx_fixups(void)
}
}
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
/*
* Setup the architecture
*/
static void __init xes_mpc85xx_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
struct device_node *root;
const char *model = "Unknown";
@@ -137,26 +130,14 @@ static void __init xes_mpc85xx_setup_arch(void)
xes_mpc85xx_fixups();
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
- of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == primary_phb_addr)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
-
mpc85xx_smp_init();
+
+ fsl_pci_assign_primary();
}
-machine_device_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
/*
* Called very early, device-tree isn't unflattened
@@ -165,42 +146,21 @@ static int __init xes_mpc8572_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "xes,MPC8572")) {
-#ifdef CONFIG_PCI
- primary_phb_addr = 0x8000;
-#endif
- return 1;
- } else {
- return 0;
- }
+ return of_flat_dt_is_compatible(root, "xes,MPC8572");
}
static int __init xes_mpc8548_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "xes,MPC8548")) {
-#ifdef CONFIG_PCI
- primary_phb_addr = 0xb000;
-#endif
- return 1;
- } else {
- return 0;
- }
+ return of_flat_dt_is_compatible(root, "xes,MPC8548");
}
static int __init xes_mpc8540_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "xes,MPC8540")) {
-#ifdef CONFIG_PCI
- primary_phb_addr = 0xb000;
-#endif
- return 1;
- } else {
- return 0;
- }
+ return of_flat_dt_is_compatible(root, "xes,MPC8540");
}
define_machine(xes_mpc8572) {
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index 1fca663..58d753f 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -73,13 +73,6 @@ static void __init gef_ppc9a_init_irq(void)
static void __init gef_ppc9a_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
printk(KERN_INFO "GE Intelligent Platforms PPC9A 6U VME SBC\n");
@@ -87,6 +80,8 @@ static void __init gef_ppc9a_setup_arch(void)
mpc86xx_smp_init();
#endif
+ fsl_pci_assign_primary();
+
/* Remap basic board registers */
regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
if (regs) {
@@ -221,6 +216,7 @@ static long __init mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -231,7 +227,7 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
+machine_arch_initcall(gef_ppc9a, declare_of_platform_devices);
define_machine(gef_ppc9a) {
.name = "GE PPC9A",
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index 14e0e576..67aaa81 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -73,20 +73,14 @@ static void __init gef_sbc310_init_irq(void)
static void __init gef_sbc310_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
-
printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n");
#ifdef CONFIG_SMP
mpc86xx_smp_init();
#endif
+ fsl_pci_assign_primary();
+
/* Remap basic board registers */
regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
if (regs) {
@@ -209,6 +203,7 @@ static long __init mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -219,7 +214,7 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(gef_sbc310, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc310, declare_of_platform_devices);
define_machine(gef_sbc310) {
.name = "GE SBC310",
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index 1638f43..7666273 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -73,13 +73,6 @@ static void __init gef_sbc610_init_irq(void)
static void __init gef_sbc610_setup_arch(void)
{
struct device_node *regs;
-#ifdef CONFIG_PCI
- struct device_node *np;
-
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- fsl_add_bridge(np, 1);
- }
-#endif
printk(KERN_INFO "GE Intelligent Platforms SBC610 6U VPX SBC\n");
@@ -87,6 +80,8 @@ static void __init gef_sbc610_setup_arch(void)
mpc86xx_smp_init();
#endif
+ fsl_pci_assign_primary();
+
/* Remap basic board registers */
regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
if (regs) {
@@ -198,6 +193,7 @@ static long __init mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -208,7 +204,7 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(gef_sbc610, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc610, declare_of_platform_devices);
define_machine(gef_sbc610) {
.name = "GE SBC610",
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 62cd3c5..a817398 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -91,6 +91,9 @@ static struct of_device_id __initdata mpc8610_ids[] = {
{ .compatible = "simple-bus", },
/* So that the DMA channel nodes can be probed individually: */
{ .compatible = "fsl,eloplus-dma", },
+ /* PCI controllers */
+ { .compatible = "fsl,mpc8610-pci", },
+ { .compatible = "fsl,mpc8641-pcie", },
{}
};
@@ -107,7 +110,7 @@ static int __init mpc8610_declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
@@ -278,25 +281,13 @@ mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
static void __init mpc86xx_hpcd_setup_arch(void)
{
struct resource r;
- struct device_node *np;
unsigned char *pixis;
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8610-pci")
- || of_device_is_compatible(np, "fsl,mpc8641-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0xa000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
- }
-#endif
+ fsl_pci_assign_primary();
+
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
diu_ops.get_pixel_format = mpc8610hpcd_get_pixel_format;
diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 817245b..e8bf3fa 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -19,7 +19,6 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/of_platform.h>
-#include <linux/memblock.h>
#include <asm/time.h>
#include <asm/machdep.h>
@@ -51,15 +50,8 @@ extern int uli_exclude_device(struct pci_controller *hose,
static int mpc86xx_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn)
{
- struct device_node* node;
- struct resource rsrc;
-
- node = hose->dn;
- of_address_to_resource(node, 0, &rsrc);
-
- if ((rsrc.start & 0xfffff) == 0x8000) {
+ if (hose->dn == fsl_pci_primary)
return uli_exclude_device(hose, bus, devfn);
- }
return PCIBIOS_SUCCESSFUL;
}
@@ -69,30 +61,11 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
static void __init
mpc86xx_hpcn_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
- struct pci_controller *hose;
-#endif
- dma_addr_t max = 0xffffffff;
-
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- hose = pci_find_hose_for_OF_device(np);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
-
ppc_md.pci_exclude_device = mpc86xx_exclude_device;
-
#endif
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
@@ -101,13 +74,9 @@ mpc86xx_hpcn_setup_arch(void)
mpc86xx_smp_init();
#endif
-#ifdef CONFIG_SWIOTLB
- if ((memblock_end_of_DRAM() - 1) > max) {
- ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_dma_ops);
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
- }
-#endif
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
}
@@ -162,6 +131,7 @@ static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "fsl,srio", },
{ .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -171,7 +141,7 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcn, declare_of_platform_devices);
machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
define_machine(mpc86xx_hpcn) {
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index e7007d0..b47a8fd 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -38,23 +38,16 @@
static void __init
sbc8641_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("sbc8641_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
- fsl_add_bridge(np, 0);
-#endif
-
printk("SBC8641 board from Wind River\n");
#ifdef CONFIG_SMP
mpc86xx_smp_init();
#endif
+
+ fsl_pci_assign_primary();
}
@@ -102,6 +95,7 @@ mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -111,7 +105,7 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(sbc8641, declare_of_platform_devices);
+machine_arch_initcall(sbc8641, declare_of_platform_devices);
define_machine(sbc8641) {
.name = "SBC8641D",
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index da7a3d7..e577cb5 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -826,54 +826,78 @@ static const struct of_device_id pci_ids[] = {
struct device_node *fsl_pci_primary;
-void __devinit fsl_pci_init(void)
+void fsl_pci_assign_primary(void)
{
- int ret;
- struct device_node *node;
- struct pci_controller *hose;
- dma_addr_t max = 0xffffffff;
+ struct device_node *np;
/* Callers can specify the primary bus using other means. */
- if (!fsl_pci_primary) {
- /* If a PCI host bridge contains an ISA node, it's primary. */
- node = of_find_node_by_type(NULL, "isa");
- while ((fsl_pci_primary = of_get_parent(node))) {
- of_node_put(node);
- node = fsl_pci_primary;
-
- if (of_match_node(pci_ids, node))
- break;
- }
+ if (fsl_pci_primary)
+ return;
+
+ /* If a PCI host bridge contains an ISA node, it's primary. */
+ np = of_find_node_by_type(NULL, "isa");
+ while ((fsl_pci_primary = of_get_parent(np))) {
+ of_node_put(np);
+ np = fsl_pci_primary;
+
+ if (of_match_node(pci_ids, np) && of_device_is_available(np))
+ return;
}
- node = NULL;
- for_each_node_by_type(node, "pci") {
- if (of_match_node(pci_ids, node)) {
- /*
- * If there's no PCI host bridge with ISA, arbitrarily
- * designate one as primary. This can go away once
- * various bugs with primary-less systems are fixed.
- */
- if (!fsl_pci_primary)
- fsl_pci_primary = node;
-
- ret = fsl_add_bridge(node, fsl_pci_primary == node);
- if (ret == 0) {
- hose = pci_find_hose_for_OF_device(node);
- max = min(max, hose->dma_window_base_cur +
- hose->dma_window_size);
- }
+ /*
+ * If there's no PCI host bridge with ISA, arbitrarily
+ * designate one as primary. This can go away once
+ * various bugs with primary-less systems are fixed.
+ */
+ for_each_matching_node(np, pci_ids) {
+ if (of_device_is_available(np)) {
+ fsl_pci_primary = np;
+ of_node_put(np);
+ return;
}
}
+}
+
+static int __devinit fsl_pci_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct device_node *node;
+ struct pci_controller *hose;
+
+ node = pdev->dev.of_node;
+ ret = fsl_add_bridge(node, fsl_pci_primary == node);
#ifdef CONFIG_SWIOTLB
- /*
- * if we couldn't map all of DRAM via the dma windows
- * we need SWIOTLB to handle buffers located outside of
- * dma capable memory region
- */
- if (memblock_end_of_DRAM() - 1 > max)
- ppc_swiotlb_enable = 1;
+ if (ret == 0) {
+ hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+
+ /*
+ * if we couldn't map all of DRAM via the dma windows
+ * we need SWIOTLB to handle buffers located outside of
+ * dma capable memory region
+ */
+ if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
+ hose->dma_window_size)
+ ppc_swiotlb_enable = 1;
+ }
#endif
+
+ mpc85xx_pci_err_probe(pdev);
+
+ return 0;
+}
+
+static struct platform_driver fsl_pci_driver = {
+ .driver = {
+ .name = "fsl-pci",
+ .of_match_table = pci_ids,
+ },
+ .probe = fsl_pci_probe,
+};
+
+static int __init fsl_pci_init(void)
+{
+ return platform_driver_register(&fsl_pci_driver);
}
+arch_initcall(fsl_pci_init);
#endif
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index baa0fd1..d5aa1d9 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -95,10 +95,19 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose);
extern struct device_node *fsl_pci_primary;
-#ifdef CONFIG_FSL_PCI
-void fsl_pci_init(void);
+#ifdef CONFIG_PCI
+void fsl_pci_assign_primary(void);
#else
-static inline void fsl_pci_init(void) {}
+static inline void fsl_pci_assign_primary(void) {}
+#endif
+
+#ifdef CONFIG_EDAC_MPC85XX
+int mpc85xx_pci_err_probe(struct platform_device *op);
+#else
+static inline int mpc85xx_pci_err_probe(struct platform_device *op)
+{
+ return -ENOTSUPP;
+}
#endif
#endif /* __POWERPC_FSL_PCI_H */
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 0e37462..e4b6113 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
{
struct edac_pci_ctl_info *pci;
struct mpc85xx_pci_pdata *pdata;
@@ -214,6 +214,16 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
if (!pci)
return -ENOMEM;
+ /* make sure error reporting method is sane */
+ switch (edac_op_state) {
+ case EDAC_OPSTATE_POLL:
+ case EDAC_OPSTATE_INT:
+ break;
+ default:
+ edac_op_state = EDAC_OPSTATE_INT;
+ break;
+ }
+
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
@@ -303,6 +313,7 @@ err:
devres_release_group(&op->dev, mpc85xx_pci_err_probe);
return res;
}
+EXPORT_SYMBOL(mpc85xx_pci_err_probe);
static int mpc85xx_pci_err_remove(struct platform_device *op)
{
@@ -326,27 +337,6 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
return 0;
}
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
- {
- .compatible = "fsl,mpc8540-pcix",
- },
- {
- .compatible = "fsl,mpc8540-pci",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
-
-static struct platform_driver mpc85xx_pci_err_driver = {
- .probe = mpc85xx_pci_err_probe,
- .remove = __devexit_p(mpc85xx_pci_err_remove),
- .driver = {
- .name = "mpc85xx_pci_err",
- .owner = THIS_MODULE,
- .of_match_table = mpc85xx_pci_err_of_match,
- },
-};
-
#endif /* CONFIG_PCI */
/**************************** L2 Err device ***************************/
@@ -1193,12 +1183,6 @@ static int __init mpc85xx_mc_init(void)
if (res)
printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
-#ifdef CONFIG_PCI
- res = platform_driver_register(&mpc85xx_pci_err_driver);
- if (res)
- printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
-#endif
-
#ifdef CONFIG_FSL_SOC_BOOKE
pvr = mfspr(SPRN_PVR);
@@ -1235,9 +1219,6 @@ static void __exit mpc85xx_mc_exit(void)
on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
}
#endif
-#ifdef CONFIG_PCI
- platform_driver_unregister(&mpc85xx_pci_err_driver);
-#endif
platform_driver_unregister(&mpc85xx_l2_err_driver);
platform_driver_unregister(&mpc85xx_mc_err_driver);
}
--
1.7.5.1
^ permalink raw reply related
* Re: [PATCH 1/2] PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too
From: Olof Johansson @ 2012-08-23 7:28 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Jacob Pan, linux-pci, linux-kernel, Jesse Barnes, Ivan Kokshaysky,
Matthew Wilcox, Greg Kroah-Hartman, linuxppc-dev, Robert Hancock
In-Reply-To: <20120709182018.18165.98339.stgit@bhelgaas.mtv.corp.google.com>
Hi,
On Mon, Jul 9, 2012 at 11:20 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> After 253d2e5498, we disable MEM and IO decoding for most devices while we
> size 32-bit BARs. However, we restore the original COMMAND register before
> we size the upper 32 bits of 64-bit BARs, so we can still cause a conflict.
>
> This patch waits to restore the original COMMAND register until we're
> completely finished sizing the BAR.
>
> Reference: https://lkml.org/lkml/2007/8/25/154
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This patch causes boot lockup on PA Semi hardware, since it disables
the bar on the UART that is used for console, and it has printks
between the old and the new re-enable location. If I boot with 'debug'
level for printk, I hit this. If I boot with just regular console
args, I don't.
I'm guessing any other platform that uses MMIO-based UART on PCI for
console will have similar issues. I can verify on Chrome OS x86
hardware tomorrow if legacy powerpc isn't important enough to care
about. :-)
I have no proposal for a fix for this. Can you please consider
reverting for 3.6 unless someone has a better idea?
-Olof
^ permalink raw reply
* [PATCH] powerpc: Fix null pointer deref in perf hardware breakpoints
From: Michael Neuling @ 2012-08-23 6:30 UTC (permalink / raw)
To: benh, linuxppc-dev
In-Reply-To: <1345620143-17289-3-git-send-email-mikey@neuling.org>
Currently if you are doing a global perf recording with hardware
breakpoints (ie perf record -e mem:0xdeadbeef -a), you can oops with:
Faulting instruction address: 0xc000000000738890
cpu 0xc: Vector: 300 (Data Access) at [c0000003f76af8d0]
pc: c000000000738890: .hw_breakpoint_handler+0xa0/0x1e0
lr: c000000000738830: .hw_breakpoint_handler+0x40/0x1e0
sp: c0000003f76afb50
msr: 8000000000001032
dar: 6f0
dsisr: 42000000
current = 0xc0000003f765ac00
paca = 0xc00000000f262a00 softe: 0 irq_happened: 0x01
pid = 6810, comm = loop-read
enter ? for help
[c0000003f76afbe0] c00000000073cd04 .notifier_call_chain.isra.0+0x84/0xe0
[c0000003f76afc80] c00000000073cdbc .notify_die+0x3c/0x60
[c0000003f76afd20] c0000000000139f0 .do_dabr+0x40/0xf0
[c0000003f76afe30] c000000000005a9c handle_dabr_fault+0x14/0x48
--- Exception: 300 (Data Access) at 0000000010000480
SP (ff8679e0) is in userspace
This is because we don't check to see if the break point is associated
with task before we deference the task_struct pointer.
This changes the update to use current.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
v2: mpe pointed out that we should be using current here so that once we
single step the next instruction, we know where to store the perf event.
Confirming this, the original patch didn't actually record any data when
we used -a even when we hit.
This new patch fixes this so that -a doesn't oops and records data too!
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index f3a82dd..956a4c4 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -253,7 +253,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
/* Do not emulate user-space instructions, instead single-step them */
if (user_mode(regs)) {
- bp->ctx->task->thread.last_hit_ubp = bp;
+ current->thread.last_hit_ubp = bp;
regs->msr |= MSR_SE;
goto out;
}
^ permalink raw reply related
* Re: [PATCH v4 2/2] powerpc: Uprobes port to powerpc
From: Ananth N Mavinakayanahalli @ 2012-08-23 5:58 UTC (permalink / raw)
To: Michael Ellerman
Cc: Srikar Dronamraju, peterz, lkml, oleg, Paul Mackerras,
Anton Blanchard, Ingo Molnar, ppcdev
In-Reply-To: <1345696100.3338.21.camel@concordia>
On Thu, Aug 23, 2012 at 02:28:20PM +1000, Michael Ellerman wrote:
> On Wed, 2012-08-22 at 13:57 +0530, Ananth N Mavinakayanahalli wrote:
> > From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
> >
> > This is the port of uprobes to powerpc. Usage is similar to x86.
>
> Hi Ananth,
>
> Excuse my ignorance of uprobes, some comments inline ...
Thanks for the review Michael!
> > [root@xxxx ~]# ./bin/perf probe -x /lib64/libc.so.6 malloc
> > Added new event:
> > probe_libc:malloc (on 0xb4860)
> >
> > You can now use it in all perf tools, such as:
> >
> > perf record -e probe_libc:malloc -aR sleep 1
>
> Is there a test suite for any of this?
We don't have a formal testsuite yet, but the usual way of testing it is
to run kernbench while registering/unregistering a bunch of probes
periodically.
...
> > + * 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 (C) IBM Corporation, 2007-2012
>
> The lawyers say we shouldn't use (C).
Will remove that.
> Is it really copyright IBM 2007-2012? Or is that because you copied
> another header?
The later. This is adapted from the x86 version.
> > +typedef unsigned int uprobe_opcode_t;
>
> I'd prefer u32.
OK. Will change.
> It would be nice if someone could consolidate this with kprobe_opcode_t.
Thats on the TODO after the uprobes code stabilizes further.
I am wondering which file would be appropriate? We could either
consolidate a bunch of these into asm/kdebug.h or asm/ptrace.h. Any
preference/suggestion?
> > +#define MAX_UINSN_BYTES 4
> > +#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
> > +
> > +#define UPROBE_SWBP_INSN 0x7fe00008
>
> This is just "trap" ?
Yes. But since its referred to in arch agnostic code too, we'd have to alias
it thus.
> > +#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */
> > +
> > +#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
> > +#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
> > +#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
> > +#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
> > +
> > +#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
> > + IS_TWI(instr) || IS_TDI(instr))
>
> These seem to be duplicated in kprobes.h, can we consolidate them.
Yes, similar to the opcode_t types above.
> > +struct arch_uprobe {
> > + u8 insn[MAX_UINSN_BYTES];
> > +};
>
> Why not uprobe_opcode_t insn ?
I had a similar discussion with Srikar while doing the port, but he has
reasons for this...
...
> > void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
> > {
> > + if (thread_info_flags & _TIF_UPROBE) {
> > + clear_thread_flag(TIF_UPROBE);
> > + uprobe_notify_resume(regs);
> > + }
>
> Presumably this ordering is crucial, ie. uprobes before signals.
Correct!
...
> > +#define UPROBE_TRAP_NR UINT_MAX
>
> In the comments below you talk about -1 a few times, but you actually
> mean UINT_MAX.
Correct. I will fix those references.
> > +/**
> > + * arch_uprobe_analyze_insn
>
> Analyze what about the instruction?
Depends on the architecture. On x86, we need to verify if the address is
at an instruction boundary, and if the instruction can be probed at all.
On powerpc, we have an easier time. We just validate the address is
aligned at instruction boundary and flag if the instruction at the
address is a trap variant.
> > + * @mm: the probed address space.
> > + * @arch_uprobe: the probepoint information.
> > + * @addr: vaddr to probe.
> > + * Return 0 on success or a -ve number on error.
> > + */
> > +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
> > +{
> > + unsigned int insn;
> > +
> > + if (addr & 0x03)
> > + return -EINVAL;
> > +
> > + memcpy(&insn, auprobe->insn, MAX_UINSN_BYTES);
>
> We shouldn't need to use memcpy, we know it's a u32.
OK. Right now, its u8 insn[4], so I did this to be 'correct'. But I
agree we can just do an assignment.
> > + if (is_trap(insn))
> > + return -ENOTSUPP;
>
> A comment saying why we can't handle this would be nice.
Will add.
> > + return 0;
> > +}
>
>
> I am probably missing something, but why do we need to execute out of
> line?
I think Srikar answered that.
...
> > +/* callback routine for handling exceptions. */
> > +int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data)
> > +{
> > + struct die_args *args = data;
> > + struct pt_regs *regs = args->regs;
> > +
> > + /* We are only interested in userspace traps */
> > + if (regs && !user_mode(regs))
> > + return NOTIFY_DONE;
>
> Do we ever get here with a NULL regs?
I don't think so. Its just a paranoid check. Do you prefer it to be
removed?
...
> > + * See if the instruction can be emulated.
> > + * Returns true if instruction was emulated, false otherwise.
> > + */
> > +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
> > +{
> > + int ret;
> > + unsigned int insn;
> > +
> > + memcpy(&insn, auprobe->insn, MAX_UINSN_BYTES);
>
> Why memcpy?
Same as above - u8 insn[4].
> > +
> > + /*
> > + * emulate_step() returns 1 if the insn was successfully emulated.
> > + * For all other cases, we need to single-step in hardware.
> > + */
> > + ret = emulate_step(regs, insn);
> > + if (ret > 0)
> > + return true;
>
> This actually emulates the instruction, ie. the contents of regs are
> changed based on the instruction.
>
> That seems to differ vs x86, where arch_uprobe_skip_sstep() just checks
> the instruction and returns true/false. Is that because on x86 they are
> only returning true for nops? ie. there is no emulation to be done?
>
> It's a little surprising that can_skip_sstep() actually emulates the
> instruction, but again that's not your fault.
We initially had a uprobe_emulate_step() callback which over many review
cycles has morphed into this.
Ananth
^ 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