* Re: [PATCH][RFC][POWERPC] i2c: adds support for i2c bus on 8xx
From: Segher Boessenkool @ 2007-04-20 8:57 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: Jean Delvare, linuxppc-dev@ozlabs.org, lkml
In-Reply-To: <20070420082714.4f10f186@localhost.localdomain>
> + compatible = "fsl-i2c-cpm";
"fsl,i2c-cpm" instead.
Segher
^ permalink raw reply
* Re: [PATCH] powerpc: save trap number in bad_stack
From: Segher Boessenkool @ 2007-04-20 8:51 UTC (permalink / raw)
To: michael; +Cc: Olof Johansson, linuxppc-dev, paulus, anton
In-Reply-To: <1177035524.6890.7.camel@concordia.ozlabs.ibm.com>
>>> + u64 trap_save; /* Used when bad stack is encountered */
>>
>> Can you put it elsewhere in the PACA (around less frequently used
>> bits) ? This is a pretty hot area of the PACA...
>
> It's only set in the bad_stack case though.
>
> You should put it after cpu_start, there's a bit hole there, and
> trap_save is readonly during normal operation, so it shouldn't be a
> performance hit.
That's not a performance hit compared to the current
state of the code, sure; but that "hot slot" could
be used for a hotter variable, instead.
Segher
^ permalink raw reply
* Re: [PATCH 7/7] MPIC MSI backend
From: Segher Boessenkool @ 2007-04-20 8:40 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-pci
In-Reply-To: <20070419073556.73A6BDDE4A@ozlabs.org>
> MPIC MSI backend. Based on code from Segher, heavily hacked by me.
I guess I'll have to do
Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
again, you keep losing it :-)
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Segher
^ permalink raw reply
* Re: [PATCH 1/4 v2] powerpc: document max-speed and interface-type properties
From: Segher Boessenkool @ 2007-04-20 8:34 UTC (permalink / raw)
To: Kim Phillips; +Cc: linuxppc-dev
In-Reply-To: <20070418164849.6f0fd817.kim.phillips@freescale.com>
>>> ..but I'm not interested in specifying what interfaces the PHY
>>> supports.
>>
>> But you *have* to. The device tree describes the hardware,
>> it is not a configuration file for Linux to use as it sees fit.
>
> not for the purposes of this patch; ucc_geth passes interface_type,
It doesn't matter what the Linux code does. The device tree
describes the hardware, it is not a configuration file for
Linux to use as it sees fit.
> a
> property of the board describing the connection between the MAC and PHY
> (not a list of what connection types the PHY is capable of) to the
> phylib, and the phylib is left to probe, identify, and configure the
> PHY
> appropriately.
Sure there's an argument for describing what type of
interface the PHY is connected on, if it supports more
than one -- but that should be a property in the PHY
node, not the controller node, since you can have multiple
PHYs connected to the same controller, possibly on
different interfaces each.
The m88e11x1 phylib code seems to ignore the "interface"
parameter completely btw.
>>>>> Again, max-speed is exclusively for configuring the UCC itself,
>>>>> regardless of the connection speed.
>>>>
>>>> If that is really true, and the value of that property
>>>> has nothing to do with the MAC<->PHY data channel, it should
>>>> have a different (not that generic) name.
>>>
>>> can you elaborate on why, including an example of what you'd think
>>> would
>>> be a better one?
>>
>> Very generic names should only be used by very generic bindings.
>
> it's intentionally generic; UCCs are Universal Communications
> Controllers and implement many communications protocols.
So? That doesn't put the UCC device binding on the same
level as, say, PCI or the base OF definition.
>> If a very specific device binding (like yours) uses a property
>> name like that, there is a high chance it will clash with a more
>> generic binding it uses (PCI, ethernet, network, ...) -- perhaps
>> with a *future* version of such a binding.
>>
> I'm sure future versions will be able to adjust accordingly :)
Do you really think that when future changes are made to
base OF, or the PCI binding, or similar, that people will
even stop to consider what you did in your (unofficial)
binding and try to stay compatible to it? Can I have
some of those pills?
>> Also, it isn't a great name /an sich/: "max-speed" -- maximum
>> speed of what?
>
> ? it's fine - it's in the context of a communications device.
> Can you come up with something better?
Sure. "ucc,max-speed" solves one problem; "max-comm-speed"
solves another. I'm sure there are better names possible,
so please find one. Giving good names to things is hard,
so good luck.
Segher
^ permalink raw reply
* Re: [PATCH] kexec-tools ppc64: add --reuseinitrd option
From: Milton Miller @ 2007-04-20 7:42 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, horms, kexec, Fastboot mailing list
In-Reply-To: <14852.1177053830@neuling.org>
On Apr 20, 2007, at 2:23 AM, Michael Neuling wrote:
> In message <46b0d1603ea2ab82b37daaa1888e8793@bga.com> you wrote:
>> On Apr 18, 2007, at 11:29 PM, Michael Neuling wrote:
>>> Add a --reuseinitrd option so that initrds saved using the
>>> retain_initrd kernel option can be reused on the kexec boot.
>>
>> Although this seems efficent to look at what was in the device tree,
>> I'd prefer we actually looked at /proc/cmdline when we parse the
>> arg, so that we are sure to find what the kernel is actually
>> using for the command line.
>>
>> Besides it will be eaiser for other archs to copy the check.
>
> Looks like we should make it a generic option. If we do, this should
> probably be two patches. One to introduce the option, and one for the
> ppc64 specific parts.
>
> Do any of the other architectures allow you to see where the initrd is
> located for the current boot from user space? If not, the option will
> need to take two parameters saying where the retained initrd is. This
> will make the option less generic (if not, we'll need to change the
> other archs to export these values to user space).
Since we just added the option to the kernel, I'm guessing not.
Most of them use /proc/iomem with resources for finding system ram,
the kernel text and crash kernel region, so they should probably
add a resource there when the initrd is retained. We (powerpc) export
our bootloader data aka device tree instead, and make kexec-tools
parse it. I don't know how sparc passes an initrd to the kernel.
>>> @@ -148,6 +154,9 @@ int elf_ppc64_load(int argc, char **argv
>>> else
>>> fprintf(stdout, "Warning: append= option is not passed. Using t
> he
>>> first kernel root partition\n");
>>>
>>> + if (ramdisk && reuse_initrd)
>>> + die("Can't specify --ramdisk or --initrd with --reuseinitrd\n")
> ;
>>> +
>>
>> This check is generic, not elf specific, so it should be where
>> we pass the args. Hmm, maybe this is that place and it just
>> wants abstracting, I don't have the tree in front of me.
>
> I put it here so the error's caught independent of the arg parsing
> order. Otherwise, we'd need to duplicate the check.
>
> I think it's the right place, unless we move it to an arch generic
> option.
I didn't mean as we parse the option, but is there not something
that gets called after we parse all the options? Maybe that is
just the load function. I was just thinking it should be in a
sanity_check_args() function that looks for exclusive options like
these rather than in "load a kernel like elf file", although that
is the only current option for ppc64, so it might be ok here.
milton
^ permalink raw reply
* [RFC][PATCH]Kprobes for PPC32(BOOKE)
From: rsmadhvesh @ 2007-04-20 7:24 UTC (permalink / raw)
To: galak; +Cc: linuxppc-dev, madhvesh.s
[-- Attachment #1: Type: text/plain, Size: 3673 bytes --]
Hi Kumar,
This is regarding the kprobes patches for
PPC32 BOOKE version. The attached patches
contain the implementation for this version.
I saw your earlier postings and commits to 2.6.21
regarding kprobes for PPC32. Since the single
step mechanism in BookE is quite different, I
thought i can share some of the issues faced
in this implementation and get your review
feedback for those patches.
Last month, i had posted the patches for
PPC32(BookE) version in the below thread.
http://ozlabs.org/pipermail/linuxppc-dev/2007-March/033058.html
Kernel Version:- 2.6.16.39
Target: Ebony (ppc440_gp processor)
I had mentioned some issues regarding the preempt count
in the above thread with some issues. In today released patches,
these issues are fixed with some additional patches to
head_booke.h and traps.c. With these changes, there are no
issues noticed and kprobes behavior is same as other
architetcures.
Regarding the below issue mentioned in my earlier mail...
> 2. It was noticed that having preempt_disable() at the beginning of
> kprobe_handler, generates OOPS and kprobes doesnot work. But this is
> against the original kprobes design implemented in other
> already working
> archs (that is, preemption is disabled for the entire
> duration of pre and post
> handlers execution). The basic problem noticed is, change in
> the preempt
> count after generating single step exception. Even though the
> preemption
> is disabled at the beginning of kprobe_handler(), after generating the
> single step exception, preempt count gets printed as zero in
> DebugException()
> handler of traps.c. This causes the problem and system
> generates OOPS!!
>
The core issue was the way debug exception was getting handled
in PPC32 BookE versions. The debug exception gets executed
using exception stack which doesnot contain the original stack
preempt count status. This exact sequence can be explained
as below
After executing pre handler, the DEBUG_EXCEPTION gets called
because of setting DE bit in MSR and IC, IDM bits of DBCR0.
As part of DEBUG_EXCEPTION in head_booke.h, the exception
stack is prepared by storing current registers and original sp. But the
current preempt count value is not set in exception stack. Because of
this, preempt_count=ZERO. This will enable preemption and at any point,
it can be rescheduled because of higher priority interrupts. Also as part
of post_kprobe_handler(), preempt_enable_no_resched() gets called,
which will try to decrement the preempt_count value by 1. But since
exception stack contains the preempt_count as ZERO, this operation
will make its value as NEGATIVE and that results in OOPS. Execution
stops after this point and system reboots
Two solutions are incorporated to solve this fix
1. The head_booke.h is modified before setting the exception stack. This
patch takes care of copying the original stack preempt_count value to
exception stack before Stack Pointer gets changed
2. Also as part of traps.c within DebugException(), the original stack
thread_info contents are copied to exception stack since other contents
of current thread_info is also required.
With the above 2 fixes, the system is stable and the kprobes behavior
is same as other architectures.
I am porting these patches to 2.6.21-rc7 and will resubmit these
patches after testing.
Originally i thought of combining the 2nd patch contents as part of 1st
patch in the form of assembly, but i could not do it because of my
limited PPC assembly knowledge.
If you have any comments regarding the above patches or better
solution, please let me know and i shall try it in 2.6.21.rc7..
Regards
Madhvesh
[-- Attachment #2: kprobes-ppc-2.6.16.39-1.patch --]
[-- Type: application/octet-stream, Size: 25233 bytes --]
kprobes-ppc-1.patch:
This patch is to add Kprobes support for BOOKE version of PPC32
Signed-off-by: Madhvesh Sulibhavi <madhvesh.s@ap.sony.com>
Signed-off-by: Lubna Badkar <lubna@ap.sony.com>
Index: linux-2.6.16.39/arch/powerpc/lib/Makefile
===================================================================
--- linux-2.6.16.39.orig/arch/powerpc/lib/Makefile 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/powerpc/lib/Makefile 2007-04-11 11:28:50.386269112 +0530
@@ -13,8 +13,8 @@
strcase.o
obj-$(CONFIG_PPC_ISERIES) += e2a.o
obj-$(CONFIG_XMON) += sstep.o
+obj-$(CONFIG_KPROBES) += sstep.o
ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_SMP) += locks.o
-obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
endif
Index: linux-2.6.16.39/arch/ppc/Kconfig
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/Kconfig 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig 2007-04-11 11:33:10.666700472 +0530
@@ -1397,3 +1397,17 @@
source "security/Kconfig"
source "crypto/Kconfig"
+
+menu "Instrumentation Support"
+
+config KPROBES
+ bool "Kprobes"
+ depends on DEBUG_KERNEL
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+endmenu
Index: linux-2.6.16.39/arch/ppc/kernel/Makefile
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/Makefile 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/Makefile 2007-04-11 11:28:50.389268656 +0530
@@ -21,6 +21,7 @@
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_RAPIDIO) += rio.o
obj-$(CONFIG_KGDB) += ppc-stub.o
+obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
obj-$(CONFIG_TAU) += temp.o
ifndef CONFIG_E200
Index: linux-2.6.16.39/arch/ppc/kernel/kprobes.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/arch/ppc/kernel/kprobes.c 2007-04-11 11:41:53.335242776 +0530
@@ -0,0 +1,371 @@
+/*
+ * Kernel Probes (KProbes)
+ * arch/ppc/kernel/kprobes.c
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/preempt.h>
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/sstep.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ int ret = 0;
+ kprobe_opcode_t insn = *p->addr;
+
+ if ((unsigned long)p->addr & 0x03) {
+ printk("Attempt to register kprobe at an unaligned address\n");
+ ret = -EINVAL;
+ } else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
+ printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
+ ret = -EINVAL;
+ }
+
+ /* insn must be on a special executable page on ppc32 */
+ if (!ret) {
+ p->ainsn.insn = get_insn_slot();
+ if (!p->ainsn.insn)
+ ret = -ENOMEM;
+ }
+
+ if (!ret) {
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
+ flush_icache_range((unsigned long) p->ainsn.insn,
+ (unsigned long) p->ainsn.insn + sizeof(kprobe_opcode_t));
+ }
+
+ return ret;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ down(&kprobe_mutex);
+ free_insn_slot(p->ainsn.insn);
+ up(&kprobe_mutex);
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ regs->msr &= ~(MSR_EE); /* Turn off 'Externel Interrupt' bits */
+ regs->msr &= ~(MSR_CE); /* Turn off 'Critical Interrupt' bits */
+ regs->msr |= MSR_DE;
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+ regs->nip = (unsigned long)p->ainsn.insn;
+}
+
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
+{
+ __get_cpu_var(current_kprobe) = p;
+ regs->msr |= (MSR_EE); /* Turn on 'External Interrupt' bits */
+ regs->msr |= (MSR_CE); /* Turn on 'Critical Interrupt' bits */
+ kcb->kprobe_saved_msr = regs->msr;
+}
+
+/* Called with kretprobe_lock held */
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
+{
+}
+
+static inline int kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ int ret = 0;
+ unsigned int *addr = (unsigned int *)regs->nip;
+ struct kprobe_ctlblk *kcb;
+
+
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
+
+ preempt_disable();
+ kcb = get_kprobe_ctlblk();
+
+ /* Check we're not actually recursing */
+ if (kprobe_running()) {
+ p = get_kprobe(addr);
+ if (p) {
+ kprobe_opcode_t insn = *p->ainsn.insn;
+ if (kcb->kprobe_status == KPROBE_HIT_SS &&
+ is_trap(insn)) {
+ regs->msr &= ~MSR_DE; /* Turn off 'trace' bits */
+ regs->msr |= kcb->kprobe_saved_msr;
+ goto no_kprobe;
+ }
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
+ kcb->kprobe_saved_msr = regs->msr;
+ kprobes_inc_nmissed_count(p);
+ prepare_singlestep(p, regs);
+ kcb->kprobe_status = KPROBE_REENTER;
+ return 1;
+ } else {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /* If trap variant, then it belongs not to us */
+ kprobe_opcode_t cur_insn = *addr;
+ if (is_trap(cur_insn))
+ goto no_kprobe;
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ ret = 1;
+ goto no_kprobe;
+ }
+ p = __get_cpu_var(current_kprobe);
+ if (p->break_handler && p->break_handler(p, regs)) {
+ goto ss_probe;
+ }
+ }
+ goto no_kprobe;
+ }
+
+ p = get_kprobe(addr);
+ if (!p) {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /*
+ * PowerPC has multiple variants of the "trap"
+ * instruction. If the current instruction is a
+ * trap variant, it could belong to someone else
+ */
+ kprobe_opcode_t cur_insn = *addr;
+ if (is_trap(cur_insn))
+ goto no_kprobe;
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+ * either a probepoint or a debugger breakpoint
+ * at this address. In either case, no further
+ * handling of this interrupt is appropriate.
+ */
+ ret = 1;
+ }
+ /* Not one of ours: let kernel handle it */
+ goto no_kprobe;
+ }
+
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p, regs, kcb);
+ if (p->pre_handler && p->pre_handler(p, regs))
+ /* handler has already set things up, so skip ss setup */
+ return 1;
+
+ss_probe:
+ prepare_singlestep(p, regs);
+ kcb->kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ preempt_enable_no_resched();
+ return ret;
+}
+
+/*
+ * Function return probe trampoline:
+ * - init_kprobes() establishes a probepoint here
+ * - When the probed function returns, this probe
+ * causes the handlers to fire
+ */
+void kretprobe_trampoline_holder(void)
+{
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 1;
+}
+
+/*
+ * Called after single-stepping. p->addr is the address of the
+ * instruction whose first byte has been replaced by the "breakpoint"
+ * instruction. 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. The address of this
+ * copy is p->ainsn.insn.
+ */
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ int ret;
+ unsigned int insn = *p->ainsn.insn;
+
+ regs->nip = (unsigned long)p->addr;
+ ret = emulate_step(regs, insn);
+ if (ret == 0)
+ regs->nip = (unsigned long)p->addr + 4;
+}
+
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
+ return 0;
+
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
+ }
+
+ resume_execution(cur, regs);
+ regs->msr |= kcb->kprobe_saved_msr;
+
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
+ goto out;
+ }
+ reset_current_kprobe();
+out:
+ preempt_enable_no_resched();
+
+ /*
+ * if somebody else is singlestepping across a probe point, msr
+ * will have DE set, in which case, continue the remaining processing
+ * of do_debug, as if this is not a probe hit.
+ */
+ if (regs->msr & MSR_DE)
+ return 0;
+
+ return 1;
+}
+
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs);
+ regs->msr &= ~MSR_DE; /* Turn off 'trace' bits */
+ regs->msr |= kcb->kprobe_saved_msr;
+
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ }
+
+ return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BPT:
+ if (kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (post_kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
+ if (kprobe_running() &&
+ kprobe_fault_handler(args->regs, args->trapnr))
+ ret = NOTIFY_STOP;
+ preempt_enable();
+ break;
+ case DIE_IABR_MATCH:
+ printk("\nIABR Match Found\n");
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+}
+
+void __kprobes jprobe_return_end(void)
+{
+};
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 1;
+}
+
+int __init arch_init_kprobes(void)
+{
+ return 0;
+}
Index: linux-2.6.16.39/arch/ppc/kernel/misc.S
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/misc.S 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/misc.S 2007-04-11 11:28:50.392268200 +0530
@@ -427,7 +427,7 @@
*
* __flush_icache_range(unsigned long start, unsigned long stop)
*/
-_GLOBAL(__flush_icache_range)
+_KPROBE(__flush_icache_range)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
Index: linux-2.6.16.39/arch/ppc/kernel/traps.c
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/traps.c 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/traps.c 2007-04-11 11:42:42.129824872 +0530
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/prctl.h>
+#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -39,6 +40,7 @@
#include <asm/reg.h>
#include <asm/xmon.h>
#include <asm/pmc.h>
+#include <asm/kdebug.h>
#ifdef CONFIG_XMON
extern int xmon_bpt(struct pt_regs *regs);
@@ -70,6 +72,23 @@
#endif
#endif
+#ifdef CONFIG_KPROBES
+struct notifier_block *ppc_die_chain;
+static DEFINE_SPINLOCK(die_notifier_lock);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ int err = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&die_notifier_lock, flags);
+ err = notifier_chain_register(&ppc_die_chain, nb);
+ spin_unlock_irqrestore(&die_notifier_lock, flags);
+ return err;
+}
+
+#endif
+
/*
* Trap & Exception support
*/
@@ -402,6 +421,11 @@
void instruction_breakpoint_exception(struct pt_regs *regs)
{
+#ifdef CONFIG_KPROBES
+ if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
+ 5, SIGTRAP) == NOTIFY_STOP)
+ return;
+#endif
if (debugger_iabr_match(regs))
return;
_exception(SIGTRAP, regs, TRAP_BRKPT, 0);
@@ -622,7 +646,7 @@
return 0;
}
-void program_check_exception(struct pt_regs *regs)
+void __kprobes program_check_exception(struct pt_regs *regs)
{
unsigned int reason = get_reason(regs);
extern int do_mathemu(struct pt_regs *regs);
@@ -671,6 +695,11 @@
}
if (reason & REASON_TRAP) {
+#ifdef CONFIG_KPROBES
+ if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
+ == NOTIFY_STOP)
+ return;
+#endif
/* trap exception */
if (debugger_bpt(regs))
return;
@@ -791,8 +820,43 @@
void DebugException(struct pt_regs *regs, unsigned long debug_status)
{
+ struct thread_info *thread_info, *exception_thread_info;
+
if (debug_status & DBSR_IC) { /* instruction completion */
regs->msr &= ~MSR_DE;
+
+#ifdef CONFIG_KPROBES
+ /* Disable instruction completion */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
+ /* Clear the instruction completion event */
+ mtspr(SPRN_DBSR, DBSR_IC);
+ /*
+ * On Book E and perhaps other processsors, singlestep is
+ * handled on the critical exception stack. This causes
+ * current_thread_info() to fail, since it locates the
+ * thread_info by masking off the low bits of the current
+ * stack pointer. We work around this issue by copying
+ * the thread_info from the kernel stack before calling
+ * kprobe_post_handler, and copying it back afterwards.
+ * On most processors the copy is avoided since
+ * exception_thread_info == thread_info.
+ */
+ thread_info = (struct thread_info *)
+ (regs->gpr[1] & ~(THREAD_SIZE - 1));
+ exception_thread_info = current_thread_info();
+
+ if (thread_info != exception_thread_info)
+ memcpy(exception_thread_info, thread_info,
+ sizeof *thread_info);
+
+ if (notify_die(DIE_SSTEP, "single_step", regs, 5,
+ 5, SIGTRAP) == NOTIFY_STOP) {
+ if (thread_info != exception_thread_info)
+ memcpy(thread_info, exception_thread_info,
+ sizeof *thread_info);
+ return;
+ }
+#endif
if (user_mode(regs)) {
current->thread.dbcr0 &= ~DBCR0_IC;
} else {
Index: linux-2.6.16.39/arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/vmlinux.lds.S 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/vmlinux.lds.S 2007-04-11 11:28:50.395267744 +0530
@@ -33,6 +33,7 @@
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
*(.got1)
__got2_start = .;
Index: linux-2.6.16.39/arch/ppc/mm/fault.c
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/mm/fault.c 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/mm/fault.c 2007-04-11 11:38:35.298348960 +0530
@@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/highmem.h>
#include <linux/module.h>
+#include <linux/kprobes.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -36,6 +37,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/tlbflush.h>
+#include <asm/kdebug.h>
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
extern void (*debugger)(struct pt_regs *);
@@ -92,7 +94,7 @@
* the error_code parameter is ESR for a data fault, 0 for an instruction
* fault.
*/
-int do_page_fault(struct pt_regs *regs, unsigned long address,
+int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
struct vm_area_struct * vma;
@@ -116,6 +118,13 @@
is_write = error_code & 0x02000000;
#endif /* CONFIG_4xx || CONFIG_BOOKE */
+#ifdef CONFIG_KPROBES
+ if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code,
+ 11, SIGSEGV) == NOTIFY_STOP) {
+ return 0;
+ }
+#endif
+
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_fault_handler && TRAP(regs) == 0x300) {
debugger_fault_handler(regs);
Index: linux-2.6.16.39/include/asm-powerpc/sstep.h
===================================================================
--- linux-2.6.16.39.orig/include/asm-powerpc/sstep.h 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/include/asm-powerpc/sstep.h 2007-04-11 11:28:50.397267440 +0530
@@ -21,6 +21,7 @@
*/
#define IS_MTMSRD(instr) (((instr) & 0xfc0007be) == 0x7c000124)
#define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024)
+#define IS_RFI(instr) (((instr) & 0xfc0007fe) == 0x4c000064)
/* Emulate instructions that cause a transfer of control. */
extern int emulate_step(struct pt_regs *regs, unsigned int instr);
Index: linux-2.6.16.39/include/asm-ppc/kdebug.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/include/asm-ppc/kdebug.h 2007-04-11 11:28:50.398267288 +0530
@@ -0,0 +1,60 @@
+#ifndef __PPC_KDEBUG_H
+#define __PPC_KDEBUG_H
+#ifdef __KERNEL__
+/*
+ * Kernel Probes (KProbes)
+ * include/asm-ppc/kdebug.h
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+ struct pt_regs *regs;
+ const char *str;
+ long err;
+ int trapnr;
+ int signr;
+};
+
+/*
+ Note - you should never unregister because that can race with NMIs.
+ If you really want to do it first unregister - then synchronize_sched -
+ then free.
+ */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *ppc_die_chain;
+
+/* Grossly misnamed. */
+enum die_val {
+ DIE_OOPS = 1,
+ DIE_IABR_MATCH,
+ DIE_BPT,
+ DIE_SSTEP,
+ DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+{
+ struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+ return notifier_call_chain(&ppc_die_chain, val, &args);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __PPC_KDEBUG_H */
Index: linux-2.6.16.39/include/asm-ppc/kprobes.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/include/asm-ppc/kprobes.h 2007-04-11 11:28:50.399267136 +0530
@@ -0,0 +1,71 @@
+#ifndef __PPC_KPROBES_H
+#define __PPC_KPROBES_H
+#ifdef __KERNEL__
+/*
+ * Kernel Probes (KProbes)
+ * include/asm-ppc/kprobes.h
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/percpu.h>
+
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+
+struct pt_regs;
+struct kprobe;
+
+typedef unsigned int kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
+#define MAX_INSN_SIZE 1
+
+#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
+
+#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry)
+
+#define is_trap(instr) (IS_TW(instr) || IS_TWI(instr))
+
+#define ARCH_SUPPORTS_KRETPROBES
+void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
+
+/* Architecture specific copy of original instruction */
+struct arch_specific_insn {
+ /* copy of original instruction */
+ kprobe_opcode_t *insn;
+};
+
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long saved_msr;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_saved_msr;
+ struct pt_regs jprobe_saved_regs;
+ struct prev_kprobe prev_kprobe;
+};
+
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+#endif /* __KERNEL__ */
+#endif /* __PPC_KPROBES_H */
Index: linux-2.6.16.39/arch/ppc/kernel/head_booke.h
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/head_booke.h 2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/head_booke.h 2007-04-11 11:34:34.031027168 +0530
@@ -85,6 +85,35 @@
#endif
/*
+ * The below macro is specific to kprobes support which addresses copying
+ * preempt count value from current stack to exception stack. This is
+ * required because kprobes has to be processed by disabling preemption.
+ * Even though it is disabled in kprobe_handler, since exception stack
+ * gets used for debug exception, this copy is taken care explicitly.
+ * Other fields of thread information is copied as part of DebugException
+ * before jumping to kprobe post handler.
+ */
+#ifdef CONFIG_KPROBES
+#define COPY_PREEMPT_STATUS \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11); \
+ rlwinm r6,r1,0,0,18; \
+ lwz r6,TI_PREEMPT(r6); \
+ rlwinm r7,r11,0,0,18; \
+ stw r6,TI_PREEMPT(r7); \
+ mr r1,r11; \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11)
+#else
+#define COPY_PREEMPT_STATUS \
+ mr r1,r11; \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+#endif
+
+/*
* Exception prolog for critical/machine check exceptions. This is a
* little different from the normal exception prolog above since a
* critical/machine check exception can potentially occur at any point
@@ -121,11 +150,7 @@
stw r1,GPR1(r11); \
mfspr r9,exc_level_srr1; \
stw r1,0(r11); \
- mr r1,r11; \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
+ COPY_PREEMPT_STATUS
#define CRITICAL_EXCEPTION_PROLOG \
EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
[-- Attachment #3: kprobes-kernel-test-module.patch --]
[-- Type: application/octet-stream, Size: 42183 bytes --]
kprobes-kernel-test-module.patch :
Kernel Probes test modules
Kprobes is a kernel debugging technique. This can be tested using kernel
modules. These kernel module will hook the user defined pre handler, post
handler and fault handler to the probed point.
Signed-off-by: Madhvesh Sulibhavi <madhvesh.s@ap.sony.com>
Signed-off-by: Lubna Badkar <lubna@ap.sony.com>
Index: linux-2.6.16.39/Makefile
===================================================================
--- linux-2.6.16.39.orig/Makefile 2007-03-12 18:26:59.470356760 +0530
+++ linux-2.6.16.39/Makefile 2007-03-12 18:29:57.976219744 +0530
@@ -559,7 +559,7 @@
ifeq ($(KBUILD_EXTMOD),)
-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ kprobe-tests/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
Index: linux-2.6.16.39/kprobe-tests/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/Kconfig 2007-03-12 18:29:57.976219744 +0530
@@ -0,0 +1,13 @@
+#
+# Kprobes test modules configuration
+#
+config KPROBESTEST
+ tristate "Kprobes test modules"
+ depends on KPROBES
+ default m if KPROBES=y
+ help
+ This support if enabled, will be used to test the kprobes support.
+
+ To compile this kprobe test support as a module, choose M here: the
+ module will be called k-00x(x will be any number in 1,2,....9).
+ If in doubt, say "N"
Index: linux-2.6.16.39/kprobe-tests/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/Makefile 2007-03-12 18:29:57.977219592 +0530
@@ -0,0 +1,5 @@
+#
+# Makefile for the Kprobes test modules kernel.
+#
+obj-$(CONFIG_KPROBESTEST) += k-001.o k-002.o k-003.o k-004.o k-005.o k-006.o \
+ k-007.o k-008.o k-009.o
Index: linux-2.6.16.39/kprobe-tests/k-001.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-001.c 2007-03-12 18:31:52.266844928 +0530
@@ -0,0 +1,91 @@
+/*
+ * k-001.c - A Kprobe with probe point to the kernel function 'do_fork'.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include "kprobes-test.h"
+
+#if defined(CONFIG_PPC32)
+extern void show_allregs(struct pt_regs *regs);
+#endif
+static struct kprobe k_001_kpr;
+
+static void __exit k_001_exit_probe(void)
+{
+ printk("\nModule exiting from do_fork \n");
+ unregister_kprobe(&k_001_kpr);
+}
+
+static int k_001_before_hook(struct kprobe *k_001_kpr, struct pt_regs *p)
+{
+ printk("\nBefore hook in do_fork");
+ printk("\nThis is the Kprobe pre \n"
+ "handler for instruction at %p\n", k_001_kpr->addr);
+ printk("Stack Dump :\n");
+ dump_stack();
+ printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+ show_allregs(p);
+#endif
+ return 0;
+}
+
+static int k_001_after_hook(struct kprobe *k_001_kpr,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook in do_fork");
+ printk("\nThis is the Kprobe post \n"
+ "handler for instruction at" " %p\n", k_001_kpr->addr);
+ printk("Stack Dump :\n");
+ dump_stack();
+ printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+ show_allregs(p);
+#endif
+ return 0;
+}
+
+static int __init k_001_init_probe(void)
+{
+ printk("\nInserting the kprobe for do_fork\n");
+
+ /* Registering a kprobe */
+ k_001_kpr.pre_handler = (kprobe_pre_handler_t) k_001_before_hook;
+ k_001_kpr.post_handler = (kprobe_post_handler_t) k_001_after_hook;
+ k_001_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+ if (k_001_kpr.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobe is \n"
+ "going to be inserted - %p\n", k_001_kpr.addr);
+ register_kprobe(&k_001_kpr);
+ return 0;
+}
+
+module_init(k_001_init_probe);
+module_exit(k_001_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-002.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-002.c 2007-03-12 18:31:59.940678328 +0530
@@ -0,0 +1,95 @@
+/*
+ * k-002.c - Multiple Kprobes with the same probe point for the kernel
+ * function 'do_fork'.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_002_kp1;
+static struct kprobe k_002_kp2;
+
+static void __exit k_002_exit_probe(void)
+{
+ printk("\nModule exiting");
+ printk("2 kprobes from do-fork\n");
+ unregister_kprobe(&k_002_kp2);
+ unregister_kprobe(&k_002_kp1);
+}
+
+static int k_002_before_hook(struct kprobe *k_002_kp1, struct pt_regs *p)
+{
+ printk("\nBefore hook 1st do_fork\n");
+ return 0;
+}
+
+static int k_002_after_hook(struct kprobe *k_002_kp1,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook 1st do_fork\n");
+ return 0;
+}
+
+static int k_002_pre_handler(struct kprobe *k_002_kp2, struct pt_regs *p)
+{
+ printk("\nBefore hook 2nd do_fork\n");
+ return 0;
+}
+
+static int k_002_post_handler(struct kprobe *k_002_kp2,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook 2nd do_fork\n");
+ return 0;
+}
+
+static int __init k_002_init_probe(void)
+{
+ printk("\nInserting two kprobes at the same probe point\n");
+
+ /* Registering a kprobe */
+ k_002_kp1.pre_handler = (kprobe_pre_handler_t) k_002_before_hook;
+ k_002_kp1.post_handler = (kprobe_post_handler_t) k_002_after_hook;
+
+ k_002_kp2.pre_handler = (kprobe_pre_handler_t) k_002_pre_handler;
+ k_002_kp2.post_handler = (kprobe_post_handler_t) k_002_post_handler;
+ k_002_kp2.addr = k_002_kp1.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+ if ((k_002_kp1.addr == NULL) || (k_002_kp2.addr == NULL)) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the two kprobes are \n"
+ "going to be inserted - %p and %p\n", k_002_kp1.addr,
+ k_002_kp2.addr);
+ register_kprobe(&k_002_kp1);
+ register_kprobe(&k_002_kp2);
+
+ return 0;
+}
+
+module_init(k_002_init_probe);
+module_exit(k_002_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-003.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-003.c 2007-03-12 18:32:09.980152096 +0530
@@ -0,0 +1,97 @@
+/*
+ * k-003.c - Multiple kprobes with the different probe point for the kernel
+ * function 'do_fork' and 'sys_gettimeofday'.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_003_kp1;
+static struct kprobe k_003_kp2;
+
+static void __exit k_003_exit_probe(void)
+{
+ printk("\nModule exiting");
+ printk("\n2 kprobes from do-fork and sys_gettimeofday\n");
+ unregister_kprobe(&k_003_kp2);
+ unregister_kprobe(&k_003_kp1);
+}
+
+static int k_003_before_hook(struct kprobe *k_003_kp1, struct pt_regs *p)
+{
+ printk("\nBefore hook in do_fork\n");
+ return 0;
+}
+
+static int k_003_after_hook(struct kprobe *k_003_kp1,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook in do_fork\n");
+ return 0;
+}
+
+static int k_003_pre_handler(struct kprobe *k_003_kp2, struct pt_regs *p)
+{
+ printk("\nBefore hook in sys_gettimeofday\n");
+ return 0;
+}
+
+static int k_003_post_handler(struct kprobe *k_003_kp2,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook in sys_gettimeofday\n");
+ return 0;
+}
+
+static int __init k_003_init_probe(void)
+{
+ printk("\nInserting two kprobes at differnt probe point\n");
+
+ /* Registering a kprobe */
+ k_003_kp1.pre_handler = (kprobe_pre_handler_t) k_003_before_hook;
+ k_003_kp1.post_handler = (kprobe_post_handler_t) k_003_after_hook;
+
+ k_003_kp2.pre_handler = (kprobe_pre_handler_t) k_003_pre_handler;
+ k_003_kp2.post_handler = (kprobe_post_handler_t) k_003_post_handler;
+ k_003_kp1.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+ k_003_kp2.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("sys_gettimeofday");
+
+ if ((k_003_kp1.addr == NULL) | (k_003_kp2.addr == NULL)) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobes are \n"
+ "going to be inserted - %p and %p\n", k_003_kp1.addr,
+ k_003_kp2.addr);
+ register_kprobe(&k_003_kp1);
+ register_kprobe(&k_003_kp2);
+
+ return 0;
+}
+
+module_init(k_003_init_probe);
+module_exit(k_003_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-004.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-004.c 2007-03-12 18:32:17.532004040 +0530
@@ -0,0 +1,124 @@
+/*
+ * k-004.c - Kprobes with the fault handler for the kernel function
+ * 'sys_gettimeofday'.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include "kprobes-test.h"
+
+#if defined(CONFIG_PPC32)
+extern void show_allregs(struct pt_regs *regs);
+#endif
+static struct kprobe k_004_kpr;
+
+void k_004_CPY_FROM_USER(struct file *file, char *buf, int len)
+{
+
+ char x = 'a';
+
+ if (put_user(x, buf)) {
+ printk("put_user : -EFAULT\n");
+ }
+
+ printk("CPY_FROM_USER\n");
+}
+
+static void __exit k_004_exit_probe(void)
+{
+ printk("\nModule exiting from sys_gettimeofday \n");
+ unregister_kprobe(&k_004_kpr);
+}
+
+static int k_004_before_hook(struct kprobe *k_004_kpr, struct pt_regs *p)
+{
+ int len = 500;
+ struct file *file;
+
+ printk("\nBefore hook in sys_gettimeofday");
+ printk("\nThis is the Kprobe pre \n"
+ "handler for instruction at" "%p\n", k_004_kpr->addr);
+ printk("Stack Dump:\n");
+ dump_stack();
+ printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+ show_allregs(p);
+#endif
+ k_004_CPY_FROM_USER(file, NULL, len);
+ return 0;
+}
+
+static int k_004_after_hook(struct kprobe *k_004_kpr,
+ struct pt_regs *p, unsigned long flags)
+{
+ printk("\nAfter hook in sys_gettimeofday");
+ printk("\nThis is the Kprobe post \n"
+ "handler for instruction at" " %p\n", k_004_kpr->addr);
+ printk("Stack Dump:\n");
+ dump_stack();
+ printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+ show_allregs(p);
+#endif
+ return 0;
+}
+
+int k_004_fault_probe(struct kprobe *p, struct pt_regs *regs, int trapnr)
+{
+ printk("\nThis is the Kprobe fault \n"
+ "handler for sys_gettimeodday\n");
+ printk("fault_handler:p->addr=0x%p\n", p->addr);
+ printk("Stack Dump:\n");
+ dump_stack();
+ printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+ show_allregs(regs);
+#endif
+ return 0;
+}
+
+static int __init k_004_init_probe(void)
+{
+ printk("\nInserting the kprobes for sys_gettimeofday\n");
+
+ /* Registering a kprobe */
+ k_004_kpr.pre_handler = (kprobe_pre_handler_t) k_004_before_hook;
+ k_004_kpr.post_handler = (kprobe_post_handler_t) k_004_after_hook;
+ k_004_kpr.fault_handler = (kprobe_fault_handler_t) k_004_fault_probe;
+ k_004_kpr.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("sys_gettimeofday");
+ if (k_004_kpr.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobe is \n"
+ "going to be inserted - %p\n", k_004_kpr.addr);
+ register_kprobe(&k_004_kpr);
+ return 0;
+}
+
+module_init(k_004_init_probe);
+module_exit(k_004_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-005.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-005.c 2007-03-12 18:32:26.889581472 +0530
@@ -0,0 +1,72 @@
+/*
+ * k-005.c - A Kprobe with probe point to the kernel function sys_read.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_005_kpr;
+static int k_005_kr_kprobe_read_cnt;
+
+static void __exit k_005_exit_probe(void)
+{
+ printk("kernel kprobe_read_cnt is %d \n", k_005_kr_kprobe_read_cnt);
+ printk("\nModule exiting from sys_read \n");
+ unregister_kprobe(&k_005_kpr);
+}
+
+static int k_005_before_hook(struct kprobe *kpr, struct pt_regs *p)
+{
+ return 0;
+}
+
+static int k_005_after_hook(struct kprobe *kpr,
+ struct pt_regs *p, unsigned long flags)
+{
+ k_005_kr_kprobe_read_cnt++;
+ return 0;
+}
+
+static int __init k_005_init_probe(void)
+{
+ printk("\nInserting the kprobe for sys_read\n");
+
+ /* Registering a kprobe */
+ k_005_kpr.pre_handler = (kprobe_pre_handler_t) k_005_before_hook;
+ k_005_kpr.post_handler = (kprobe_post_handler_t) k_005_after_hook;
+ k_005_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_read");
+ if (k_005_kpr.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobe is \n"
+ "going to be inserted - %p\n", k_005_kpr.addr);
+ register_kprobe(&k_005_kpr);
+ return 0;
+}
+
+module_init(k_005_init_probe);
+module_exit(k_005_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-006.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-006.c 2007-03-12 18:32:34.632404384 +0530
@@ -0,0 +1,72 @@
+/*
+ * k-006.c - A Kprobe with probe point to the kernel function sys_write.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_006_kpr;
+static int k_006_kr_kprobe_write_cnt;
+
+static void __exit k_006_exit_probe(void)
+{
+ printk("kernel kprobe_write_cnt is %d \n", k_006_kr_kprobe_write_cnt);
+ printk("\nModule exiting from sys_write \n");
+ unregister_kprobe(&k_006_kpr);
+}
+
+static int k_006_before_hook(struct kprobe *kpr, struct pt_regs *p)
+{
+ return 0;
+}
+
+static int k_006_after_hook(struct kprobe *kpr,
+ struct pt_regs *p, unsigned long flags)
+{
+ k_006_kr_kprobe_write_cnt++;
+ return 0;
+}
+
+static int __init k_006_init_probe(void)
+{
+ printk("\nInserting the kprobe for sys_write\n");
+
+ /* Registering a kprobe */
+ k_006_kpr.pre_handler = (kprobe_pre_handler_t) k_006_before_hook;
+ k_006_kpr.post_handler = (kprobe_post_handler_t) k_006_after_hook;
+ k_006_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_write");
+ if (k_006_kpr.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobe is \n"
+ "going to be inserted - %p\n", k_006_kpr.addr);
+ register_kprobe(&k_006_kpr);
+ return 0;
+}
+
+module_init(k_006_init_probe);
+module_exit(k_006_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-007.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-007.c 2007-03-12 18:32:41.485362576 +0530
@@ -0,0 +1,80 @@
+/*
+ * k-007.c - Kprobes with probe points to the kernel functions __kmalloc and
+ * kfree.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_007_kp, k_007_kp1;
+int k_007_kmalloc_count = 0;
+int k_007_kfree_count = 0;
+
+static int k_007_kmalloc_hndlr(struct kprobe *kpr, struct pt_regs *p)
+{
+ k_007_kmalloc_count++;
+ return 0;
+}
+
+static int k_007_kfree_hndlr(struct kprobe *kpr, struct pt_regs *p)
+{
+ k_007_kfree_count++;
+ return 0;
+}
+
+static int __init k_007_kmf_init(void)
+{
+ int ret;
+ k_007_kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("__kmalloc");
+ k_007_kp.pre_handler = k_007_kmalloc_hndlr;
+ k_007_kp1.addr = (kprobe_opcode_t *) kallsyms_lookup_name("kfree");
+ k_007_kp1.pre_handler = k_007_kfree_hndlr;
+ ret = register_kprobe(&k_007_kp);
+ if (ret != 0) {
+ printk(KERN_ERR "register_kprobe returns %d %d \n", ret,
+ __LINE__);
+ return -1;
+ }
+
+ ret = register_kprobe(&k_007_kp1);
+ if (ret != 0) {
+ printk(KERN_ERR "register_kprobe returns %d %d \n", ret,
+ __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit k_007_kmf_exit(void)
+{
+ printk("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\n\n");
+ printk("kmalloc count is %d \n", k_007_kmalloc_count);
+ printk("kfree count is %d \n", k_007_kfree_count);
+ printk("\n\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+ unregister_kprobe(&k_007_kp);
+ unregister_kprobe(&k_007_kp1);
+ printk(KERN_INFO "ktime: exiting...\n");
+}
+
+module_init(k_007_kmf_init);
+module_exit(k_007_kmf_exit);
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-008.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-008.c 2007-03-12 18:32:48.248334448 +0530
@@ -0,0 +1,68 @@
+/*
+ * k-008.c - A Kprobe with a probe point to the kernel function
+ * do_gettimeofday, with an empty pre-handler which can be used
+ * to measure the Kprobes overhead.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_008_kp1;
+
+static void __exit k_008_exit_probe(void)
+{
+ printk("\nModule exiting ");
+ printk("from gettimeofday\n");
+ unregister_kprobe(&k_008_kp1);
+}
+
+static int k_008_pre_handler(struct kprobe *k_008_kp1, struct pt_regs *p)
+{
+ return 0;
+}
+
+static int __init k_008_init_probe(void)
+{
+ printk("\nInserting the kprobe at do_gettimeofday\n");
+
+ /* Registering a kprobe */
+ k_008_kp1.pre_handler = (kprobe_pre_handler_t) k_008_pre_handler;
+ k_008_kp1.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("do_gettimeofday");
+
+ if (k_008_kp1.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobes are \n"
+ "going to be inserted - %p \n", k_008_kp1.addr);
+ register_kprobe(&k_008_kp1);
+
+ return 0;
+}
+
+module_init(k_008_init_probe);
+module_exit(k_008_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-009.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-009.c 2007-03-12 18:32:55.554223784 +0530
@@ -0,0 +1,74 @@
+/*
+ * k-009.c - A Kprobe with a probe point to the kernel function
+ * do_gettimeofday, with the empty pre-handler and post-handler
+ * which can be used to measure the Kprobes overhead.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_009_kp1;
+
+static void __exit k_009_exit_probe(void)
+{
+ printk("\nModule exiting ");
+ printk("from gettimeofday\n");
+ unregister_kprobe(&k_009_kp1);
+}
+
+static int k_009_pre_handler(struct kprobe *k_009_kp1, struct pt_regs *p)
+{
+ return 0;
+}
+
+static int k_009_post_handler(struct kprobe *k_009_kp1,
+ struct pt_regs *p, unsigned long flags)
+{
+ return 0;
+}
+
+static int __init k_009_init_probe(void)
+{
+ printk("\nInserting the kprobe at do_gettimeofday\n");
+
+ /* Registering a kprobe */
+ k_009_kp1.pre_handler = (kprobe_pre_handler_t) k_009_pre_handler;
+ k_009_kp1.post_handler = (kprobe_post_handler_t) k_009_post_handler;
+ k_009_kp1.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("do_gettimeofday");
+
+ if (k_009_kp1.addr == NULL) {
+ printk("kallsyms_lookup_name could not find address "
+ "for the specified symbol name\n");
+ return 1;
+ }
+
+ printk("\nAddress where the kprobes are \n"
+ "going to be inserted - %p \n", k_009_kp1.addr);
+ register_kprobe(&k_009_kp1);
+
+ return 0;
+}
+
+module_init(k_009_init_probe);
+module_exit(k_009_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/Documentation/kprobe-tests.txt
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/Documentation/kprobe-tests.txt 2007-03-12 18:29:57.986218224 +0530
@@ -0,0 +1,299 @@
+Title : Kernel Probes test modules
+
+Kprobes is a kernel debugging technique. This can be tested using kernel
+modules. These kernel module will hook the user defined pre handler, post
+handler and fault handler to the probed point.
+
+When configuring the kernel using make menuconfig/xconfig/oldconfig,
+ensure that CONFIG_KPROBES is set to "y". Under "Instrumentation
+Support", look for "Kprobes".
+
+And also ensure that CONFIG_KPROBESTEST is set to "m", only if
+CONFIG_KPROBES is set to "y"
+
+To load and unload Kprobes-based instrumentation modules, make sure
+"Loadable module support" (CONFIG_MODULES) and "Module unloading"
+(CONFIG_MODULE_UNLOAD) are set to "y".
+
+You may also want to ensure that CONFIG_KALLSYMS and perhaps even
+CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name()
+is a handy, version-independent way to find a function's address.
+
+The Kprobes modules are:
+
+- kprobe-tests/k-00x.c ( x = 0,1,2....9 )
+
+
+1. k-001.c
+
+A Kprobe with probe point to the kernel function 'do_fork'.
+This will test the working of KPROBES support.
+
+DESCRIPTION:
+It has a kernel probe 'k_001_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_001_before_hook
+2. Kprobe's post-handler : k_001_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("do_fork").
+
+When this module is inserted using insmod, it registers the k_001_kpr
+using 'register_kprobe(&k_001_kpr)'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handler 'k_001_before_hook()'. As part of the this
+function call it dumps the stack using dump_stack() and also shows
+the register content at that point using k_001_show_allregs().
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_001_after_hook()'. This also does the same dump_stack and
+shows the register content at that point using k_001_show_allregs().
+
+While unloading the module using rmmod(), it deregisters the k_001_kpr
+using 'unregister_kprobe()'.
+
+
+2. k-002.c
+
+OBJECTIVE :
+Multiple Kprobes with the same probe point for the kernel function
+'do_fork'.
+
+DESCRIPTION :
+ It has two kernel probes 'k_002_kp1 and k_002_kp2' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_002_kp1 : k_002_before_hook
+2 Kprobe's post-handler for k_002_kp1 : k_002_after_hook
+3. Kprobe's pre-handler for k_002_kp2 : k_002_pre_handler
+4. Kprobe's post-handler for k_002_kp2 : k_002_post_handler
+
+And the probed adddress for k_002_kp1 is : kallsyms_lookup_name("do_fork").
+And the probed adddress for k_002_kp2 is : kallsyms_lookup_name("do_fork").
+
+When this module is inserted using insmod, it registers the k_002_kp1 and
+k_002_kp2 using 'register_kprobe()'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handlers 'k_002_pre_handler' and 'k_002_before_hook'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handlers 'k_002_post_handler' and 'k_002_after_hook()'.
+
+While unloading the module using rmmod(), it deregisters the k_002_kp1
+and k_002_kp2 using 'unregister_kprobe()'.
+
+
+3. k-003.c
+
+OBJECTIVE :
+Multiple kprobes with the different probe point for the kernel function
+'do_fork' and 'sys_gettimeofday'.
+
+DESCRIPTION :
+It has two kernel probes 'k_003_kp1 and k_003_kp2' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_003_kp1 : k_003_before_hook
+2 Kprobe's post-handler for k_003_kp1 : k_003_after_hook
+3. Kprobe's pre-handler for k_003_kp2 : k_003_pre_handler
+4. kprobe's post-handler for k_003_kp2 : k_003_post_handler
+
+And the probed adddress for k_003_kp1 is : kallsyms_lookup_name("do_fork").
+And for k_003_kp2 is : kallsyms_lookup_name("sys_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_003_kp1 and
+k_003_kp2 using 'register_kprobe()'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handlers 'k_003_before_hook'.
+
+When the adress of a kernel routine 'sys_gettimeofday' is hit, Kprobes
+calls user defined pre handlers 'k_003_pre_handler'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handlers 'k_003_post_handler' and 'k_003_after_hook()' for each probed
+address.
+
+While unloading the module using rmmod(), it deregisters the k_003_kp1
+and k_003_kp2 using 'unregister_kprobe()'.
+
+
+4. k-004.c
+
+Kprobes with the fault handler for the kernel function 'sys_gettimeofday'.
+
+DESCRIPTION:
+It has a kernel probe 'k_004_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_004_before_hook
+2. Kprobe's post-handler : k_004_after_hook
+3. Kprobe's fault-handler : k_004_fault_probe
+
+And the probed adddress is : kallsyms_lookup_name("sys_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_004_kpr
+using 'register_kprobe(&k_004_kpr)'.
+
+When the adress of a kernel routine 'sys_gettimeofday' is hit, Kprobes
+calls user defined pre handler 'k_004_before_hook()'. As part of the this
+function call it dumps the stack using dump_stack() and also shows the
+register content at that point using k_004_show_allregs().
+And also pre handler k_004_before_hook() tries to genearate a fault by
+doing put_user() for a null buffer.
+
+When this fault is hit, Kprobe calls kprobe's fault handler 'k_004_fault_probe'.
+After the probed instruction single-stepped, Kprobes calls the post handler
+'k_004_after_hook()'. This also does the same dump_stack and shows the
+register content at that point using k_004_show_allregs().
+
+While unloading the module using rmmod(), it deregisters the k_004_kpr using
+'unregister_kprobe()'.
+
+
+5. k-005.c
+
+A Kprobe with probe point to the kernel function sys_read.
+
+DESCRIPTION:
+It has a kernel probe 'k_005_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_005_before_hook
+2. Kprobe's post-handler : k_005_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("sys_read").
+
+When this module is inserted using insmod, it registers the k_005_kpr
+using 'register_kprobe(&k_005_kpr)'.
+
+When the adress of a kernel routine 'sys_read' is hit, Kprobes
+calls user defined pre handler 'k_005_before_hook()'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_005_after_hook()'. This will increases the count variable
+'k_005_kr_kprobe_read_cnt' by one.
+
+While unloading the module using rmmod(), it deregisters the k_005_kpr
+using 'unregister_kprobe()' and also prints the total number of read count.
+
+
+6. k-006.c
+
+A Kprobe with probe point to the kernel function sys_write.
+
+DESCRIPTION:
+It has a kernel probe 'k_006_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_006_before_hook
+2. Kprobe's post-handler : k_006_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("sys_write").
+
+When this module is inserted using insmod, it registers the k_006_kpr
+using 'register_kprobe(&k_006_kpr)'.
+
+When the adress of a kernel routine 'sys_read' is hit, Kprobes calls
+user defined pre handler 'k_006_before_hook()'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_006_after_hook()'. This will increases the count variable
+'k_006_kr_kprobe_write_cnt' by one.
+
+While unloading the module using rmmod(), it deregisters the k_006_kpr
+using 'unregister_kprobe()' and also prints the total number of write
+count.
+
+
+7. k-007.c
+
+Kprobes with probe points to the kernel functions __kmalloc and kfree.
+
+DESCRIPTION :
+It has two kernel probes 'k_007_kp and k_007_kp1' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_007_kp : k_007_kmalloc_hndlr
+2. Kprobe's pre-handler for k_007_kp1 : k_007_kfree_hndlr
+
+And the probed adddress for k_007_kp is : kallsyms_lookup_name("__kmalloc").
+And the probed adddress for k_007_kp1 is: kallsyms_lookup_name("kfree").
+
+When this module is inserted using insmod, it registers the k_007_kp and
+k_007_kp1 using 'register_kprobe()'.
+
+When the adress of a kernel routine '__kmalloc' is hit, Kprobes calls
+user defined pre handlers 'k_007_kmalloc_hndlr'. This will increases
+the count variable 'k_007_kmalloc_count' by one.
+
+When the adress of a kernel routine 'free' is hit, Kprobes calls user
+defined pre handlers 'k_007_kfree_hndlr'. This will increases the
+count variable 'k_007_kfree_count' by one.
+
+After the pre handler excution it does the single-stepping of the
+probed instruction.
+
+While unloading the module using rmmod(), it deregisters the k_003_kp
+and k_003_kp1 using 'unregister_kprobe()' and also prints the total
+number of __kmalloc and kfree counts.
+
+
+8. k-008.c
+
+A Kprobe with a probe point to the kernel function do_gettimeofday,
+with an empty pre-handler which can be used to measure the Kprobes
+overhead.
+
+DESCRIPTION:
+It has a kernel probe 'k_008_kp1' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_008_pre_handler
+
+And the probed adddress is : kallsyms_lookup_name("do_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_008_kp1
+using 'register_kprobe(&k_008_kp1)'.
+
+When the adress of a kernel routine 'do_gettimeofday' is hit, Kprobes
+calls user defined empty pre handler 'k_008_pre_handler()'.
+
+After the pre handler excution it does the single-stepping of the probed
+instruction.
+
+While unloading the module using rmmod(), it deregisters the k_008_kp1
+using 'unregister_kprobe()'.
+
+
+9. k-009.c
+
+A Kprobe with a probe point to the kernel function do_gettimeofday,
+with the empty pre-handler and post-handler which can be used to
+measure the Kprobes overhead.
+
+DESCRIPTION:
+It has a kernel probe 'k_009_kp1' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler : k_009_pre_handler
+2. Kprobe's post-handler : k_009_post_handler
+
+And the probed adddress is : kallsyms_lookup_name("do_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_009_kp1
+using 'register_kprobe(&k_009_kp1)'.
+
+When the adress of a kernel routine 'do_gettimeofday' is hit, Kprobes
+calls user defined empty pre handler 'k_009_pre_handler()'.
+
+After the probed instruction single-stepped, Kprobes calls the empty post
+handler 'k_009_post_handler'.
+
+While unloading the module using rmmod(), it deregisters the k_009_kp1
+using 'unregister_kprobe()'.
Index: linux-2.6.16.39/kprobe-tests/kprobes-test.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/kprobes-test.h 2007-03-12 18:30:54.164677800 +0530
@@ -0,0 +1,101 @@
+#ifndef _KPROBES_TEST_H
+#define _KPROBES_TEST_H
+/*
+ * kprobes-test.h - Architecture specific kprobes test functions.
+ *
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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
+ */
+
+#ifdef CONFIG_PPC32
+#include<linux/utsname.h>
+#include <asm/uaccess.h>
+
+#define REG "%08lX"
+#define REGS_PER_LINE 8
+#define LAST_VOLATILE 12
+
+static struct regbit {
+ unsigned long bit;
+ const char *name;
+} msr_bits[] = {
+ {MSR_WE, "WE"},
+ {MSR_CE, "CE"},
+ {MSR_EE, "EE"},
+ {MSR_PR, "PR"},
+ {MSR_ME, "ME"},
+ {MSR_DWE, "DWE"},
+ {MSR_DE, "DE"},
+ {MSR_IS, "IS"},
+ {MSR_DS, "DS"},
+ {0, NULL}
+};
+
+static void printbits(unsigned long val, struct regbit *bits)
+{
+ const char *sep = "";
+
+ printk("<");
+ for (; bits->bit; ++bits)
+ if (val & bits->bit) {
+ printk("%s%s", sep, bits->name);
+ sep = ",";
+ }
+ printk(">");
+}
+void show_allregs(struct pt_regs * regs)
+{
+ int i, trap;
+
+ printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
+ regs->nip, regs->link, regs->ctr);
+ printk("REGS: %p TRAP: %04lx (%s)\n",
+ regs, regs->trap, system_utsname.release);
+ printk("MSR: "REG" ", regs->msr);
+ printbits(regs->msr, msr_bits);
+ printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer);
+ trap = TRAP(regs);
+ if (trap == 0x300 || trap == 0x600)
+ printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
+ printk("TASK = %p[%d] '%s' THREAD: %p",
+ current, current->pid, current->comm, task_thread_info(current));
+
+#ifdef CONFIG_SMP
+ printk(" CPU: %d", smp_processor_id());
+#endif /* CONFIG_SMP */
+
+ for (i = 0; i < 32; i++) {
+ if ((i % REGS_PER_LINE) == 0)
+ printk("\n" KERN_INFO "GPR%02d: ", i);
+ printk(REG " ", regs->gpr[i]);
+ if (i == LAST_VOLATILE && !FULL_REGS(regs))
+ break;
+ }
+ printk("\n");
+#ifdef CONFIG_KALLSYMS
+ /*
+ * Lookup NIP late so we have the best change of getting the
+ * above info out without failing
+ */
+ printk("NIP ["REG"] ", regs->nip);
+ print_symbol("%s\n", regs->nip);
+ printk("LR ["REG"] ", regs->link);
+ print_symbol("%s\n", regs->link);
+#endif
+}
+#endif
+
+
+#endif
Index: linux-2.6.16.39/arch/ppc/Kconfig
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/Kconfig 2007-03-12 18:26:59.476355848 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig 2007-03-12 18:29:57.989217768 +0530
@@ -1410,4 +1410,5 @@
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
+source "kprobe-tests/Kconfig"
endmenu
^ permalink raw reply
* Re: [PATCH] kexec-tools ppc64: add --reuseinitrd option
From: Michael Neuling @ 2007-04-20 7:23 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, horms, kexec, Fastboot mailing list
In-Reply-To: <46b0d1603ea2ab82b37daaa1888e8793@bga.com>
In message <46b0d1603ea2ab82b37daaa1888e8793@bga.com> you wrote:
>
> On Apr 18, 2007, at 11:29 PM, Michael Neuling wrote:
>
> > Add a --reuseinitrd option so that initrds saved using the
> > retain_initrd kernel option can be reused on the kexec boot.
> >
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > ---
> > Horms: This fixes comments from Milton. Also adds sanity checks to
> > make
> > sure the old initrd was retained, and that another initrd/ramdisk is
> > not
> > being specified at the same time.
> >
> > fastboot is dead... love live kexec! Yay :-)
> >
>
> > - checkprop(fn, dt);
> > + checkprop(fn, dt, len);
> >
> > /* Get the cmdline from the device-tree and modify it */
> > if (!strcmp(dp->d_name, "bootargs")) {
> > @@ -249,6 +263,10 @@ static void putprops(char *fn, struct di
> > char temp_cmdline[COMMAND_LINE_SIZE] = { "" };
> > char *param = NULL;
> > cmd_len = strlen(local_cmdline);
> > + if (reuse_initrd &&
> > + (strstr((char *)dt, "retain_initrd") == NULL))
> > + die("unrecoverable error: current boot didn't "
> > + "retain the initrd for reuse.\n");
>
> Although this seems efficent to look at what was in the device tree,
> I'd prefer we actually looked at /proc/cmdline when we parse the
> arg, so that we are sure to find what the kernel is actually
> using for the command line.
>
> Besides it will be eaiser for other archs to copy the check.
Looks like we should make it a generic option. If we do, this should
probably be two patches. One to introduce the option, and one for the
ppc64 specific parts.
Do any of the other architectures allow you to see where the initrd is
located for the current boot from user space? If not, the option will
need to take two parameters saying where the retained initrd is. This
will make the option less generic (if not, we'll need to change the
other archs to export these values to user space).
> > /* Add initrd entries to the second kernel */
> > - if (initrd_base && !strcmp(basename,"/chosen/")) {
> > + if (initrd_base && !strcmp(basename,"/chosen/") && !reuse_initrd) {
>
> How does initrd_base get set if you disallow --initrd= ?
Oops, that's left over crud. Thanks.
When using this option, the initrd entries get imported from the first
kernel, rather than being generated here.
>
> >
> > @@ -148,6 +154,9 @@ int elf_ppc64_load(int argc, char **argv
> > else
> > fprintf(stdout, "Warning: append= option is not passed. Using t
he
> > first kernel root partition\n");
> >
> > + if (ramdisk && reuse_initrd)
> > + die("Can't specify --ramdisk or --initrd with --reuseinitrd\n")
;
> > +
>
> This check is generic, not elf specific, so it should be where
> we pass the args. Hmm, maybe this is that place and it just
> wants abstracting, I don't have the tree in front of me.
I put it here so the error's caught independent of the arg parsing
order. Otherwise, we'd need to duplicate the check.
I think it's the right place, unless we move it to an arch generic
option.
Mikey
^ permalink raw reply
* Re: FDT for MPC5200, CPU revision, MSCAN
From: Wolfgang Grandegger @ 2007-04-20 7:21 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: linuxppc-embedded
In-Reply-To: <462864CA.7050601@grandegger.com>
Wolfgang Grandegger wrote:
> Hello,
>
> is there a way to distinguish the CPU revision (Rev.A vs. Rev.B) of the
> MPC5200, preferably at run time? Or should this be defined in the FDT?
> I ask, because some settings depend on the CPU revision due to hardware
> bugs, like the clock source used for MSCAN.
I found the information here:
$ cat Documentation/powerpc/mpc52xx-device-tree-bindings.txt
...
The 5200B is almost the same as the 5200, but not quite. It fixes
silicon bugs and it adds a small number of enhancements. Most of the
devices either provide exactly the same interface as on the 5200. A few
devices have extra functions but still have a backwards compatible mode.
To express this infomation as completely as possible, 5200B device trees
should have two items in the compatible list;
"mpc5200b-<device>\0mpc5200-<device>". It is *strongly* recommended
that 5200B device trees follow this convention (instead of only listing
the base mpc5200 item).
...
Sorry for the noise.
Wolfgang.
^ permalink raw reply
* FDT for MPC5200, CPU revision, MSCAN
From: Wolfgang Grandegger @ 2007-04-20 6:59 UTC (permalink / raw)
To: linuxppc-embedded
Hello,
is there a way to distinguish the CPU revision (Rev.A vs. Rev.B) of the
MPC5200, preferably at run time? Or should this be defined in the FDT?
I ask, because some settings depend on the CPU revision due to hardware
bugs, like the clock source used for MSCAN.
Thanks.
Wolfgang.
^ permalink raw reply
* Re: PREEMPT_RT patch on 85xx
From: Pradyumna Sampath @ 2007-04-20 6:46 UTC (permalink / raw)
To: Johan Borkhuis; +Cc: Linuxppc-embedded
In-Reply-To: <46285CF6.30409@dutchspace.nl>
[-- Attachment #1: Type: text/plain, Size: 725 bytes --]
Hi Johan,
> Josh,
>
> Josh Boyer wrote:
> > arch/ppc is dying a slow death and is being replaced by arch/powerpc.
> > This is likely why there is no ppc "backport".
> >
> Thanks for your answer. I was not aware that the ppc-branch was being
> replaced. For the board we use we just received a BSP that is based on
> the ppc-branch.
>
I have been having some problems with getting RT_PREEMPT compiled for
my 52xx icecube board. Here is a patch that I created which compiles
for me. Just compiles and does not mean that the full RT_PREEMPT
functionality is available. :-)
However, PPC support for the CONFIG_RT_PREEMPT is currently broken and
I understand that the developers are working on this as we speak.
regards
Prady
[-- Attachment #2: patch-2.6.21-rc6-rt0-pr0 --]
[-- Type: application/octet-stream, Size: 5281 bytes --]
diff -u -r rc6-rt0/linux-2.6.20/arch/ppc/Kconfig linux-2.6.20/arch/ppc/Kconfig
--- rc6-rt0/linux-2.6.20/arch/ppc/Kconfig 2007-04-18 16:41:56.000000000 +0530
+++ linux-2.6.20/arch/ppc/Kconfig 2007-04-18 12:05:31.000000000 +0530
@@ -58,6 +58,14 @@
default y
depends on BUG
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
+config GENERIC_TIME
+ bool
+ default y
+
source "init/Kconfig"
menu "Processor"
diff -u -r rc6-rt0/linux-2.6.20/arch/ppc/kernel/time.c linux-2.6.20/arch/ppc/kernel/time.c
--- rc6-rt0/linux-2.6.20/arch/ppc/kernel/time.c 2007-04-18 16:41:56.000000000 +0530
+++ linux-2.6.20/arch/ppc/kernel/time.c 2007-04-18 13:14:44.000000000 +0530
@@ -200,6 +200,7 @@
/*
* This version of gettimeofday has microsecond resolution.
*/
+#ifndef CONFIG_GENERIC_TIME
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
@@ -282,6 +283,7 @@
}
EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
/* This function is only called on the boot processor */
void __init time_init(void)
Only in linux-2.6.20/: .config
Only in linux-2.6.20/: .config.old
diff -u -r rc6-rt0/linux-2.6.20/drivers/mtd/maps/Kconfig linux-2.6.20/drivers/mtd/maps/Kconfig
--- rc6-rt0/linux-2.6.20/drivers/mtd/maps/Kconfig 2007-04-18 16:41:41.000000000 +0530
+++ linux-2.6.20/drivers/mtd/maps/Kconfig 2007-04-18 15:21:31.000000000 +0530
@@ -374,6 +374,18 @@
Redwood board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
+config MTD_LITE5200
+ tristate "CFI Flash devices mapped on Metrowerks Lite5200"
+ depends on MTD_CFI && PPC_MPC52xx && LITE5200
+
+config MTD_LITE5200B
+ tristate "CFI Flash devices mapped on Freescale Lite5200B"
+ depends on MTD_CFI && PPC_MPC52xx && LITE5200B
+
+config MTD_MEDIA5200
+ tristate "CFI Flash devices mapped on Freescale Media5200"
+ depends on MTD_CFI && PPC_MPC52xx && MEDIA5200
+
config MTD_TQM834x
tristate "Flash device mapped on TQ Components TQM834x Boards"
depends on MTD_CFI && TQM834x
Only in linux-2.6.20/drivers/mtd/maps: Kconfig.orig
Only in linux-2.6.20/drivers/mtd/maps: lite5200.c
diff -u -r rc6-rt0/linux-2.6.20/drivers/mtd/maps/Makefile linux-2.6.20/drivers/mtd/maps/Makefile
--- rc6-rt0/linux-2.6.20/drivers/mtd/maps/Makefile 2007-02-05 00:14:54.000000000 +0530
+++ linux-2.6.20/drivers/mtd/maps/Makefile 2007-04-18 15:21:31.000000000 +0530
@@ -51,6 +51,10 @@
obj-$(CONFIG_MTD_IMPA7) += impa7.o
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
obj-$(CONFIG_MTD_REDWOOD) += redwood.o
+obj-$(CONFIG_MTD_LITE5200) += lite5200.o
+obj-$(CONFIG_MTD_LITE5200B) += lite5200.o
+obj-$(CONFIG_MTD_MEDIA5200) += media5200.o
+obj-$(CONFIG_MTD_CHESTNUT) += chestnut.o
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
Only in linux-2.6.20/drivers/mtd/maps: Makefile.orig
Only in linux-2.6.20/drivers/mtd/maps: media5200.c
Only in linux-2.6.20/include: asm
diff -u -r rc6-rt0/linux-2.6.20/include/asm-powerpc/irqflags.h linux-2.6.20/include/asm-powerpc/irqflags.h
--- rc6-rt0/linux-2.6.20/include/asm-powerpc/irqflags.h 2007-02-05 00:14:54.000000000 +0530
+++ linux-2.6.20/include/asm-powerpc/irqflags.h 2007-04-18 12:05:08.000000000 +0530
@@ -14,14 +14,18 @@
* Get definitions for raw_local_save_flags(x), etc.
*/
#include <asm-powerpc/hw_irq.h>
-
/*
* Do the CPU's IRQ-state tracing from assembly code. We call a
* C function, so save all the C-clobbered registers:
*/
#ifdef CONFIG_TRACE_IRQFLAGS
-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
+//#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
+#define TRACE_IRQS_ON \
+ bl trace_hardirqs_on; \
+
+#define TRACE_IRQS_OFF \
+ bl trace_hardirqs_off; \
#else
# define TRACE_IRQS_ON
Only in linux-2.6.20/include: config
Only in linux-2.6.20/include/linux: autoconf.h
Only in linux-2.6.20/include/linux: utsrelease.h
Only in linux-2.6.20/include/linux: version.h
diff -u -r rc6-rt0/linux-2.6.20/Makefile linux-2.6.20/Makefile
--- rc6-rt0/linux-2.6.20/Makefile 2007-04-18 16:41:56.000000000 +0530
+++ linux-2.6.20/Makefile 2007-04-18 16:39:07.000000000 +0530
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 21
-EXTRAVERSION = -rc6-rt0
-NAME = Nocturnal Monster Puppy
+EXTRAVERSION = -rc6-rt0-pr0
+NAME = incrc black dustbins
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
Only in linux-2.6.20/: Module.symvers
Only in linux-2.6.20/scripts/basic: docproc
Only in linux-2.6.20/scripts/basic: fixdep
Only in linux-2.6.20/scripts: conmakehash
Only in linux-2.6.20/scripts/genksyms: genksyms
Only in linux-2.6.20/scripts/genksyms: keywords.c
Only in linux-2.6.20/scripts/genksyms: lex.c
Only in linux-2.6.20/scripts/genksyms: parse.c
Only in linux-2.6.20/scripts/genksyms: parse.h
Only in linux-2.6.20/scripts: kallsyms
Only in linux-2.6.20/scripts/kconfig: conf
Only in linux-2.6.20/scripts/kconfig: lex.zconf.c
Only in linux-2.6.20/scripts/kconfig: mconf
Only in linux-2.6.20/scripts/kconfig: zconf.hash.c
Only in linux-2.6.20/scripts/kconfig: zconf.tab.c
Only in linux-2.6.20/scripts/mod: elfconfig.h
Only in linux-2.6.20/scripts/mod: mk_elfconfig
Only in linux-2.6.20/scripts/mod: modpost
Only in linux-2.6.20/scripts: trace-it
Only in linux-2.6.20/: .version
^ permalink raw reply
* Re: PREEMPT_RT patch on 85xx
From: Johan Borkhuis @ 2007-04-20 6:25 UTC (permalink / raw)
To: Linuxppc-embedded
In-Reply-To: <1176985606.3877.12.camel@zod.rchland.ibm.com>
Josh,
Josh Boyer wrote:
> arch/ppc is dying a slow death and is being replaced by arch/powerpc.
> This is likely why there is no ppc "backport".
>
Thanks for your answer. I was not aware that the ppc-branch was being
replaced. For the board we use we just received a BSP that is based on
the ppc-branch.
Is there some documentation available on the differences between the ppc
and powerpc architecure, and on porting a bsp from ppc to powerpc?
Kind regards,
Johan Borkhuis
^ permalink raw reply
* Re: [PATCH] kexec-tools ppc64: add --reuseinitrd option
From: Milton Miller @ 2007-04-20 5:58 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, horms, kexec, Fastboot mailing list
In-Reply-To: <5129.1176956949@neuling.org>
On Apr 18, 2007, at 11:29 PM, Michael Neuling wrote:
> Add a --reuseinitrd option so that initrds saved using the
> retain_initrd kernel option can be reused on the kexec boot.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
> Horms: This fixes comments from Milton. Also adds sanity checks to
> make
> sure the old initrd was retained, and that another initrd/ramdisk is
> not
> being specified at the same time.
>
> fastboot is dead... love live kexec! Yay :-)
>
> - checkprop(fn, dt);
> + checkprop(fn, dt, len);
>
> /* Get the cmdline from the device-tree and modify it */
> if (!strcmp(dp->d_name, "bootargs")) {
> @@ -249,6 +263,10 @@ static void putprops(char *fn, struct di
> char temp_cmdline[COMMAND_LINE_SIZE] = { "" };
> char *param = NULL;
> cmd_len = strlen(local_cmdline);
> + if (reuse_initrd &&
> + (strstr((char *)dt, "retain_initrd") == NULL))
> + die("unrecoverable error: current boot didn't "
> + "retain the initrd for reuse.\n");
Although this seems efficent to look at what was in the device tree,
I'd prefer we actually looked at /proc/cmdline when we parse the
arg, so that we are sure to find what the kernel is actually
using for the command line.
Besides it will be eaiser for other archs to copy the check.
> if (cmd_len != 0) {
> param = strstr(local_cmdline, "crashkernel=");
> if (param)
> @@ -282,7 +300,7 @@ static void putprops(char *fn, struct di
> }
>
> fn[0] = '\0';
> - checkprop(pathname, NULL);
> + checkprop(pathname, NULL, 0);
> }
>
> /*
> @@ -343,7 +361,7 @@ static void putnode(void)
> putprops(dn, namelist, numlist);
>
> /* Add initrd entries to the second kernel */
> - if (initrd_base && !strcmp(basename,"/chosen/")) {
> + if (initrd_base && !strcmp(basename,"/chosen/") && !reuse_initrd) {
How does initrd_base get set if you disallow --initrd= ?
>
> @@ -148,6 +154,9 @@ int elf_ppc64_load(int argc, char **argv
> else
> fprintf(stdout, "Warning: append= option is not passed. Using the
> first kernel root partition\n");
>
> + if (ramdisk && reuse_initrd)
> + die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
> +
This check is generic, not elf specific, so it should be where
we pass the args. Hmm, maybe this is that place and it just
wants abstracting, I don't have the tree in front of me.
> setup_memory_ranges(info->kexec_flags);
>
> /* Need to append some command line parameters internally in case of
>
milton
^ permalink raw reply
* Re: [PATCH] Fix interrupt distribution in ppc970
From: Milton Miller @ 2007-04-20 5:45 UTC (permalink / raw)
To: mohan; +Cc: ppcdev, Paul Mackerras, Anton Blanchard, fastboot
In-Reply-To: <20070419115233.GA4172@in.ibm.com>
On Apr 19, 2007, at 6:52 AM, Mohan Kumar M wrote:
> On Wed, Apr 11, 2007 at 11:16:41AM +1000, Michael Ellerman wrote:
>> On Tue, 2007-04-10 at 11:59 -0500, Milton Miller wrote:
>>>
>>> This means we are doing population counts of two masks, when we
>>> really
>>> just care that they are the same. How about using
>>> cpus_equal(cpu_online_mask, cpu_present_mask)?
>>
>> Yep that's sensible.
>>
>>> This shows how close these two functions are. The difference is
>>> what happens when cpus_empty is true -- we default in one and
>>> ignore in the other.
>>>
>>> How about adding another arg to get_server, that says to fail
>>> or default for the empty case, with failure being -1?
>
> I modified the patch based on suggestions given by Milton and Mike.
> Milton is this patch okay?
Well, its part of the way there.
>
> Tested on 2.6.21-rc7.
> Index: linux-2.6.21-rc4/arch/powerpc/platforms/pseries/xics.c
> ===================================================================
> --- linux-2.6.21-rc4.orig/arch/powerpc/platforms/pseries/xics.c
> +++ linux-2.6.21-rc4/arch/powerpc/platforms/pseries/xics.c
> @@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_
>
>
> #ifdef CONFIG_SMP
> -static int get_irq_server(unsigned int virq)
> +static int get_irq_server(unsigned int virq, unsigned int
> strict_check)
> {
> - unsigned int server;
> + int server;
> /* For the moment only implement delivery to all cpus or one cpu */
> cpumask_t cpumask = irq_desc[virq].affinity;
> cpumask_t tmp = CPU_MASK_NONE;
> @@ -167,21 +167,25 @@ static int get_irq_server(unsigned int v
> return default_server;
>
> if (cpus_equal(cpumask, CPU_MASK_ALL)) {
> - server = default_distrib_server;
> + if (cpus_equal(cpu_online_map, cpu_present_map))
> + server = default_distrib_server;
> + else
> + server = default_server;
> } else {
> cpus_and(tmp, cpu_online_map, cpumask);
>
> - if (cpus_empty(tmp))
> + if (cpus_empty(tmp) && !strict_check)
> server = default_distrib_server;
> + else if(cpus_empty(tmp) && strict_check)
> + server = -1;
> else
> server = get_hard_smp_processor_id(first_cpu(tmp));
> }
Don't test cpus_empty twice, instead do a nested if.
Actually, looking at this a bit, you need your default_distrib or
default_server check again.
How about reorder to be if (!cpus_equal(...ALL)) {
cpus_and
if !cpus_empty(tmp
return get_hard(first);
if (strict)
return -1;
}
if (cpus_equal(online, preseent)
return distrib
return default_server
For that matter, can we just call first_cpu, and check its <= NUM_CPUS
elminating the call to cpus_empty ? Only call get_hard_cpu if its
valid.
...
> @@ -415,7 +419,10 @@ static void xics_set_affinity(unsigned i
...
> /* For the moment only implement delivery to all cpus or one cpu */
> if (cpus_equal(cpumask, CPU_MASK_ALL)) {
> - newmask = default_distrib_server;
> + if (cpus_equal(cpu_online_map, cpu_present_map))
>
this was supposed to be the call with strict = 1
milton
^ permalink raw reply
* [PATCH][RFC][POWERPC] i2c: adds support for i2c bus on 8xx
From: Vitaly Bordug @ 2007-04-20 4:27 UTC (permalink / raw)
To: Jean Delvare; +Cc: linuxppc-dev@ozlabs.org, lkml
Utilized devicetree to store I2C data, ported i2c-algo-8xx.c from 2.4
approach(which remains nearly intact), refined i2c-rpx.c. I2C functionality has been validated on
mpc885ads with EEPROM access.
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
---
Jean,
The patch below may have rough edges but I'd appreciate you to take a look.
It adds I2C capabilities of PQ series (mpc8xx mostly) or, more correctly, takes
them off from the 2.4 kernel and makes it work.
Validated with quilt tree residing at
http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
arch/powerpc/boot/dts/mpc885ads.dts | 7
arch/powerpc/platforms/8xx/mpc885ads_setup.c | 14 +
arch/powerpc/sysdev/fsl_soc.c | 61 +++
drivers/i2c/algos/Kconfig | 2
drivers/i2c/algos/Makefile | 1
drivers/i2c/algos/i2c-algo-8xx.c | 622 ++++++++++++++++++++++++++
drivers/i2c/busses/Kconfig | 4
drivers/i2c/busses/i2c-rpx.c | 129 ++++-
include/linux/i2c-algo-8xx.h | 29 +
9 files changed, 822 insertions(+), 47 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 19d2d79..90e047a 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -188,6 +188,13 @@
interrupts = <1d 3>;
interrupt-parent = <930>;
};
+ i2c@860 {
+ device_type = "i2c";
+ compatible = "fsl-i2c-cpm";
+ reg = <860 20 3c80 30>;
+ interrupts = <10 3>;
+ interrupt-parent = <930>;
+ };
};
};
};
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index 9bd81c7..d32e066 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -51,6 +51,7 @@ static void init_smc1_uart_ioports(struc
static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
static void init_scc3_ioports(struct fs_platform_info* ptr);
static void init_irda_ioports(void);
+static void init_i2c_ioports(void);
void __init mpc885ads_board_setup(void)
{
@@ -120,6 +121,10 @@ #endif
#ifdef CONFIG_8XX_SIR
init_irda_ioports();
#endif
+
+#ifdef CONFIG_I2C_RPXLITE
+ init_i2c_ioports();
+#endif
}
@@ -361,6 +366,15 @@ static void init_irda_ioports()
immr_unmap(cp);
}
+static void init_i2c_ioports()
+{
+ cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
+
+ setbits32(&cp->cp_pbpar, 0x00000030);
+ setbits32(&cp->cp_pbdir, 0x00000030);
+ setbits16(&cp->cp_pbodr, 0x0030);
+}
+
int platform_device_skip(const char *model, int id)
{
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 419b688..7ecd537 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -331,7 +331,7 @@ static int __init fsl_i2c_of_init(void)
for (np = NULL, i = 0;
(np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
i++) {
- struct resource r[2];
+ struct resource r[3];
struct fsl_i2c_platform_data i2c_data;
const unsigned char *flags = NULL;
@@ -1215,4 +1215,63 @@ err:
arch_initcall(fs_irda_of_init);
+static const char *i2c_regs = "regs";
+static const char *i2c_pram = "pram";
+static const char *i2c_irq = "interrupt";
+
+static int __init fsl_i2c_cpm_of_init(void)
+{
+ struct device_node *np;
+ unsigned int i;
+ struct platform_device *i2c_dev;
+ int ret;
+
+ for (np = NULL, i = 0;
+ (np = of_find_compatible_node(np, "i2c", "fsl-i2c-cpm")) != NULL;
+ i++) {
+ struct resource r[3];
+ struct fsl_i2c_platform_data i2c_data;
+
+ memset(&r, 0, sizeof(r));
+ memset(&i2c_data, 0, sizeof(i2c_data));
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto err;
+ r[0].name = i2c_regs;
+
+ ret = of_address_to_resource(np, 1, &r[1]);
+ if (ret)
+ goto err;
+ r[1].name = i2c_pram;
+
+ r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+ r[2].flags = IORESOURCE_IRQ;
+ r[2].name = i2c_irq;
+
+ i2c_dev = platform_device_register_simple("fsl-i2c-cpm", i, &r[0], 3);
+ if (IS_ERR(i2c_dev)) {
+ ret = PTR_ERR(i2c_dev);
+ goto err;
+ }
+
+ ret =
+ platform_device_add_data(i2c_dev, &i2c_data,
+ sizeof(struct
+ fsl_i2c_platform_data));
+ if (ret)
+ goto unreg;
+ }
+
+ return 0;
+
+unreg:
+ platform_device_unregister(i2c_dev);
+err:
+ return ret;
+}
+
+arch_initcall(fsl_i2c_cpm_of_init);
+
+
#endif /* CONFIG_8xx */
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index 5889907..7d7fb87 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -37,6 +37,8 @@ config I2C_ALGOPCA
config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface"
depends on 8xx
+ help
+ 8xx I2C Algorithm
config I2C_ALGO_SGI
tristate "I2C SGI interfaces"
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index cac1051..1bd3b37 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bi
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
+obj-$(CONFIG_I2C_ALGO8XX) += i2c-algo-8xx.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/algos/i2c-algo-8xx.c b/drivers/i2c/algos/i2c-algo-8xx.c
new file mode 100644
index 0000000..b1f414a
--- /dev/null
+++ b/drivers/i2c/algos/i2c-algo-8xx.c
@@ -0,0 +1,622 @@
+/*
+ * i2c-algo-8xx.c i2x driver algorithms for MPC8XX CPM
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * moved into proper i2c interface; separated out platform specific
+ * parts into i2c-rpx.c
+ * Brad Parker (brad@heeltoe.com)
+ */
+
+
+/* $Id: i2c-algo-8xx.c,v 1.15 2004/11/20 08:02:24 khali Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-8xx.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/time.h>
+#include <asm/mpc8xx.h>
+
+#define CPM_MAX_READ 513
+#undef I2C_CHIP_ERRATA /* Try ot define this if you have an older CPU(earlier than rev D4) */
+
+static wait_queue_head_t iic_wait;
+static ushort r_tbase, r_rbase;
+
+int cpm_debug = 0;
+int cpm_scan = 0;
+
+static irqreturn_t cpm_iic_interrupt(int irq, void *dev_id)
+{
+ i2c8xx_t *i2c = (i2c8xx_t *) dev_id;
+ if (cpm_debug > 1)
+ printk("cpm_iic_interrupt(dev_id=%p)\n", dev_id);
+#if 0
+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs */
+ /* This should probably be removed and replaced by I2C_CHIP_ERRATA stuff */
+ /* Someone with a buggy CPU needs to confirm that */
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+#endif
+ /* Clear interrupt.
+ */
+ out_8(&i2c->i2c_i2cer, 0xff);
+
+ /* Get 'me going again.
+ */
+ wake_up_interruptible(&iic_wait);
+
+ return IRQ_HANDLED;
+}
+
+static void cpm_iic_init(struct i2c_algo_8xx_data *cpm)
+{
+ iic_t *iip = cpm->iip;
+ i2c8xx_t *i2c = cpm->i2c;
+ unsigned char brg;
+
+ if (cpm_debug)
+ printk(KERN_DEBUG "cpm_iic_init()\n");
+
+ /* Initialize the parameter ram.
+ * We need to make sure many things are initialized to zero,
+ * especially in the case of a microcode patch.
+ */
+ iip->iic_rstate = 0;
+ iip->iic_rdp = 0;
+ iip->iic_rbptr = 0;
+ iip->iic_rbc = 0;
+ iip->iic_rxtmp = 0;
+ iip->iic_tstate = 0;
+ iip->iic_tdp = 0;
+ iip->iic_tbptr = 0;
+ iip->iic_tbc = 0;
+ iip->iic_txtmp = 0;
+
+ /* Set up the IIC parameters in the parameter ram.
+ */
+ iip->iic_tbase = r_tbase = cpm->dp_addr;
+ iip->iic_rbase = r_rbase = cpm->dp_addr + sizeof(cbd_t) * 2;
+
+ if (cpm_debug) {
+ printk("iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr);
+ printk("iic_tbase %d, r_tbase %d\n", iip->iic_tbase, r_tbase);
+ }
+
+ iip->iic_tfcr = SMC_EB;
+ iip->iic_rfcr = SMC_EB;
+
+ /* Set maximum receive size.
+ */
+ iip->iic_mrblr = CPM_MAX_READ;
+
+ /* Initialize Tx/Rx parameters.
+ */
+ if (cpm->reloc == 0) {
+ cpm8xx_t *cp = cpm->cp;
+ u16 v = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ out_be16(&cp->cp_cpcr, v);
+ while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) ;
+ } else {
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_tbptr = iip->iic_tbase;
+ iip->iic_rstate = 0;
+ iip->iic_tstate = 0;
+ }
+
+ /* Select an arbitrary address. Just make sure it is unique.
+ */
+ out_8(&i2c->i2c_i2add, 0xfe);
+
+ /* Make clock run at 60 KHz.
+ */
+ brg = (unsigned char)(ppc_proc_freq / (32 * 2 * 60000) - 3);
+ out_8(&i2c->i2c_i2brg, brg);
+
+ out_8(&i2c->i2c_i2mod, 0x00);
+ out_8(&i2c->i2c_i2com, 0x01); /* Master mode */
+
+ /* Disable interrupts.
+ */
+ out_8(&i2c->i2c_i2cmr, 0);
+ out_8(&i2c->i2c_i2cer, 0xff);
+
+ init_waitqueue_head(&iic_wait);
+
+ /* Install interrupt handler.
+ */
+ if (cpm_debug) {
+ printk("%s[%d] Install ISR for IRQ %d\n",
+ __func__, __LINE__, CPMVEC_I2C);
+ }
+ request_irq(cpm->irq, cpm_iic_interrupt, 0, "8xx_i2c", i2c);
+}
+
+static int cpm_iic_shutdown(struct i2c_algo_8xx_data *cpm)
+{
+ i2c8xx_t *i2c = cpm->i2c;
+
+ /* Shut down IIC.
+ */
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+ out_8(&i2c->i2c_i2cmr, 0);
+ out_8(&i2c->i2c_i2cer, 0xff);
+
+ return (0);
+}
+
+static void cpm_reset_iic_params(iic_t * iip)
+{
+ iip->iic_tbase = r_tbase;
+ iip->iic_rbase = r_rbase;
+
+ iip->iic_tfcr = SMC_EB;
+ iip->iic_rfcr = SMC_EB;
+
+ iip->iic_mrblr = CPM_MAX_READ;
+
+ iip->iic_rstate = 0;
+ iip->iic_rdp = 0;
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_rbc = 0;
+ iip->iic_rxtmp = 0;
+ iip->iic_tstate = 0;
+ iip->iic_tdp = 0;
+ iip->iic_tbptr = iip->iic_tbase;
+ iip->iic_tbc = 0;
+ iip->iic_txtmp = 0;
+}
+
+#define BD_SC_NAK ((ushort)0x0004) /* NAK - did not respond */
+#define BD_SC_OV ((ushort)0x0002) /* OV - receive overrun */
+#define CPM_CR_CLOSE_RXBD ((ushort)0x0007)
+
+static void force_close(struct i2c_algo_8xx_data *cpm)
+{
+ i2c8xx_t *i2c = cpm->i2c;
+ if (cpm->reloc == 0) { /* micro code disabled */
+ cpm8xx_t *cp = cpm->cp;
+ u16 v = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) | CPM_CR_FLG;
+
+ if (cpm_debug)
+ printk("force_close()\n");
+
+ out_be16(&cp->cp_cpcr, v);
+ while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) ;
+ }
+ out_8(&i2c->i2c_i2cmr, 0x00); /* Disable all interrupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+}
+
+/* Read from IIC...
+ * abyte = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_read(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf, int count)
+{
+ iic_t *iip = cpm->iip;
+ i2c8xx_t *i2c = cpm->i2c;
+ cbd_t *tbdf, *rbdf;
+ u_char *tb;
+ unsigned long tmo;
+ int res = 0;
+
+ if (count >= CPM_MAX_READ)
+ return -EINVAL;
+
+ /* check for and use a microcode relocation patch */
+ if (cpm->reloc) {
+ cpm_reset_iic_params(iip);
+ }
+
+ tbdf = (cbd_t *) cpm_dpram_addr(iip->iic_tbase);
+ rbdf = (cbd_t *) cpm_dpram_addr(iip->iic_rbase);
+
+ /* To read, we need an empty buffer of the proper length.
+ * All that is used is the first byte for address, the remainder
+ * is just used for timing (and doesn't really have to exist).
+ */
+ tb = cpm->temp;
+ tb = (u_char *) (((uint) tb + 15) & ~15);
+ tb[0] = abyte; /* Device address byte w/rw flag */
+
+ flush_dcache_range((unsigned long)tb, (unsigned long)(tb + 1));
+
+ if (cpm_debug)
+ printk("cpm_iic_read(abyte=0x%x)\n", abyte);
+
+ tbdf->cbd_bufaddr = __pa(tb);
+ tbdf->cbd_datlen = count + 1;
+ tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+
+ iip->iic_mrblr = count + 1; /* prevent excessive read, +1
+ is needed otherwise will the
+ RXB interrupt come too early */
+
+ /* flush will invalidate too. */
+ flush_dcache_range((unsigned long)buf, (unsigned long)(buf + count));
+
+ rbdf->cbd_datlen = 0;
+ rbdf->cbd_bufaddr = __pa(buf);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;
+
+ if (count > 16) {
+ /* Chip bug, set enable here */
+ out_8(&i2c->i2c_i2cmr, 0x13); /* Enable some interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80); /* Begin transmission */
+
+ /* Wait for IIC transfer */
+ res = wait_event_interruptible_timeout(iic_wait, 0, 1 * HZ);
+ } else { /* busy wait for small transfers, its faster */
+ out_8(&i2c->i2c_i2cmr, 0x00); /* Disable I2C interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80); /* Begin transmission */
+
+ tmo = jiffies + 1 * HZ;
+ while (!(in_8(&i2c->i2c_i2cer) & 0x11 || time_after(jiffies, tmo))) ;/* Busy wait, with a timeout */
+ }
+
+ if ( res < 0) {
+ force_close(cpm);
+ if (cpm_debug)
+ printk("IIC read: timeout!\n");
+ return -EIO;
+ }
+#ifdef I2C_CHIP_ERRATA
+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+ Disabling I2C too early may cause too short stop condition */
+ udelay(4);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+#endif
+ if (cpm_debug) {
+ printk("tx sc %04x, rx sc %04x\n", tbdf->cbd_sc, rbdf->cbd_sc);
+ }
+
+ if (tbdf->cbd_sc & BD_SC_READY) {
+ printk("IIC read; complete but tbuf ready\n");
+ force_close(cpm);
+ printk("tx sc %04x, rx sc %04x\n", tbdf->cbd_sc, rbdf->cbd_sc);
+ }
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ if (cpm_debug)
+ printk("IIC read; no ack\n");
+ return -EREMOTEIO;
+ }
+
+ if (rbdf->cbd_sc & BD_SC_EMPTY) {
+ /* force_close(cpm); */
+ if (cpm_debug) {
+ printk("IIC read; complete but rbuf empty\n");
+ printk("tx sc %04x, rx sc %04x\n",
+ tbdf->cbd_sc, rbdf->cbd_sc);
+ }
+ return -EREMOTEIO;
+ }
+
+ if (rbdf->cbd_sc & BD_SC_OV) {
+ if (cpm_debug)
+ printk("IIC read; Overrun\n");
+ return -EREMOTEIO;;
+ }
+
+ if (cpm_debug)
+ printk("read %d bytes\n", rbdf->cbd_datlen);
+
+ if (rbdf->cbd_datlen < count) {
+ if (cpm_debug)
+ printk("IIC read; short, wanted %d got %d\n",
+ count, rbdf->cbd_datlen);
+ return 0;
+ }
+
+ return count;
+}
+
+/* Write to IIC...
+ * addr = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_write(struct i2c_algo_8xx_data *cpm, u_char abyte, char *buf, int count)
+{
+ iic_t *iip = cpm->iip;
+ i2c8xx_t *i2c = cpm->i2c;
+ cbd_t *tbdf;
+ u_char *tb;
+ unsigned long tmo;
+ int res = 0;
+
+ /* check for and use a microcode relocation patch */
+ if (cpm->reloc) {
+ cpm_reset_iic_params(iip);
+ }
+ tb = cpm->temp;
+ tb = (u_char *) (((uint) tb + 15) & ~15);
+ *tb = abyte; /* Device address byte w/rw flag */
+
+ flush_dcache_range((unsigned long)tb, (unsigned long)(tb + 1));
+ flush_dcache_range((unsigned long)buf, (unsigned long)(buf + count));
+
+ if (cpm_debug)
+ printk("cpm_iic_write(abyte=0x%x)\n", abyte);
+
+ /* set up 2 descriptors */
+
+
+ tbdf = (cbd_t *) cpm_dpram_addr(iip->iic_tbase);
+
+ tbdf[0].cbd_bufaddr = __pa(tb);
+ tbdf[0].cbd_datlen = 1;
+ tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START;
+
+ tbdf[1].cbd_bufaddr = __pa(buf);
+ tbdf[1].cbd_datlen = count;
+ tbdf[1].cbd_sc = BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP;
+
+ if (count > 16) {
+ /* Chip bug, set enable here */
+ out_8(&i2c->i2c_i2cmr, 0x13); /* Enable some interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80); /* Begin transmission */
+
+ /* Wait for IIC transfer */
+ res = wait_event_interruptible_timeout(iic_wait, 0, 1 * HZ);
+ } else { /* busy wait for small transfers, its faster */
+ out_8(&i2c->i2c_i2cmr, 0x00); /* Disable I2C interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80); /* Begin transmission */
+ tmo = jiffies + 1 * HZ;
+ while (!(in_8(&i2c->i2c_i2cer) & 0x12 || time_after(jiffies, tmo))) ;/* Busy wait, with a timeout */
+ }
+
+ if ( res < 0) {
+ force_close(cpm);
+ if (cpm_debug)
+ printk("IIC write: timeout!\n");
+ return -EIO;
+ }
+#ifdef I2C_CHIP_ERRATA
+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+ Disabling I2C too early may cause too short stop condition */
+ udelay(4);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+#endif
+ if (cpm_debug) {
+ printk("tx0 sc %04x, tx1 sc %04x\n",
+ tbdf[0].cbd_sc, tbdf[1].cbd_sc);
+ }
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ if (cpm_debug)
+ printk("IIC write; no ack\n");
+ return 0;
+ }
+
+ if (tbdf->cbd_sc & BD_SC_READY) {
+ if (cpm_debug)
+ printk("IIC write; complete but tbuf ready\n");
+ return 0;
+ }
+
+ return count;
+}
+
+/* See if an IIC address exists..
+ * addr = 7 bit address, unshifted
+ */
+static int cpm_iic_tryaddress(struct i2c_algo_8xx_data *cpm, int addr)
+{
+ iic_t *iip = cpm->iip;
+ i2c8xx_t *i2c = cpm->i2c;
+ cbd_t *tbdf, *rbdf;
+ u_char *tb;
+ unsigned long len;
+ int res = 0;
+
+ if (cpm_debug > 1)
+ printk("cpm_iic_tryaddress(cpm=%p,addr=%d)\n", cpm, addr);
+
+ /* check for and use a microcode relocation patch */
+ if (cpm->reloc) {
+ cpm_reset_iic_params(iip);
+ }
+
+ if (cpm_debug && addr == 0) {
+ printk("iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr);
+ printk("iic_tbase %d, r_tbase %d\n", iip->iic_tbase, r_tbase);
+ }
+
+ tbdf = (cbd_t *) cpm_dpram_addr(iip->iic_tbase);
+ rbdf = (cbd_t *) cpm_dpram_addr(iip->iic_rbase);
+
+ tb = cpm->temp;
+ tb = (u_char *) (((uint) tb + 15) & ~15);
+
+ /* do a simple read */
+ tb[0] = (addr << 1) | 1; /* device address (+ read) */
+ len = 2;
+
+ flush_dcache_range((unsigned long)tb, (unsigned long)(tb + 2));
+
+ tbdf->cbd_bufaddr = __pa(tb);
+ tbdf->cbd_datlen = len;
+ tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+
+ rbdf->cbd_datlen = 0;
+ rbdf->cbd_bufaddr = __pa(tb + 2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT;
+
+ out_8(&i2c->i2c_i2cmr, 0x13); /* Enable some interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80); /* Begin transmission */
+
+ if (cpm_debug > 1)
+ printk("about to sleep\n");
+
+ /* wait for IIC transfer */
+ res = wait_event_interruptible_timeout(iic_wait, 0, 1 * HZ);
+
+#ifdef I2C_CHIP_ERRATA
+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+ Disabling I2C too early may cause too short stop condition */
+ udelay(4);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+#endif
+
+ if ( res < 0) {
+ force_close(cpm);
+ if (cpm_debug)
+ printk("IIC tryaddress: timeout!\n");
+ return -EIO;
+ }
+
+ if (cpm_debug > 1)
+ printk("back from sleep\n");
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ if (cpm_debug > 1)
+ printk("IIC try; no ack\n");
+ return 0;
+ }
+
+ if (tbdf->cbd_sc & BD_SC_READY) {
+ printk("IIC try; complete but tbuf ready\n");
+ }
+
+ return 1;
+}
+
+static int cpm_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+ struct i2c_algo_8xx_data *cpm = adap->algo_data;
+ struct i2c_msg *pmsg;
+ int i, ret;
+ u_char addr;
+
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+
+ if (cpm_debug)
+ printk("i2c-algo-8xx.o: "
+ "#%d addr=0x%x flags=0x%x len=%d\n buf=%lx\n",
+ i, pmsg->addr, pmsg->flags, pmsg->len,
+ (unsigned long)pmsg->buf);
+
+ addr = pmsg->addr << 1;
+ if (pmsg->flags & I2C_M_RD)
+ addr |= 1;
+ if (pmsg->flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+
+ if (!(pmsg->flags & I2C_M_NOSTART)) {
+ }
+ if (pmsg->flags & I2C_M_RD) {
+ /* read bytes into buffer */
+ ret = cpm_iic_read(cpm, addr, pmsg->buf, pmsg->len);
+ if (cpm_debug)
+ printk("i2c-algo-8xx.o: read %d bytes\n", ret);
+ if (ret < pmsg->len) {
+ return (ret < 0) ? ret : -EREMOTEIO;
+ }
+ } else {
+ /* write bytes from buffer */
+ ret = cpm_iic_write(cpm, addr, pmsg->buf, pmsg->len);
+ if (cpm_debug)
+ printk("i2c-algo-8xx.o: wrote %d\n", ret);
+ if (ret < pmsg->len) {
+ return (ret < 0) ? ret : -EREMOTEIO;
+ }
+ }
+ }
+ return (num);
+}
+
+static u32 cpm_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
+ I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm cpm_algo = {
+ .master_xfer = cpm_xfer,
+ .functionality = cpm_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_8xx_add_bus(struct i2c_adapter *adap)
+{
+ struct i2c_algo_8xx_data *cpm = adap->algo_data;
+ int i;
+
+ if (cpm_debug)
+ printk("i2c-algo-8xx.o: hw routines for %s registered.\n",
+ adap->name);
+
+ /* register new adapter to i2c module... */
+
+ adap->algo = &cpm_algo;
+
+ i2c_add_adapter(adap);
+ cpm_iic_init(cpm);
+
+ /* scan bus */
+ if (cpm_scan) {
+ printk(KERN_INFO " i2c-algo-8xx.o: scanning bus %s...\n",
+ adap->name);
+ for (i = 0; i < 128; i++) {
+ if (cpm_iic_tryaddress(cpm, i))
+ printk("(%02x)",i<<1);
+ }
+ printk("\n");
+ }
+
+ return 0;
+}
+
+int i2c_8xx_del_bus(struct i2c_adapter *adap)
+{
+ struct i2c_algo_8xx_data *cpm = adap->algo_data;
+
+ cpm_iic_shutdown(cpm);
+
+ return i2c_del_adapter(adap);
+}
+
+EXPORT_SYMBOL(i2c_8xx_add_bus);
+EXPORT_SYMBOL(i2c_8xx_del_bus);
+
+MODULE_AUTHOR("Brad Parker <brad@heeltoe.com>");
+MODULE_DESCRIPTION("I2C-Bus MPC8XX algorithm");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4afc795..83d9aef 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -385,8 +385,8 @@ config I2C_PROSAVAGE
will be called i2c-prosavage.
config I2C_RPXLITE
- tristate "Embedded Planet RPX Lite/Classic support"
- depends on RPXLITE || RPXCLASSIC
+ tristate "Embedded Planet RPX Lite/Classic and Freescale 86x/885 ads support"
+ depends on RPXLITE || RPXCLASSIC || MPC86XADS || MPC885ADS
select I2C_ALGO8XX
config I2C_S3C2410
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
index 8764df0..ebddd94 100644
--- a/drivers/i2c/busses/i2c-rpx.c
+++ b/drivers/i2c/busses/i2c-rpx.c
@@ -14,88 +14,129 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/stddef.h>
+#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-8xx.h>
#include <asm/mpc8xx.h>
#include <asm/commproc.h>
+#include <asm/fs_pd.h>
-static void
-rpx_iic_init(struct i2c_algo_8xx_data *data)
+struct m8xx_i2c {
+ char *base;
+ struct device *dev;
+ struct i2c_adapter adap;
+ struct i2c_algo_8xx_data *algo_8xx;
+};
+
+static struct i2c_algo_8xx_data rpx_data;
+
+static struct i2c_adapter rpx_ops = {
+ .owner = THIS_MODULE,
+ .name = "m8xx",
+ .id = I2C_HW_MPC8XX_EPON,
+ .algo_data = &rpx_data,
+};
+
+static int rpx_iic_init(struct m8xx_i2c *i2c)
{
volatile cpm8xx_t *cp;
- volatile immap_t *immap;
+ struct resource *r;
+ struct i2c_algo_8xx_data *data = i2c->algo_8xx;
+ struct platform_device *pdev = to_platform_device(i2c->dev);
+
+ cp = data->cp = (cpm8xx_t *)immr_map(im_cpm); /* pointer to Communication Processor */
- cp = cpmp; /* Get pointer to Communication Processor */
- immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ data->irq = platform_get_irq_byname(pdev, "interrupt");
+
+ if (data->irq < 0)
+ return -EINVAL;
- data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
+ data->iip = ioremap(r->start, r->end - r->start + 1);
+ if (data->iip == NULL)
+ return -EINVAL;
/* Check for and use a microcode relocation patch.
- */
+ */
if ((data->reloc = data->iip->iic_rpbase))
data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
- data->i2c = (i2c8xx_t *)&(immap->im_i2c);
- data->cp = cp;
-
- /* Initialize Port B IIC pins.
- */
- cp->cp_pbpar |= 0x00000030;
- cp->cp_pbdir |= 0x00000030;
- cp->cp_pbodr |= 0x00000030;
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ data->i2c = ioremap(r->start, r->end - r->start + 1);
+ if (data->i2c == NULL)
+ return -EINVAL;
/* Allocate space for two transmit and two receive buffer
* descriptors in the DP ram.
*/
data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
-
- /* ptr to i2c area */
- data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
}
-static int rpx_install_isr(int irq, void (*func)(void *), void *data)
+static int i2c_rpx_probe(struct device *device)
{
- /* install interrupt handler */
- cpm_install_handler(irq, func, data);
-
- return 0;
-}
+ int result = 0;
+ struct m8xx_i2c *i2c;
+ struct platform_device *pdev = to_platform_device(device);
-static struct i2c_algo_8xx_data rpx_data = {
- .setisr = rpx_install_isr
-};
+ if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+ return -ENOMEM;
+ }
+ memset(i2c, 0, sizeof(*i2c));
+ i2c->dev = device;
+ i2c->algo_8xx = &rpx_data;
-static struct i2c_adapter rpx_ops = {
- .owner = THIS_MODULE,
- .name = "m8xx",
- .id = I2C_HW_MPC8XX_EPON,
- .algo_data = &rpx_data,
-};
+ rpx_iic_init(i2c);
-int __init i2c_rpx_init(void)
-{
- printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n");
+ dev_set_drvdata(device, i2c);
- /* reset hardware to sane state */
- rpx_iic_init(&rpx_data);
+ i2c->adap = rpx_ops;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &pdev->dev;
- if (i2c_8xx_add_bus(&rpx_ops) < 0) {
+ if ((result = i2c_8xx_add_bus(&rpx_ops) < 0)) {
printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n");
- return -ENODEV;
+ kfree(i2c);
}
+ return result;
+}
+
+
+static int i2c_rpx_remove(struct device *device)
+{
+ struct m8xx_i2c *i2c = dev_get_drvdata(device);
+
+ i2c_8xx_del_bus(&i2c->adap);
+ dev_set_drvdata(device, NULL);
+
+ kfree(i2c);
return 0;
}
-void __exit i2c_rpx_exit(void)
+
+/* Structure for a device driver */
+static struct device_driver i2c_rpx_driver = {
+ .name = "fsl-i2c-cpm",
+ .bus = &platform_bus_type,
+ .probe = i2c_rpx_probe,
+ .remove = i2c_rpx_remove,
+};
+
+static int __init i2c_rpx_init(void)
{
- i2c_8xx_del_bus(&rpx_ops);
+ return driver_register(&i2c_rpx_driver);
}
-MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
+static void __exit i2c_rpx_exit(void)
+{
+ driver_unregister(&i2c_rpx_driver);
+}
module_init(i2c_rpx_init);
module_exit(i2c_rpx_exit);
+
+MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
diff --git a/include/linux/i2c-algo-8xx.h b/include/linux/i2c-algo-8xx.h
new file mode 100644
index 0000000..a644512
--- /dev/null
+++ b/include/linux/i2c-algo-8xx.h
@@ -0,0 +1,29 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-algo-8xx.h i2c driver algorithms for MPX8XX CPM */
+/* ------------------------------------------------------------------------- */
+
+/* $Id$ */
+
+#ifndef I2C_ALGO_8XX_H
+#define I2C_ALGO_8XX_H
+
+#include <linux/i2c.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+struct i2c_algo_8xx_data {
+ uint dp_addr;
+ int reloc;
+ int irq;
+ i2c8xx_t *i2c;
+ iic_t *iip;
+ cpm8xx_t *cp;
+
+ u_char temp[513];
+};
+
+extern int i2c_8xx_add_bus(struct i2c_adapter *);
+extern int i2c_8xx_del_bus(struct i2c_adapter *);
+
+#endif /* I2C_ALGO_8XX_H */
+
--
Sincerely, Vitaly
^ permalink raw reply related
* PTE entries
From: Siva Prasad @ 2007-04-20 4:34 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 266 bytes --]
Hi,
Where exactly the PTE are setup for any given new user program?
In other words, if you are trying to execute a user level program,
kernel needs to load it and setup PTEs for that program. Where does
kernel do it?
Thanks
Siva
[-- Attachment #2: Type: text/html, Size: 2357 bytes --]
^ permalink raw reply
* [PATCH] Fix the -S to modify the totalsize properly.
From: Jerry Van Baren @ 2007-04-20 2:22 UTC (permalink / raw)
To: linuxppc-dev, jdl, u-boot-users
With the last improvement to pad out the blob, I broke the blob
header totalsize adjustment. The adjustment was moved up in the
code before the memory image of the blob is created.
Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
---
Hi Jon,
This fixes my header totalsize screwup. Until this is applied, the -S
adds padding but is not effective.
My apologies,
gvb
flattree.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/flattree.c b/flattree.c
index 913b02f..b54f7ef 100644
--- a/flattree.c
+++ b/flattree.c
@@ -353,6 +353,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
struct data dtbuf = empty_data;
struct data strbuf = empty_data;
struct boot_param_header bph;
+ int padlen;
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
if (version_table[i].version == version)
@@ -371,6 +372,19 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
boot_cpuid_phys);
/*
+ * If the user asked for more space than is used, adjust the totalsize.
+ */
+ padlen = minsize - be32_to_cpu(bph.totalsize);
+ if (padlen > 0) {
+ bph.totalsize = cpu_to_be32(minsize);
+ } else {
+ if ((minsize > 0) && (quiet < 1))
+ fprintf(stderr,
+ "Warning: blob size %d >= minimum size %d\n",
+ be32_to_cpu(bph.totalsize), minsize);
+ }
+
+ /*
* Assemble the blob: start with the header, add with alignment
* the reserve buffer, add the reserve map terminating zeroes,
* the device tree itself, and finally the strings.
@@ -385,18 +399,9 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
/*
* If the user asked for more space than is used, pad out the blob.
*/
- if (minsize > 0) {
- int padlen = minsize - be32_to_cpu(bph.totalsize);
-
- if (padlen > 0) {
- blob = data_append_zeroes(blob, padlen);
- bph.totalsize = cpu_to_be32(minsize);
- } else {
- if (quiet < 1)
- fprintf(stderr,
- "Warning: blob size %d >= minimum size %d\n",
- be32_to_cpu(bph.totalsize), minsize);
- }
+ if (padlen > 0) {
+ blob = data_append_zeroes(blob, padlen);
+ bph.totalsize = cpu_to_be32(minsize);
}
fwrite(blob.val, blob.len, 1, f);
--
1.4.4.4
^ permalink raw reply related
* Re: [PATCH] powerpc: save trap number in bad_stack
From: Michael Ellerman @ 2007-04-20 2:18 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Olof Johansson, linuxppc-dev, paulus, anton
In-Reply-To: <1177024678.7286.23.camel@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 2136 bytes --]
On Fri, 2007-04-20 at 09:17 +1000, Benjamin Herrenschmidt wrote:
> On Mon, 2007-04-16 at 01:23 -0500, Olof Johansson wrote:
> > Save the trap number in the case of getting a bad stack in an exception
> > handler. It is sometimes useful to know what exception it was that caused
> > this to happen. Without this, no trap is reported.
> >
> >
> > Signed-off-by: Olof Johansson <olof@lixom.net>
> >
> > Index: linux-2.6/arch/powerpc/kernel/asm-offsets.c
> > ===================================================================
> > --- linux-2.6.orig/arch/powerpc/kernel/asm-offsets.c
> > +++ linux-2.6/arch/powerpc/kernel/asm-offsets.c
> > @@ -139,6 +139,7 @@ int main(void)
> > DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
> > DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
> > DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
> > + DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
> >
> > DEFINE(SLBSHADOW_STACKVSID,
> > offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
> > Index: linux-2.6/include/asm-powerpc/paca.h
> > ===================================================================
> > --- linux-2.6.orig/include/asm-powerpc/paca.h
> > +++ linux-2.6/include/asm-powerpc/paca.h
> > @@ -81,6 +81,8 @@ struct paca_struct {
> > u64 exslb[10]; /* used for SLB/segment table misses
> > * on the linear mapping */
> >
> > + u64 trap_save; /* Used when bad stack is encountered */
>
> Can you put it elsewhere in the PACA (around less frequently used
> bits) ? This is a pretty hot area of the PACA...
It's only set in the bad_stack case though.
You should put it after cpu_start, there's a bit hole there, and
trap_save is readonly during normal operation, so it shouldn't be a
performance hit.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Guide to porting to an MPC82xx or any PPC for that mater
From: Hunter Cobbs @ 2007-04-20 2:15 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 999 bytes --]
Is there anywhere I can turn to help me figure out how to at least get a
serial console running on SCC1 from an MPC8247 in Linux 2.6.(14+) ?
Our current version of uboot puts data out on SCC1 quite well and I can
compile and load a 2.6 kernel. I run into a problem following boot where no
more data comes over the SCC1.
I have used the jtag port to get a register dump during uboot and one as
soon as it's obvious no data is coming from scc1. None of the registers
pertaining to the serial configuration are different.
I've been digging around in the kernel and the default SCC1 hookup bitmasks
are exactly the same as our working 2.4 kernel. I just can't seem to make
linux use SCC1 as a serial console. I even tried consoel=ttyCPM[0..5] to
attempt to force it out a SCC1.
Since this is my first attempt at porting (or creating a BSP for that
matter), I'm sure I'm overlooking something exceedingly easy. I just need
something other than raw kernel code to help me out.
--
Hunter Cobbs
[-- Attachment #2: Type: text/html, Size: 1102 bytes --]
^ permalink raw reply
* Re: RFC: powerpc: Start splitting up mmu.h by MMU type
From: David Gibson @ 2007-04-20 0:56 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <CE8B1295-3D26-4495-99B9-3448E3CE69D9@kernel.crashing.org>
On Thu, Apr 19, 2007 at 07:11:07AM -0500, Kumar Gala wrote:
>
> On Apr 19, 2007, at 1:54 AM, David Gibson wrote:
>
> > This patch makes a start to sorting out the tangled mess of MMU
> > related header files in asm-powerpc, and weaning arch/powerpc off the
> > remaining asm-ppc headers it uses.
> >
> > Specifically it splits the ppc64 specific (or more strictly, the
> > 64-bit hash table specific) parts of asm-powerpc/mmu.h into its own
> > file, asm-powerpc/mmu-hash64/mmu.h. Similarly, PowerPC 44x
> > definitions are taken from asm-ppc/mmu.h, trimmed down for use in
> > arch/powerpc and place in their own file, asm-powerpc/mmu-44x/mmu.h.
> >
> > mmu.h definitions for other 32-bit MMU types remain in asm-ppc/mmu.h
> > for now, but should be likewise split into their own files.
>
> I asked this before, but why the need for a separate directory per
> mmu type? why not just include/asm-powerpc/mmu-44x.h?
Because I have further patches in the works that add MMU specific
versions of tlbflush.h, pgtable.h and so forth to the same
directories.
I'm not wedded to the idea, but it seemed like a reasonable way to
organize things.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 9/10] Add device tree for Ebony
From: David Gibson @ 2007-04-20 0:08 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1177006172.14328.13.camel@ld0161-tx32>
On Thu, Apr 19, 2007 at 01:09:32PM -0500, Jon Loeliger wrote:
> On Wed, 2007-04-18 at 01:36, David Gibson wrote:
> > Add a device tree for the Ebony evaluation board (440GP based). This
> > tree is not complete or finalized. This tree needs a very recent
> > version of dtc to process.
>
> "recent" will get stale without absolute reference here.
> In fact, -V 16 is "old" now even. :-)
Heh, yes.. Comment adjusted.
> > --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> > +++ working-2.6/arch/powerpc/boot/dts/ebony.dts 2007-03-21 13:23:48.000000000 +1100
> > @@ -0,0 +1,295 @@
> > +/*
> > + * Device Tree Source for IBM Ebony
> > + *
> > + * Copyright (c) 2006, 2007 IBM Corp.
> > + * Josh Boyer <jwboyer@linux.vnet.ibm.com>, David Gibson <dwg@au1.ibm.com>
> > + *
> > + * FIXME: Draft only!
>
> Hrm.
Yes..?
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without
> > + * any warranty of any kind, whether express or implied.
> > + *
> > + * To build:
> > + * dtc -I dts -O asm -o ebony.S -b 0 -V 16 ebony.dts
> > + * dtc -I dts -O dtb -o ebony.dtb -b 0 -V 16 ebony.dts
>
> Really Version 16? Can we just default to latest version
> by not specifying the -V arg at all?
Ah, yes, version reference removed.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [RFC/PATCH] Change 440GP platform to ppc440
From: David Gibson @ 2007-04-20 0:02 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <1177019006.3877.36.camel@zod.rchland.ibm.com>
On Thu, Apr 19, 2007 at 04:43:26PM -0500, Josh Boyer wrote:
> On Thu, 2007-04-19 at 16:16 -0500, Kumar Gala wrote:
> > I don't see any reason the 440GP should its own platform. Posting this to
> > see if anyone thinks otherwise.
>
> Seems fine to me.
Likewise to me.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [U-Boot-Users] [PATCH: dtc take 2] Assemble the blob in memory before writing it out.
From: Jerry Van Baren @ 2007-04-19 23:45 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org, u-boot-users
In-Reply-To: <E1HefA8-0008Tl-VA@jdl.com>
Jon Loeliger wrote:
> So, like, the other day Jerry Van Baren mumbled:
>> Patch #2 and #3...
>> [PATCH dtc take 3] Fix reserve map output for asm format.
>> Tue, 17 Apr 2007 18:14:41 -0400
>> [PATCH: dtc take 2] Assemble the blob in memory before writing it out.
>> Wed, 18 Apr 2007 21:59:51 -0400
>
> [snip]
>
>> AAAARGH! Sorry, I see I left a debug statement in flattree.c around
>> line 390:
>
>> Your option:
>> 1) Take the last two patches as is and remove the fprintf yourself
>
>
> Applied #2 and #3 listed above.
> Cleaned out the debug fprintf().
>
> Thanks,
> jdl
Oh oh, does NOT look good. I lost the rewrite of the header size with
the new, bigger size when -S is specified.
Ahh, I think I see the problem, sloppy programming bites me again.
Modifying "bph.totalsize" worked before I changed to the struct data
blob. Grrrr. I need to figure out the padding and apply it to the bph
before starting the blob assembly. Before the line:
blob = data_append_data(blob, &bph, sizeof(bph));
Patch will take a bit because I have a meeting to go to :-(.
sorry,
gvb
^ permalink raw reply
* Re: [PATCH] powerpc: save trap number in bad_stack
From: Benjamin Herrenschmidt @ 2007-04-19 23:17 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, paulus, anton
In-Reply-To: <20070416062347.GA20196@lixom.net>
On Mon, 2007-04-16 at 01:23 -0500, Olof Johansson wrote:
> Save the trap number in the case of getting a bad stack in an exception
> handler. It is sometimes useful to know what exception it was that caused
> this to happen. Without this, no trap is reported.
>
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
>
> Index: linux-2.6/arch/powerpc/kernel/asm-offsets.c
> ===================================================================
> --- linux-2.6.orig/arch/powerpc/kernel/asm-offsets.c
> +++ linux-2.6/arch/powerpc/kernel/asm-offsets.c
> @@ -139,6 +139,7 @@ int main(void)
> DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
> DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
> DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
> + DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
>
> DEFINE(SLBSHADOW_STACKVSID,
> offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
> Index: linux-2.6/include/asm-powerpc/paca.h
> ===================================================================
> --- linux-2.6.orig/include/asm-powerpc/paca.h
> +++ linux-2.6/include/asm-powerpc/paca.h
> @@ -81,6 +81,8 @@ struct paca_struct {
> u64 exslb[10]; /* used for SLB/segment table misses
> * on the linear mapping */
>
> + u64 trap_save; /* Used when bad stack is encountered */
Can you put it elsewhere in the PACA (around less frequently used
bits) ? This is a pretty hot area of the PACA...
Ben.
^ permalink raw reply
* Re: [U-Boot-Users] [PATCH: dtc take 2] Assemble the blob in memory before writing it out.
From: Jon Loeliger @ 2007-04-19 22:31 UTC (permalink / raw)
To: Jerry Van Baren; +Cc: linuxppc-dev@ozlabs.org, u-boot-users
In-Reply-To: <4627B9C7.8010800@smiths-aerospace.com>
So, like, the other day Jerry Van Baren mumbled:
>
> Patch #2 and #3...
> [PATCH dtc take 3] Fix reserve map output for asm format.
> Tue, 17 Apr 2007 18:14:41 -0400
> [PATCH: dtc take 2] Assemble the blob in memory before writing it out.
> Wed, 18 Apr 2007 21:59:51 -0400
[snip]
> AAAARGH! Sorry, I see I left a debug statement in flattree.c around
> line 390:
> Your option:
> 1) Take the last two patches as is and remove the fprintf yourself
Applied #2 and #3 listed above.
Cleaned out the debug fprintf().
Thanks,
jdl
^ permalink raw reply
* Re: [PATCH dtc] Add -o <output file> to the usage message.
From: Jon Loeliger @ 2007-04-19 22:28 UTC (permalink / raw)
To: Jerry Van Baren; +Cc: linuxppc-dev
In-Reply-To: <20070414221647.GB23870@dellserver.lan>
So, like, the other day Jerry Van Baren mumbled:
>
> Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
> ---
>
> It turns out -o <file> was there all along, just not in the usage. :-)
Applied.
Thanks,
jdl
^ 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